Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Only allow visible items to be selected in SelectionEventHandler

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
ebunn3
209 Views, 6 Replies

Only allow visible items to be selected in SelectionEventHandler

Is there a way to set up a SelectionEventHandler to ignore selections that are not visible. (isVisible = False)?

 

Thanks,

Eric

class MySelectHandler(adsk.core.SelectionEventHandler):
    """When a select button is active and something is selected this function responds to the event.
    Differentiate the select buttons using the activeSelectionInput.id function and build if statements to run specific
    code for the different select buttons"""
    def __init__(self):
        super().__init__()
        self.units = units
    def notify(self, args):
        app = adsk.core.Application.get()
        ui = app.userInterface
        try:
            eventArgs = adsk.core.SelectionEventArgs.cast(args)
            activeSelectionInput = eventArgs.firingEvent.activeInput
            type = args.selection.entity.objectType#;print(type)
            if type == 'adsk::fusion::Occurrence':
                selectedBody = adsk.fusion.Occurrence.cast(args.selection.entity) 
            elif type == 'adsk::fusion::BRepBody':
                selectedBody = adsk.fusion.BRepBody.cast(args.selection.entity) 
            else:
                ui.messageBox("Choose either a component or a single body only.")
                return
            # Get the values from the command inputs.
            inputs = eventArgs.firingEvent.sender.commandInputs

            if selectedBody:
                # #customize this for the number of select buttons on the form.  Find them by id.
                if activeSelectionInput.id == 'cushBody':
                    globList[0].append(selectedBody)
                    
            if activeSelectionInput.id == 'prodBody':
                globList[1].append(selectedBody)

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

 

6 REPLIES 6
Message 2 of 7
tykapl.breuil
in reply to: ebunn3

I don't see any other way to do it other than adding a check on your selectHandler and when the selected item isn't visible, getting every item from the involved selection on a list, clearing that selection then re-adding every item but the last one. It's a bit clumsy but I don't know of a way to remove an item from a selection input. Maybe setting then removing a limit could work ?

Message 3 of 7
j.han97
in reply to: ebunn3

There is this isSelectable property for BRepBody and Occurrence which in theory, could be used to exclude them for selections:

item.isSelectable = item.isVisible

However, I have not tried this method yet though.

Message 4 of 7
kandennti
in reply to: ebunn3

Hi @ebunn3 .

 

Instead of deselecting them, how about not letting them select the ones that aren't shown?

 

By using the PreSelect event, it is possible to get the element under the mouse cursor, and depending on the condition, it is possible to prevent selection.

 

In the following sample, a body that is not displayed is not selected.

# Fusion360API Python script

import traceback
import adsk.cam
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []

class MyPreSelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.SelectionEventArgs):
        if not args.selection.entity.isVisible:
            args.isSelectable = False

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        try:
            global _handlers
            cmd = adsk.core.Command.cast(args.command)
            cmd.isOKButtonVisible = False

            inputs: adsk.core.CommandInputs = cmd.commandInputs

            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onPreSelect = MyPreSelectHandler()
            cmd.preSelect.add(onPreSelect)
            _handlers.append(onPreSelect)

            selIpt: adsk.core.SelectionCommandInput = inputs.addSelectionInput(
                'selIpt',
                'select',
                'select'
            )
            selIpt.setSelectionLimits(0)
            selIpt.selectionFilters = ['Bodies']

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

class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        adsk.core.Application.get().log('Call Destroy Event')
        adsk.terminate()

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        cmdDef = _ui.commandDefinitions.itemById('test')
        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                'test', 'Test', 'Test')

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Message 5 of 7
ebunn3
in reply to: kandennti

Thank you @kandennti .  I’ll check this out since it appears that it could be a great solution for me.  Thanks.  

Eric

Message 6 of 7
ebunn3
in reply to: kandennti

@kandennti 

 

The preselect handler works great unless I set the selection filter to occurrences.  When I do this I get an error:

ebunn3_0-1640013474287.png

 

There is not an  isVisible property for an adsk.fusion.component and when I hover over anything in the tree or screen that is not an occurrence or body I get this error. Seems to be anything at the root component level, like a plane, etc.  I have included code below that will throw the error.  I've tried putting in if statements in the handler to try and correct this with no success.  As soon as it enters the handler it throws the error.  Any help here would be greatly appreciated.  This will work for me if I can get it to work.

 

Eric

 

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback

