Problem adding to active selections

Problem adding to active selections

robduarte
Collaborator Collaborator
1,359 Views
5 Replies
Message 1 of 6

Problem adding to active selections

robduarte
Collaborator
Collaborator

Hi, I'm able to add to the active selections using the following code in my add-in but when the command completes the selection is lost. Is this a feature? The only function of this add-in is to select curves. (The code below does select the one circle in my sketch and the message box shows 1 as expected - it's just that the circle is unselected after the message box is dismissed). Thanks for any help.

 

class Selections:
    def Execute(self, entityOne):
        sketch = entityOne.parentSketch
        curves = sketch.sketchCurves   
        
        selections = ui.activeSelections
        selections.clear()
        
        for curve in curves:
            if (type(curve) is adsk.fusion.SketchCircle):
                selections.add(curve)
                ui.messageBox(str(selections.count))

Rob Duarte
Associate Professor in Art, Florida State University
Co-Director FSU Facility for Arts Research
http://art.fsu.edu/rob-duarte/

Twitter | YouTube

0 Likes
1,360 Views
5 Replies
Replies (5)
Message 2 of 6

robduarte
Collaborator
Collaborator

Actually, let me be more specific... I tried to pare down both a script and an add-in to the bare minimum to reproduce the problems I'm having (they are both supposed to do the same thing).

 

The first listing is a python "script" that mostly functions as intended. If you select a sketch curve, it selects ALL curves in that same sketch. There is one issue with this one that hopefully someone can answer: Why doesn't the ui.selectEntity function display the prompt as it's supposed to. (On my computer it shows nothing, although it does accept my selection).

 

The second listing is a python "add-in" with a command definition that allows the user to select that initial curve. The problem with this one is as I originally described: it doesn't keep the selections that are made. In addition, it seems to only select ONE of the curves, even though all of the "add" methods ARE being called within the loop (ie: it seems to only keep the LAST "add" since the message box shows 1 instead of the actual number of curves in the sketch).

 

Again, my 3 questions are:

 

  1. Why doesn't ui.selectEntity display the prompt as it's supposed to according to the api docs
  2. Why doesn't the add-in version of the script keep the selections after closing the messagebox?
  3. Why is it only selecting ONE of the curves instead of all of them (the loop is the same in both versions below)

Thanks for any help...

 

----- SCRIPT VERSION ------

#Author-
#Description-

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

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        sel = ui.selectEntity("Select a curve", "SketchCurves")
        selcurve = sel.entity        

        sketch = selcurve.parentSketch
        curves = sketch.sketchCurves
        
        selections = ui.activeSelections
        selections.clear()

        for curve in curves:
            selections.add(curve)
            
        ui.messageBox(str(selections.count))
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

--- ADD-IN VERSION ----

import adsk.core, adsk.fusion, traceback
import os

handlers = []
app = adsk.core.Application.get()
if app:
    ui = app.userInterface

class SelectionCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            command = args.firingEvent.sender
            inputs = command.commandInputs

            input0 = inputs[0];
            sel = input0.selection(0);
            selcurve = sel.entity

            sketch = selcurve.parentSketch
            curves = sketch.sketchCurves
        
            selections = ui.activeSelections
            selections.clear()

            for curve in curves:
                selections.add(curve)
            
            ui.messageBox(str(selections.count))
            
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            # when the command is done, terminate the script
            # this will release all globals which will remove all event handlers
            adsk.terminate()
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionValidateInputHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
       
    def notify(self, args):
        try:
            sels = ui.activeSelections;
            if len(sels) == 1:
                args.areInputsValid = True
            else:
                args.areInputsValid = False
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            cmd = args.command
            onExecute = SelectionCommandExecuteHandler()
            cmd.execute.add(onExecute)
            onDestroy = SelectionCommandDestroyHandler()
            cmd.destroy.add(onDestroy)

            onValidateInput = SelectionValidateInputHandler()
            cmd.validateInputs.add(onValidateInput)
            # keep the handler referenced beyond this function
            handlers.append(onExecute)
            handlers.append(onDestroy)
            handlers.append(onValidateInput)
            #define the inputs
            inputs = cmd.commandInputs
            i1 = inputs.addSelectionInput('entity', 'Sketch Curve', 'Please select a sketch curve')

            i1.addSelectionFilter(adsk.core.SelectionCommandInput.SketchCurves);

        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
                
def run(context):
    try:
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        if not design:
            ui.messageBox('It is not supported in current workspace, please change to MODEL workspace and try again.')
            return
        commandDefinitions = ui.commandDefinitions
        # check the command exists or not
        cmdDef = commandDefinitions.itemById('SelectionCMDDef')
        
        if not cmdDef:
            resourceDir = os.path.dirname(os.path.realpath(__file__)) # os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources') # absolute resource file path is specified
            cmdDef = commandDefinitions.addButtonDefinition('SelectionCMDDef',
                    'Select Curves',
                    'Select sketch curves',
                    resourceDir)

        onCommandCreated = SelectionCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        # keep the handler referenced beyond this function
        handlers.append(onCommandCreated)
        inputs = adsk.core.NamedValues.create()
        cmdDef.execute(inputs)

        # prevent this module from being terminate when the script returns, because we are waiting for event handlers to fire
        adsk.autoTerminate(False)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Rob Duarte
