Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- Be respectful, on topic and if you see a problem, Flag it.
If you would like to contact our Community Manager personally, feel free to send a private message or an email.
How can I assign a LookUp Table result to variable when both live in an array?
Caleb_Kehoe
Member, HDM Posts: 28 PRO
There's a good chance I'm over complicating this but when I tuck a lookup table inside an array, I'm having issues assigning its resulting value to a variable that lives in the array. This variable would then be used 'globally' to drive a sketch, feature, etc. I've edited the standing Onshape lookup table example below:
<div>FeatureScript 951;</div><div>import(path : "onshape/std/geometry.fs", version : "951.0");</div><div><br></div><div>const oz is ValueWithUnits = 29.5735 * centimeter ^ 3;</div><div>export const sizeTable = {</div><div> "name" : "region",</div><div> "displayName" : "Region",</div><div> "default" : "EU",</div><div> "entries" : {</div><div> "EU" : {</div><div> "name" : "size",</div><div> "displayName" : "Size",</div><div> "default" : "medium",</div><div> "entries" : {</div><div> "small" : 8 * oz,</div><div> "medium" : 12 * oz,</div><div> "large" : 16 * oz</div><div> }</div><div> },</div><div> "US" : {</div><div> "name" : "size",</div><div> "displayName" : "Size",</div><div> "default" : "large",</div><div> "entries" : {</div><div> "medium" : 16 * oz,</div><div> "large" : 32 * oz,</div><div> "supersize" : 64 * oz</div><div> }</div><div> }</div><div> }</div><div> };</div><div><br></div><div>annotation { "Feature Type Name" : "Soda" }</div><div>export const soda = defineFeature(function(context is Context, id is Id, definition is map)</div><div> precondition</div><div> {</div><div> annotation { "Item name" : "", "Item label template" : "#(#inputname) = #inputvalue1", "Driven query" : "query", "UIHint" : ["COLLAPSE_ARRAY_ITEMS", "NO_PREVIEW_PROVIDED"] }</div><div> definition.array_Vars is array;</div><div><br></div><div> for (var arrayVar in definition.array_Vars)</div><div> {</div><div> annotation { "Name" : "Var Name", "Default" : "VAR1", "UIHint" : "SHOW_LABEL" }</div><div> arrayVar.inputname is string;</div><div> annotation { "Name" : "Def Value" }</div><div> isLength(arrayVar.inputvalue1, LENGTH_BOUNDS);</div><div> annotation { "Name" : "Entities", "Filter" : SketchObject.NO, "MaxNumberOfPicks" : 1, "UI Hint" : ["ALWAYS_HIDDEN", "CONTROL_VISIBILITY", "REMEMBER_PREVIOUS_VALUE"] }</div><div> arrayVar.query is Query;</div><div><br></div><div> annotation { "Name" : "Soda size", "Lookup Table" : sizeTable }</div><div> arrayVar.sizeTable is LookupTablePath;</div><div><br></div><div> }</div><div> }</div><div> {</div><div><br></div><div> for (var arrayVar in definition.array_Vars)</div><div> {</div><div> println(arrayVar.sizeTable);</div><div> var selectedRegion = arrayVar.sizeTable.region;</div><div> var selectedSize = arrayVar.sizeTable.size;</div><div> var size = sizeTable</div><div>.entries[selectedRegion]</div><div>.entries[selectedSize];</div><div> println(size);</div><div> setVariable(context, arrayVar.inputname, arrayVar.inputvalue1);</div><div> //setVariable(context, arrayVar.inputname, arrayVar.size);</div><div> }</div><div><br></div><div> });</div>
0
Best Answer
-
Jake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646@Caleb_Kehoe
I think there is a little bit of a disconnect here as far as the architecture of the pipeline itself. The "definition" of a feature is just a map representing the current state of the user input. It is not affected by execution of the feature body. The order of operations here is as follows:- The user makes some change to the dialog.
- The editing logic function is called, with the old state represented as "oldDefinition" and the new state represented as "definition". You can make changes to the definition here and return them.
- The dialog updates to respond to the changes you made with the editing logic.
- The body of the feature is executed (using the current state of the dialog, a.k.a. the definition you returned from the editing logic). Nothing you do in the body of the feature can affect the parameters in the dialog.
The way to go about this is to do your lookup table logic in the editing logic, store it in the READ_ONLY parameter, and use it in the feature body:// in the editing logic - do the lookup to set the READ_ONLY parameter for (var i = 0; ...) { var selectedRegion = definition.array_Vars[i].sizeTable.region; var selectedSize = ...; var size = sizeTable.entries[selectedRegion].entries[selectedSize]; definition.array_Vars[i].inputvalue1 = size; } // in the feature body - use the parameter you set via the editing logic to set the global variable for (arrayVar in definition.array_Vars) { setVariable(context, arrayVar.inputName, arrayVar.inputvalue1 * 2); }
I'm sure that @kevin_o_toole_1 or @ilya_baran would probably like to chime in about how you should probably do the full processing in both of the places (a helper function would make this easy without duplicating code), because this may break down in the face of configurations, as (I think) changes to a configuration do not cause editing logic to be called.
Jake Rosenfeld - Modeling Team5
Answers
Can you share a link or what you are trying to do?
IR for AS/NZS 1100
I don't quite understand your question. When you say "globally" are you just trying to use that value within the scope of this feature? Or are you trying to make it so that after a user runs your feature, they have access to that value in subsequent features of the Part Studio?
Also, it is very hard to read your code blocks. When I paste them in, they paste just fine. Not sure what the problem is, but here is a gif of me pasting in your code:
And how the code should look when pasted in:
Are you pasting the code into another program before pasting it in here? You should be able to just start a new "code" block and then paste the whole feature studio into it. Let me know your workflow and we can figure out where the trouble is.
Yes, I use the term 'globally' to mean that I can use this created variable in the Part Studio (in all subsequent features). In addition, it would be very nice to display the value within the feature (before the feature is exited) so that the user can see the resulting value associated with the lookup table options. In simplest form, I'm trying to create a 'driven' text box/display box for an assigned variable value - in this case all happening in an array.
To do this, I would use editing logic (as discussed in the other thread) to change the value of the driven parameter in the dialog, then use setVariable() in the body of your feature to set the global variable. If you want that 'driven' parameter to not be editable by the user, you can use the 'READ_ONLY' UIHint.
I tried a couple variations on that ELF without any luck as well. i.e.
I think there is a little bit of a disconnect here as far as the architecture of the pipeline itself. The "definition" of a feature is just a map representing the current state of the user input. It is not affected by execution of the feature body. The order of operations here is as follows:
- The user makes some change to the dialog.
- The editing logic function is called, with the old state represented as "oldDefinition" and the new state represented as "definition". You can make changes to the definition here and return them.
- The dialog updates to respond to the changes you made with the editing logic.
- The body of the feature is executed (using the current state of the dialog, a.k.a. the definition you returned from the editing logic). Nothing you do in the body of the feature can affect the parameters in the dialog.
So, there is less magic going on here than you think. Setting a variable "size" in your feature body does not do anything to the definition, it's just part of the execution of the feature. The reason what you're doing is not working is because "definition.size" is not something that is specified in the precondition, so it does not exist during the editing logic stage.The way to go about this is to do your lookup table logic in the editing logic, store it in the READ_ONLY parameter, and use it in the feature body:
I'm sure that @kevin_o_toole_1 or @ilya_baran would probably like to chime in about how you should probably do the full processing in both of the places (a helper function would make this easy without duplicating code), because this may break down in the face of configurations, as (I think) changes to a configuration do not cause editing logic to be called.
Yep, generally the recommendation is to not use configurable parameters to drive editing logic.
For example, let's say definition.input is used in editing logic to set the value of definition.computedInput whenever definition.input changes. If someone configures definition.input, then changes the configuration, the editing logic won't run, even though definition.input has changed.
This isn't an issue if no one configures your input parameter. So, one solution is just to make sure the driving parameter is not configurable. You can do this by adding "UIHint" : "UNCONFIGURABLE" to the parameter annotation.
In your case, array parameters are currently not configurable anyway, so there's no issue at all! If you want to really future-proof your feature you can add "UIHint" : "UNCONFIGURABLE" to the inputname parameter, to ensure configuring is blocked even when we implement the ability to configure array parameters.