ui = adsk.core.UserInterface.cast(None)
handlers = []
_prodBodies = []
_cushBodies = []

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            cmd = args.command
            cmd.isExecutedWhenPreEmpted = False

            global _inputs
            inputs = cmd.commandInputs
            
            selectInput = inputs.addSelectionInput(
                'productBodies',
                'productBodies',
                'Please select Bodies'
            )
            selectInput.addSelectionFilter('Occurrences')
            selectInput.setSelectionLimits(1)

            selectInput = inputs.addSelectionInput(
                'cushionBodies',
                'cushionBodies',
                'Please select Bodies'
            )
            selectInput.addSelectionFilter('Bodies')
            selectInput.setSelectionLimits(1)

            # Connect to the command related events.
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            handlers.append(onDestroy)

            onSelect = MySelectHandler()
            cmd.select.add(onSelect)
            handlers.append(onSelect)

            onUnSelect = MyUnSelectHandler()
            cmd.unselect.add(onUnSelect)
            handlers.append(onUnSelect)

            onPreSelect = MyPreSelectHandler()
            cmd.preSelect.add(onPreSelect)
            handlers.append(onPreSelect)
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def stop(context):
    """This function will unload the add-in and icon.  No customization necessary within this function."""
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        #ui.messageBox('Stop addin')

        #deleting the com button definition (use the id created in the run function 
        # (adsk.core.CommandDefinitions.addButtonDefinition(butName))
        cmdDef = ui.commandDefinitions.itemById('SelectionEventsTest')
        if cmdDef:
            cmdDef.deleteMe()

        #deleting the button
        addinsToolbarPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel' )
        cntrl = addinsToolbarPanel.controls.itemById('SelectionEventsTest')
        if cntrl:
            cntrl.deleteMe()
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            adsk.terminate()
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class MyPreSelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.SelectionEventArgs):
        try:
            app = adsk.core.Application.get()
            ui = app.userInterface

            if not args.selection.entity.isVisible:
                args.isSelectable = False
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))     

class MySelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        app = adsk.core.Application.get()
        ui = app.userInterface
        try:
            eventArgs = adsk.core.SelectionEventArgs.cast(args)
            activeSelectionInput = eventArgs.firingEvent.activeInput
            selectedBody = adsk.fusion.BRepBody.cast(args.selection.entity) 

            if selectedBody:
                if activeSelectionInput.id == 'productBodies':
                    _prodBodies.append(selectedBody)
                if activeSelectionInput.id == 'cushionBodies':
                    _cushBodies.append(selectedBody)

            # dumpSelectionInputItem()

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

class MyUnSelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        app = adsk.core.Application.get()
        ui = app.userInterface
        try:
            eventArgs = adsk.core.SelectionEventArgs.cast(args)
            activeSelectionInput = eventArgs.firingEvent.activeInput
            selectedBody = adsk.fusion.BRepBody.cast(args.selection.entity) 

            if selectedBody:
                if activeSelectionInput.id == 'productBodies':
                    _prodBodies.remove(selectedBody)
                if activeSelectionInput.id == 'cushionBodies':
                    _cushBodies.remove(selectedBody)

            # dumpSelectionInputItem()

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

def run(context):
    global ui
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        myCmdDef = ui.commandDefinitions.itemById('SelectionEventsTest')
        if myCmdDef is None:
            myCmdDef = ui.commandDefinitions.addButtonDefinition(
                'SelectionEventsTest',
                'Selection Events Test',
                '',
                ''
            )

        onCommandCreated = MyCommandCreatedHandler()
        myCmdDef.commandCreated.add(onCommandCreated)
        handlers.append(onCommandCreated)

        myCmdDef.execute()

        adsk.autoTerminate(False)

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

 

 

Message 7 of 7
ebunn3
in reply to: kandennti

@kandennti 

 

I believe I corrected the problem with an if statement to filter out everything except occurrences and bodies.  See attached.

 

Eric

class MyPreSelectHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.SelectionEventArgs):
        try:
            app = adsk.core.Application.get()
            ui = app.userInterface
            eventArgs = adsk.core.SelectionEventArgs.cast(args)
            type = eventArgs.selection.entity
            if type.objectType == 'adsk::fusion::Occurrence' or type.objectType == 'adsk::fusion::BRepBody':
                if not args.selection.entity.isVisible:
                    args.isSelectable = False
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))    

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report