Rhino.Input.Custom.GetObject(): trigger event when new object is added to selection

Is there a way of triggering an event every time a new object is added to the selection?

I am trying to write a custom block picker that adds all instances of the block that the user has just picked to the selection, and print how many instances of the block it has found.

My code so far is largely based on this thread:

Thank you

Are you looking for RhinoDoc.SelectObjects event?
Here you can find a simple implementation in Grasshopper:

Hm, I’m not sure how I would add this to my code. Rhino common is not my forte

def getBlocksWithDirection():
        msg = "Select blocks"
        go = Rhino.Input.Custom.GetObject()
        go.SetCommandPrompt(msg)

        toggle = Rhino.Input.Custom.OptionToggle(True, '+x', '-y')
        go.AddOptionToggle('Arrange', toggle)
        go.EnablePreSelect(True, True)
        go.GeometryFilter = Rhino.DocObjects.ObjectType.InstanceReference

        objs = []
        while True:
            # https://discourse.mcneel.com/t/get-multiple-objects-plus-list-option/14849/3
            get = go.GetMultiple(1, 0)
            if get == Rhino.Input.GetResult.Cancel:
                return False
            elif get == Rhino.Input.GetResult.Option:
                continue
            elif get == Rhino.Input.GetResult.Object:
                ids = [go.Object(i).ObjectId for i in range(go.ObjectCount)]
                return (ids, toggle.CurrentValue)

            return False

You mean something like this?

import Rhino
def getBlocks():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select blocks")
    go.OneByOnePostSelect = True
    go.GeometryFilter = Rhino.DocObjects.ObjectType.InstanceReference
    while True:
        go.Get()
        if go.CommandResult()!=Rhino.Commands.Result.Success:
            return go.CommandResult()
        instance = go.Object(0).Object().InstanceDefinition
        print "There are {} references of {}".format(instance.GetReferences(0).Count, instance.Name)
        go.SetCommandPrompt("Select blocks. Press Enter when done")

if __name__ == "__main__":
    getBlocks()

GetBlocks.py (634 Bytes)

import Rhino
from scriptcontext import doc
def getBlocks():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select blocks")
    go.OneByOnePostSelect = True
    go.GeometryFilter = Rhino.DocObjects.ObjectType.InstanceReference
    go.DeselectAllBeforePostSelect = False
    while True:
        go.Get()
        if go.CommandResult()!= Rhino.Commands.Result.Success:
            return go.CommandResult()
        instance = go.Object(0).Object().InstanceDefinition
        references = instance.GetReferences(0)
        for reference in references:
            reference.Select(True)
        doc.Views.Redraw()
        print "There are {} references of {}".format(references.Count, instance.Name)
        go.SetCommandPrompt("Select blocks. Press Enter when done")

if __name__ == "__main__":
    getBlocks()

GetBlocks.py (845 Bytes)

1 Like

This is amazing, Mahdiyar. Thank you. Please let me ask you one last question:
After selecting the blocks, when I hit Enter or right-click, the return value is Rhino.Commands.Result.Cancel. How would I return all the selected block GUIDs (from user click, and the additional ones)? I also have an OptionToggle, whose state needs to be returned.
Thank you so much