Model Objects - Set User Text (Without Content Cache)

EDIT:
Incorrectly started this thread as a bug report…

Please see post below down here for the corrected issue:

Original Post

Hi all,

In 8.9 SR the Query Model Objects component is failing to correctly return User Text values unless the Model Object output is first cast to a GUID component.

Please see the attached files to reproduce the issue and a video demonstration.
(Pay attention to the “Incorrect Values From GH Doc” Panel(s)

Graph Space:

I was pulling my hair out for two days thinking I was going crazy that my “sorting values” weren’t working correctly until I finally traced back the issue haha

Almost all of our scripts rely heavily on getting real-time user text values so we will put a GUID component downstream of the Query Model Objects component for now as a temp fix.

Thanks for your help!

20240613_GH_User_Text_Get_Bug_Report_01b.gh (7.8 KB)

3 Likes

Thanks for the video.

1 Like

Can you post your file as well? Thanks

Hi @Japhy , The Rhino file you mean?

Yeah, i can see what’s going on in your video but a my tests aren’t replicating. The model objects aren’t internalizing.

Okay sorry @Japhy, I dug around more and realized that in a different part of the script I had a Python component setting user text values which worked great for the updates being live in Rhino but I was not calling a refresh of the GH script, thus the Query components weren’t getting the latest values (unless a GUID component was added? which confuses me… I guess that’s because it’s then calling directly to that GUID object vs passing through a Model Object?)

I believe this was the issue why the UserText values weren’t being updated from the GH components dynamically.

Sorry for misleading you all on that, it now appears to be working just fine (the grasshopper components, not my script yet)



I wish there was a way (or perhaps there is) to refresh specific components or upstream components, I was able to refresh “downstream” logic by calling ExpireSolution(False) but unsure how to update the upstream Query Model Objects component so that the Model Objects coming out have the proper User Text values.



@AndyPayne and @kike or maybe this is a @scottd question, what method is being called within the “Synchronize” menu option of the Query Model Object component?

image

My question is, if I set UserText from a Python script how do I ensure that the referenced Model Objects from the Query components are always getting the latest and greatest attribute values without carpet bombing the whole script in a recompute?

Here’s more info about my script specifically and the GH context surrounding it:

-Historically I’ve been setting User Text immediately after a Query and then continuing with logic after that (the logic downstream relies on the User Text values being dynamic)

-However, in a large definition Caching at the start of a script starts to slow down everything over time where as directly calling a SetUserText definition is very fast.

Is there a way to set the User Text without the Content Cache but still get downstream Model Objects to have the correct, updated values without “carpet bombing” the larger script component refresh states?

Thanks for your help!

Attached is the simplest example I could come up with to illustrate this. Obviously a Cache at this scale is speedy but when I replicate the logic more than 10 times it gets slower of course.

I thought about using a data tree to have only 1 Query for “everything” and 1 Cache for “everything” but the problem with that is then it fires downstream logic if only 1 “piece” of said Query or Cache is modified.

Example if I am editing a layer called “Shapes” but the Query Model Objects component has layers “Shapes, Tools, Paths, Etc.” in it, then all the downstream logic relying on Tools Paths Etc also gets fired which is a deal breaker.

Any ideas are greatly appreciated! Thank you!

Graph Space:

Model Space:

20240614_Set_User_Text_01a.gh (39.4 KB)
20240614_Set_User_Text_01a.3dm (90.0 KB)

Thank you! :dizzy:

1 Like

This is a bit confusing in that the Rhino Objects with the python components. These components point straight at the Rhino.Object within ActiveDoc.

The test here:

Is testing the ObjectModel element within Grasshopper.

I think the best way to explain it is. The Content Cache Pull (Result) will sync all the attributes and ID from the Rhino.object and transfer that information to the Model object. But, these are not the same object. So the Python components are only updating the Rhino.Object. The ModelObjects do not change. An additional Content Cache pull would be needed to sync the model object to the Rhino.object updates.

Although I guess I would like to ask what is the goal here? To measure performance of different ways to exchange objects and attributes between Rhino and Grasshopper?

1 Like

Thanks for your response @scottd !

There are 3 total moving parts in this, an Eto UI, a Grasshopper Script, and a Rhino Object.

  1. Eto UI is responsible for calling a Python Script that sets the Rhino.Object UserText value when a button is pressed. For the sake of simplicity lets say the Eto button (+) or (-) increments or decrements an integer value that is stored in the Rhino.Object UserText.

  2. Now, in the Grasshopper script, we are getting the Model Objects containing said Rhino.Object and sorting the Model Object list off of this value and calling some “visual graphics” stuff like Custom Preview to showcase the change to the objects.

  3. This works fine… but, as you point out, the Model Object is still seeing the old outdated values prior to the Eto UI interaction. As you also point out, using a Content Cache will update the Model Object with the latest values.

  4. The only caveat is that this introduces an undesirable latency because when the Content Cache is updated, it triggers downstream logic since that Rhino.Object UserText was updated in the Cache now, thus telling the ModelObject to expire and run downstream logic on the updated ModelObject. (Which is typically what you want of course) but when there is ALOT of downstream logic, having to always push the Cache for a UserText update really gets slow over time.

  5. So I guess the question is… is it possible to target just the UserText of the MO to update that to the current RhinoObjects post UI interaction WITHOUT triggering the script to execute downstream but ensuring the Model Object is “current/up to date” (with the latest user text post UI interaction)

I realize what I am asking for may be at odds with what the Cache is actually doing which is exactly what I want (to keep the MO updated with the latest changes to UserText) but maybe it’s just a question of optimization/speed/performance and not really having anything to do with “how to get around without using it” in this case…

1 Like

Okay I figured out a method to achieve this by using the targeted expiration of a single scripting component and then feeding the output into the Set User Text component to attach the updated values to the Model Objects.

The Python script in this snip simply gets expired by the Eto UI Interaction, causing it to get the latest User Text values by rerunning the script and then that gets passed on to the Model Object.

image

Targeted Expiration Code from UI Script:

for obj in gh.Instances.ActiveCanvas.Document.Objects:
    if obj.NickName == "SUT":
        print("Valid Nickname Match Found")
        obj.ExpireSolution(True)

This means I can now update the Model Object User Text “mid stream” without needing to use a Query or Cache component.

I realize that this is a bit precarious in that any Query component else where attempting to Query the same Model Objects would not have the updated results…

The updated results are only carried “directly” downstream via the Wire but in my case this is what I want, to have all the Model Objects exist only in GH/Data Space until a final Content Cache operation at the very end of the logic.

This is the most performant for my needs.

Thanks for all your help @scottd !