Associate Professor in Art, Florida State University
Co-Director FSU Facility for Arts Research
http://art.fsu.edu/rob-duarte/

Twitter | YouTube

0 Likes
Message 3 of 6

liujac
Alumni
Alumni

Hi,

 

  1. The prompt is displayed at the mouse cursor. There is no dialog or message box to be displayed for UserInterface.selectEntity.
  2. Clear all selection after the command dialog is closed, the behavior is as expected. You can see the UI commands also have the same behavior.
  3. Selections within command are limited to selection command inputs. When add a selection command input, the default behavior is that only one entity can be selected and it can be of any type. You can set the selection filters and limits on the selection command input as below.
  4.             i1 = inputs.addSelectionInput('entity', 'Sketch Curve', 'Please select a sketch curve')
                i1.addSelectionFilter(adsk.core.SelectionCommandInput.SketchCurves);
                i1.setSelectionLimits(1, 0) #A value of zero means that there is no limit

Also you need to change the line "if len(sels) == 1:" to "if len(sels) >= 1:" in SelectionValidateInputHandler to enable the OK button when the selections count is equal or greater than 1.

 

Thanks,

Jack

0 Likes
Message 4 of 6

robduarte
Collaborator
Collaborator

Thank you for the answers. Just to make sure I understand: it is not possible to make an add-in (with a command dialog) that selects curves for future operations by the user? That was my goal.. to allow the user to select a curve and have the command select similar curves based on attributes like length, approximate length, type of curve, etc.

Rob Duarte
Associate Professor in Art, Florida State University
Co-Director FSU Facility for Arts Research
http://art.fsu.edu/rob-duarte/

Twitter | YouTube

0 Likes
Message 5 of 6

liujac
Alumni
Alumni

Right, all selections made in a command will be cleared after the command is terminated. Could you keep the dialog open, and make the additional selections in selection event of the command for your workflow? Please try the addin below:

 

 

import adsk.core, adsk.fusion, traceback
import os

handlers = []
app = adsk.core.Application.get()
if app:
    ui = app.userInterface

class SelectionCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            command = args.firingEvent.sender
            inputs = command.commandInputs
            
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            # when the command is done, terminate the script
            # this will release all globals which will remove all event handlers
            adsk.terminate()
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionCommandSelectionEventHandler(adsk.core.SelectionEventHandler):
    def __init__(self):
        super().__init__()
       
    def notify(self, args):
        try:
            if args.selection:
                selcurve = args.selection.entity
    
                sketch = selcurve.parentSketch
                curves = sketch.sketchCurves
                
                additionalEntities = adsk.core.ObjectCollection.create()
                for curve in curves:
                    if curve != selcurve:
                        additionalEntities.add(curve)
                args.additionalEntities = additionalEntities
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectionCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            cmd = args.command
            onExecute = SelectionCommandExecuteHandler()
            cmd.execute.add(onExecute)
            onDestroy = SelectionCommandDestroyHandler()
            cmd.destroy.add(onDestroy)

            onSelect = SelectionCommandSelectionEventHandler()
            cmd.selectionEvent.add(onSelect)
            # keep the handler referenced beyond this function
            handlers.append(onExecute)
            handlers.append(onDestroy)
            handlers.append(onSelect)
            #define the inputs
            inputs = cmd.commandInputs
            i1 = inputs.addSelectionInput('entity', 'Sketch Curve', 'Please select a sketch curve')
            i1.addSelectionFilter(adsk.core.SelectionCommandInput.SketchCurves);
            i1.setSelectionLimits(1, 0) #A value of zero means that there is no limit

        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
                
def run(context):
    try:
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        if not design:
            ui.messageBox('It is not supported in current workspace, please change to MODEL workspace and try again.')
            return
        commandDefinitions = ui.commandDefinitions
        # check the command exists or not
        cmdDef = commandDefinitions.itemById('SelectionCMDDef')
        
        if not cmdDef:
            resourceDir = os.path.dirname(os.path.realpath(__file__)) # os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources') # absolute resource file path is specified
            cmdDef = commandDefinitions.addButtonDefinition('SelectionCMDDef',
                    'Select Curves',
                    'Select sketch curves',
                    resourceDir)

        onCommandCreated = SelectionCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        # keep the handler referenced beyond this function
        handlers.append(onCommandCreated)
        inputs = adsk.core.NamedValues.create()
        cmdDef.execute(inputs)

        # prevent this module from being terminate when the script returns, because we are waiting for event handlers to fire
        adsk.autoTerminate(False)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Thanks,

Jack

0 Likes
Message 6 of 6

Anonymous
Not applicable

@liujac wrote:

Right, all selections made in a command will be cleared after the command is terminated.


 

 

Is this still valid for the current version of Fusion 360?

 

So if I want to pass a program-generated selection of objects to the user I have to use a script instead of an Add-In?

0 Likes