additionalEntities on selection

additionalEntities on selection

j.han97
Advocate Advocate
489 Views
3 Replies
Message 1 of 4

additionalEntities on selection

j.han97
Advocate
Advocate

Hi all,

 

I have tested and found that it is not possible to use additionalEntities property on select event. Instead, it is only applicable to preSelect event.

 

In the simple code below, the additionalEntities property is used to add additional faces which are neighboring to the selected face. However, this only works in preSelect handler, but not in select handler. 

 

In my use case, the computations involved are rather large, therefore when the users hover through the faces, they will experience severe lagging issues because of the preSelect handler. I would like to move the calculations for additional entities to select event to improve the smoothness of users' operations. 

 

In short, I want the API to only compute for additional entities AFTER a selection has been made, instead of hovering. If the API is unable to do this, is there any workaround to achieve this objective?

 

Thank you for your time to read this. If you are interested, this code below is for demonstration: Additional entities work as expected in preSelect handler but not in select handler.

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

class mySelectionCommand_commandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    
    def notify(self, args):
        try:
            command = adsk.core.CommandCreatedEventArgs.cast(args).command
            
            commandInputs = command.commandInputs
            
            selectionInput1 = commandInputs.addSelectionInput('mySelectionInput1',
                                                              'MySelection1', 
                                                              'Select any face')
            selectionInput1.addSelectionFilter('Faces')
            selectionInput1.setSelectionLimits(0)
            
            #Event handlers
            # mySelectionCommand_ps = mySelectionCommandInput_preSelectEventHandler()
            # command.preSelect.add(mySelectionCommand_ps)
            # _handlers.append(mySelectionCommand_ps)
            
            mySelectionCommand_s = mySelectionCommandInput_selectEventHandler()
            command.select.add(mySelectionCommand_s)
            _handlers.append(mySelectionCommand_s)
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

# class mySelectionCommandInput_preSelectEventHandler(adsk.core.SelectionEventHandler):
#     def __init__(self):
#         super().__init__()
    
#     def notify(self, args):
#         try:
#             eventArgs = adsk.core.SelectionEventArgs.cast(args)

#             selected_face = adsk.fusion.BRepFace.cast(eventArgs.selection.entity)
            
#             neighbour_faces = adsk.core.ObjectCollection.create()
#             for e in selected_face.edges:
#                 for f in e.faces:
#                     if f is not selected_face:
#                         neighbour_faces.add(f)
                        
            
#             eventArgs.additionalEntities = neighbour_faces
#         except:
#             _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class mySelectionCommandInput_selectEventHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    
    def notify(self, args):
        try:
            eventArgs = adsk.core.SelectionEventArgs.cast(args)

            selected_face = adsk.fusion.BRepFace.cast(eventArgs.selection.entity)
            
            neighbour_faces = adsk.core.ObjectCollection.create()
            for e in selected_face.edges:
                for f in e.faces:
                    if f is not selected_face:
                        neighbour_faces.add(f)
                        
            
            eventArgs.additionalEntities = neighbour_faces
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

_app: adsk.core.Application = adsk.core.Application.get()
_ui: adsk.core.UserInterface = _app.userInterface

_handlers = []

def run(context):
    try:
        mySelectionCommand = _ui.commandDefinitions.itemById('mySelectionCommand')
        if mySelectionCommand:
            mySelectionCommand.deleteMe()
        mySelectionCommand = _ui.commandDefinitions.addButtonDefinition(
            'mySelectionCommand',
            'MySelection',
            'Select a random face',
            './MySelection')

        mySelectionCommand_cc = mySelectionCommand_commandCreatedEventHandler()
        mySelectionCommand.commandCreated.add(mySelectionCommand_cc)
        _handlers.append(mySelectionCommand_cc)
        
        addin_tab = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel')
        mySelectionControl = addin_tab.controls.itemById('mySelectionCommand')
        if mySelectionControl: mySelectionControl.deleteMe()
        mySelectionControl = addin_tab.controls.addCommand(mySelectionCommand)
        
        mySelectionControl.isVisible = True; mySelectionControl.isPromoted = True

        mySelectionCommand.execute()
        
    except:
        _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


(To run the code above you need a resource folder named 'MySelection'. Or, change it as you wish)

 

0 Likes
490 Views
3 Replies
Replies (3)
Message 2 of 4

tykapl.breuil
Advocate
Advocate

Hey there,

 

So the problem you are facing is that the additionalEntities attribute isn't meant to be used in the SelectEvent (ie it's not a bug, it's a feature). To manipulate the selection in this event, you need to go through the commandInput directly.

 

See the class below :

 

class mySelectionCommandInput_selectEventHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    
    def notify(self, args):
        try:
            eventArgs = adsk.core.SelectionEventArgs.cast(args)

            selected_face = adsk.fusion.BRepFace.cast(eventArgs.selection.entity)
            selectionInput = eventArgs.firingEvent.activeInput
            
            neighbour_faces = adsk.core.ObjectCollection.create()
            for e in selected_face.edges:
                for f in e.faces:
                    if f is not selected_face:
                        selectionInput.addSelection(f)

        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Two words of caution:

- You'll need to manage the unselect manually (if you need too) but you'll probably figure that out.

- There is a bug (or a problem in the documentation) with the eventArgs.activeInput property (which does not work), you need to use eventArgs.firingEvent.activeInput which works fine. (@BrianEkins would it be possible to report this issue ?)

 

Also the code you gave did not work directly, I had to add adsk.autoTerminate(False) in the run function (or the script terminated and the command Definition didn't execute because the handlers weren't connected anymore).

0 Likes
Message 3 of 4

j.han97
Advocate
Advocate

Hi @tykapl.breuil , 

 

Thanks for your reply. I do considered the approach but I don't like this because I thought it should be implemented in the API. From my perspective, applying additionalEntities in preSelect or select handler is similar in terms of the algorithm. (Just some random rant here, I understand that Fusion 360 API is far from a complete API)

 

Thanks for the reminder too, you actually gave me this hint (activeInput) before in a previous post.

 

I tested my code in an add-in and it did work for me. Maybe you have been running it as a script? (I'm not sure about this)

Message 4 of 4

tykapl.breuil
Advocate
Advocate

Yes exactly, I ran it as a script because there is no stop function (you should clean up :p).