Let "SelColor" command select objects inside blocks

And all other “Sel*” commands - it would be useful to have them also select objects inside blocks :slight_smile:

pls explain how you would use this. The way I see it, the block instance is the top level item and selection tools should only look at that.

I see what you mean, but I think that blocks shouldn’t block (no pun intended) “introspectability” of the model. If you need to check how many “purple elements” you have in the model (bad example, rather block types or lines of specific length etc.) including those inside the blocks (and blocks inside the blocks) you’d need to run SelColor command in the model and inside every block.

Perhaps a family of commands (SelColorInBlocks, SelMaterialNameInBlocks etc.) would make sense?

I think that part of this idea has been addressed already with the new features added to Rhino 8 WIP like changing object attributes (layer, color) from outside of the blocks already.

Are there any methods in RhinoCommon/rhinoscript to select block sub-objects?rhinoscriptsyntax.GetObject() and SelectedObjects() functions don’t seem to work with block sub-objects. Running “What” on a selected sub-object only retrieves information about the containing block.


… ok i can see the point:
subselecting parts of a block is possible with a mouseclick.
so it would be consistent to allow selColor to do the same …

a workaround of course is to _explode the blocks - maybe in a copied document ?
or undo after counting ?

there is also
And Blockmanager will also show the number of instances …

1 Like

thanks, do you know if it’s possible to subselect parts of block via rhinoscipt/rhinocommon as well?

I don’t think that it will “scale” - on my model it took about 3 seconds to explode all of them and over 10 seconds to undo - not counting nested blocks. Also if you forget to undo it…

my guess / Did you try

Thanks, will try. I thought this was for faces of polysurfaces, meshes etc.

I think you should do that through InstanceDefinition.GetObjects Method

thanks both, @Tom_P this led me to RhinoObject. GetSelectedSubObjects() method, which seems to retrieve “ComponentIndex”, which I hope can be used to modify object attributes in multiple block instances at once.

I still think that a visual feedback using existing Sel* commands would be useful, as sometimes you want to check where sub-objects are, visually filter some of them out and then apply changes.

import rhinoscriptsyntax as rs

b = rs.coercerhinoobject("ff2d1ab3-814f-41d7-98da-d29ef358d9ad")
c = b.GetSelectedSubObjects()

check something similar to this:

rh_obj.SelectSubObject(Rhino.Geometry.ComponentIndex( Rhino.Geometry.ComponentIndexType.InstanceDefinitionPart,1),True,True,True)
1 Like

Brilliant, thanks a lot, that did work!

I’m really curious if this will work for nested blocks :star_struck:

I will try something like this for selcolor:

  • iterate through all objects in document
  • filter out all that don’t match selected displaycolor
  • find ComponentIndex for objects inside blocks and select them with SelectSubObject

I can’t seem to obtain guid of a block of a selected sub-object. The example above worked, because I’ve hard-coded block’s guid, but I can’t seem to find anywhere a function that accepts selected subobjects.

EDIT: sorry, it’s solved now I think. Instead of using guid by iterating over all blocks and checking if a subobject is selected:

for object in sc.doc.Objects:
    if type(object) == Rhino.DocObjects.InstanceObject:

“SelColorInBlock” seems to work now, but it looks like it’s not possible to select sub-objects in nested blocks - do you know if it’s something that could be fixed “upstream”? Or if there’s any reason why it’s not possible?

import rhinoscriptsyntax as rs
import scriptcontext  as sc
import Rhino
import System.Drawing.Color

selected_colors = list()

# get colors of blocks' sub-objects
for object in sc.doc.Objects:
    if type(object) == Rhino.DocObjects.InstanceObject:
        sub_object_ids = object.GetSelectedSubObjects()
        if sub_object_ids:
            for sub_object_id in sub_object_ids:
                sub_object = object.InstanceDefinition.GetObjects()[sub_object_id.Index]
                sub_object_color = sub_object.Attributes.DrawColor(sc.doc)

# get colors of other objects
for object_id in rs.SelectedObjects():
    object = rs.coercerhinoobject(object_id)
    object_color = object.Attributes.DrawColor(sc.doc)

def _SelColor(object):
    for sub_object_id, sub_object in enumerate(object.InstanceDefinition.GetObjects()):
        if type(sub_object) == Rhino.DocObjects.InstanceObject:
        if sub_object.Attributes.DrawColor(sc.doc) in selected_colors:
            object.SelectSubObject(Rhino.Geometry.ComponentIndex(Rhino.Geometry.ComponentIndexType.InstanceDefinitionPart, sub_object_id), True, True, True)

# select objects by color recursively, even though doesn't work for nested blocks
# https://discourse.mcneel.com/t/let-selcolor-command-select-objects-inside-blocks/151883/13?u=daniel_krajnik
for object in sc.doc.Objects:
    if type(object) == Rhino.DocObjects.InstanceObject:


This looks a bit like a bug, if you print out the colors you will see they will not return their layer color. @dale?
in fact it will return the layer color of the parent block

1 Like

Thanks for checking, that’s bad news, because it was meant to batch modify objects in nested blocks.

Just tried a similar “SelMaterialInBlocks” script with the same results - objects in nested blocks were not selected.

SelMaterialInBlocks.py (1.8 KB)

also I just realized that Python uses “object” keyword, just in case I replaced all “object” symbols for “obj” - still the same results, it hasn’t changed the behaviour:
SelMaterialInBlocks-modified.py (1.7 KB)

After running your script, even on non nested blocks, if you type “What” you’ll see that it will just give back selected block instances.

1 Like