Grasshopper/Python - Replace geometry while keeping GUID

Hello everyone,

I am trying to write my own version of “Replace” component, which could be found in LegoPod for Rhino 7. Now I want to have my own python-based component, that would do the same thing, in Rhino 8.

The idea is that I would like to replace geometry in an object, while keeping its GUID and attributes etc.

Here is how far I have got, but it doesn’t work:

import Rhino as rc
import scriptcontext as sc
import rhinoscriptsyntax as rs

sc.doc = rc.RhinoDoc.ActiveDoc
rs.EnableRedraw(False)
objecttable = sc.doc.Objects

if a==1:
    for object_id in IDs:
        objecttable.Replace(object_id,Geo)      

rs. EnableRedraw(True)
sc.doc = ghdoc

Both IDs and Geo are List Access. I would like to be able to connect tree structure of both IDs and Geometry.

Could someone please help?

Best,
P

PS: Greasshopper file for Rhino 8:
Replace in Python.gh (6.4 KB)

Did you write Greasshopper on purpose?

sorry, fixed

1 Like

Why not just use the Model Object component in Rhino 8? You can replace the geometry and keep all the other attributes in place.

1 Like

Hey,

Thank you for quick response.

I agree, but I found it a bit difficult to get into at first. How do you push the changes? You need to plug in the Cache component at the end for it to apply the changes in Rhino?

Anyways, I am also a bit afraid that it changes some of the attributes that I am not aware of - see here:
20250624_133555_Rhino_cSJHDnDCwl

Notice that the “Display Mode” override is going back to “By View” when I use your logic. When using “Replace”, it stays as is - here I am really sure that I am replacing only geometry. It seems to me like a cleaner solution. (side note: In the past I had similar problems when baking with Elefront, the layers changed colors, print width etc to default, so I got a bit paranoid.)

Lastly, I would like to know how to make it in Python just for learning purposes. I know that I am almost there but I miss something…

Is that a gif? Anyway, I cannot see anything. Can you post that Grasshopper definition?

yes it is - you can play it by clicking the small icon on the bottom right.

Here is the file:
Replace in Python_with Legopod and model cache.gh (8.7 KB)

Thank you for looking into it.

I see the animation play and I well understand the button but the resolution is so poor I cannot see anything. The resolution might be automatically lowered…

Can you also share the Rhino file with an object that has all the attributes you want?

Got it.

Here are both files:
Replace in Python_with Legopod and model cache.gh (8.6 KB)
Replace in Python_with Legopod and model cache.gh.3dm (158.2 KB)

I checked all possible overrides, including Vray (like displacement modifier etc.)

When I use “Model Object - Cache” - then “Display Mode” goes from "Ghosted" back to “By View
When I use “LegoPod - Replace” - then “Display Mode” stays on "Ghosted" (no change)

Otherwise, so far, everything stays as it was. Only geometry changes. So thumbs up.

But regardless of the “Cache” solution, can we go back to the Python script? Any ideas how to make that one work?

Why doesn’t the display mode output show ‘Ghosted’ when it is set in Rhino?

Start your scripts with a query model objects and end them with a content cache. If you have some logic you can also automate the pushing/purging, etc..


push with display mode.gh (17.4 KB)

Regarding display modes, I suspect that since display modes are set per viewport, and grasshopper doesnt know what the current viewport is, it would treat it as the majority of display modes (1 is ghosted and 3 are by view so the display mode is by view…or something like that). If you set the display mode in grasshopper and push to rhino then you can see it be ghosted every viewport and in each subsequent query the display mode is still ghosted.

1st query: Queried object display mode is ‘By View’

2nd query: Queried object display mode is ‘Ghosted’

Sorry I don’t have any scripting skills so I won’t be able to help you there.

2 Likes

It makes a lot of sense - well done with detective work!

But that is why it is yet another reason I can’t use Grasshopper “Model Object - Cache”. I do a lot of custom object view overrides in layouts/details.

I just checked two solutions against Layout/Detail Display overrides.
And again:
When I use “Model Object - Cache ” - then “Display Mode ” goes from "Assigned custom (Ghosted etc)" back to “By View ” in all details
When I use “LegoPod - Replace ” - then “Display Mode ” stays on "Assigned custom (Ghosted etc)" (no change)

So “LegoPod” comes on top.

Files are here:
Replace in Python_with Legopod and model cache.gh.3dm (124.2 KB)
Replace in Python_with Legopod and model cache.gh (8.6 KB)

1 Like

@kike it would be nice if we could have a viewport parameter in the display mode setting. I had encountered a similar problem and since then I have changed my approach to not using display modes and rather use a custom colour library that uses the user attribute text to decide what display properties of the objects have to be (material, display colour, etc etc). In regular rhino workflow the display mode is super useful to have a certain parts of the model be wireframe/ghosted/arctic and have that be different throughout different viewports.

2 Likes

That is a great help! Thank you for contributing!

1 Like

I second that. I use mostly 3d views in details, so possibility of adding a “per view override” for objects is such a blessing.

Hello again.
Anyone could help with the Python?

I managed to (successfully this time) to pass the script through the Claude.ai, and this is what I got.
It updates the geometry, has a “failsafe” so the script is executed only once (Grasshopper executed the script twice - on button push down and button push up).
All overrides (including display mode) stay the same.

import Rhino as rc
import scriptcontext as sc
import rhinoscriptsyntax as rs
import System

sc.doc = rc.RhinoDoc.ActiveDoc
rs.EnableRedraw(False)

# Create a persistent variable to track execution
if 'executed_state' not in globals():
    executed_state = False

if Replace == 1 and not executed_state:
    executed_state = True
    
    for i, object_id in enumerate(IDs):
        # Convert string ID to System.Guid if needed
        if isinstance(object_id, str):
            guid_id = System.Guid(object_id)
        else:
            guid_id = object_id
        
        # Get the geometry for this iteration
        if isinstance(Geo, list):
            geometry = Geo[i] if i < len(Geo) else Geo[0]
        else:
            geometry = Geo
        
        # Replace the object's geometry
        sc.doc.Objects.Replace(guid_id, geometry)

elif Replace == 0:
    executed_state = False

rs.EnableRedraw(True)
sc.doc = ghdoc

Replace in Python.gh (6.6 KB)