Change layer of block *definition*?

It doesn’t work on block instances, it works on block definitions - and it does that one definition at a time. The problem seems to be when the block definition contains block instance objects.

I created this a while ago with the help of @DavidLeon:

def block_dissect(block_id=Rhino.Geometry.InstanceDefinitionGeometry, parent_layer = "Root"):
    #check if its a block
    block_obj = rs.coercerhinoobject(block_id)
    
    
    # if its not a block, add to document 
    if type(block_obj) is not Rhino.DocObjects.InstanceObject: 
        #print "{0} is not a block".format(block_obj)
        rs.AddLayer(name=parent_layer, color=None, visible=True, locked=False, parent=None)
        rs.ObjectLayer(block_obj, parent_layer)
        
    #if its a block, get sub objects, and recursively dissect
    if type(block_obj) is Rhino.DocObjects.InstanceObject:
        #print "{0} is a block".format(block_obj)
        block_name = rs.BlockInstanceName(block_id)
        
        #nake new parent layer
        parent_layer = parent_layer + "::" + block_name
        rs.AddLayer(name=parent_layer, color=None, visible=True, locked=False, parent=None)
        sub_objs = rs.BlockObjects(block_name)
        for obj in sub_objs:
            block_dissect(obj, parent_layer)

def initiate_dissection():
    block_id = [obj for obj in rs.AllObjects() if rs.ObjectType(obj) == rs.filter.instance]
    block_dissect(block_id[0])

Hmmm I’ve missed that part :blush: does it need to be definitions?

Yes, that was the point… The idea was that you are stuck with a block definition that is related to the layers of the original objects; there are no longer objects on those layers, and you want to purge them. I thought it might be simple to just get the definitions and change all the layers of the objects in the definition. That works file for one level, but somehow when it find a nested block, one or more of of the objects is a block instance object (not a definition), and the layer change fails there. Haven’t figured out why yet - and I guess I’m going to give up on it for now.

I dredged these up, dunno if any gets at what being sought here…

MoveBlockObjectstoLayer.py (1.3 KB)

MoveBlockObjectstoInstanceLayer.py (907 Bytes)

-Pascal

2 Likes

I was doing this out of curiosity mostly, I don’t need it personally, just trying to understand where I went wrong in my reasoning.

Hi Mitch

As far as I understand (not much, actually …), a RhinoObject cannot be an InstanceDefinition, only
an InstanceObject …

I edited your script a little.
I think it works on your file, but I may be wrong …
You might like to give it a try.

HTH

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

#Maybe working for nested blocks...

def NukeAllBlockDefs(b_def,layer_index):
    block_objs=b_def.GetObjects()
    for block_obj in block_objs:
        print type(block_obj)
#       if isinstance(block_obj,Rhino.DocObjects.InstanceDefinition):
#           #recurse
#           NukeAllBlockDefs(block_obj,layer_index)
        if isinstance(block_obj,Rhino.DocObjects.InstanceObject):
            indef=block_obj.InstanceDefinition
            NukeAllBlockDefs(indef,layer_index)
        else:
            block_obj.Attributes.LayerIndex=layer_index
            block_obj.CommitChanges()

b_defs=sc.doc.InstanceDefinitions
if b_defs:
    msg="Layer to send all block objects to"
    dest_layer=rs.GetLayer(msg,show_new_button=True)
    if dest_layer:
        layers=sc.doc.Layers
        layer_index=sc.doc.Layers.Find(dest_layer,True)
        for b_def in b_defs: NukeAllBlockDefs(b_def,layer_index)
        sc.doc.Views.Redraw()

Hi Emilio,

No, it doesn’t actually work, for example if you specify the “Block” layer for all the objects, you can see that the nested block remains on Layer 01.

That’s true, but in any case if there was no instance definition passed to the function except the initial one then the part you commented out would never be reached, so it actually doesn’t matter if it is there.

Hmmm.

True … :confused:

I think your script moves all original objects to the desired layer,
but it only move those instances that are nested in other instances.

If you want to change any instance’s layer, I think we need another loop on the definition instances.

I also removed the recursion.
I think that b_defs should already contain any block definition.

This seems to move both objects in the definition and block instances to the desired layer …
Well … as I said … it ‘seems’ … :crossed_fingers:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

#Maybe working for nested blocks...

def NukeAllBlockDefs(b_def,layer_index):
    block_objs=b_def.GetObjects()
    for block_obj in block_objs:
        print type(block_obj)
#       if isinstance(block_obj,Rhino.DocObjects.InstanceDefinition):
#           #recurse
#           NukeAllBlockDefs(block_obj,layer_index)
#       if isinstance(block_obj,Rhino.DocObjects.InstanceObject):
#           indef=block_obj.InstanceDefinition
#           NukeAllBlockDefs(indef,layer_index)
        block_obj.Attributes.LayerIndex=layer_index
        block_obj.CommitChanges()
    instances = b_def.GetReferences( 1 )
    for instance in instances:
        instance.Attributes.LayerIndex=layer_index
        instance.CommitChanges()

b_defs=sc.doc.InstanceDefinitions
if b_defs:
    msg="Layer to send all block objects to"
    dest_layer=rs.GetLayer(msg,show_new_button=True)
    if dest_layer:
        layers=sc.doc.Layers
        layer_index=sc.doc.Layers.Find(dest_layer,True)
        for b_def in b_defs: NukeAllBlockDefs(b_def,layer_index)
        sc.doc.Views.Redraw()

Cheers

1 Like

great script. did what i wanted. i reccomend this to be a part of block manager natively…

2 Likes

Thank You Pascal! That script is a life saver!

1 Like

This script is very useful when working with imported Sketchup Models I found. Wouldn’t mind adding it to Rhino 8 and calling it ChangeLayerInBlocks to match the existing ChangeLayer command.

A moan to add to the pile (of very helpful resources) here. Usage of blocks in rhino is opaque, byzantine and a massive administrative time drain. I have taken to purging them completely from my model because of the maddening amount of work involved in their management (see the inability to delete a layer with a definition, which in itself cannot be deleted as it is nested in another block which must be deleted first etc), which is ridiculous.

Blocks should be the lingua franca of CAD programs and BIM/PLM. Rhino’s block system is some arcane language which takes an age to learn, mostly by trial and error. An Achilles heel in my favourite workhorse programme…

R

2 Likes