Connecting command created handler to command execute handler

Connecting command created handler to command execute handler

pcajp96
Explorer Explorer
1,542 Views
6 Replies
Message 1 of 7

Connecting command created handler to command execute handler

pcajp96
Explorer
Explorer

Hi, I am new to fusion API and am trying to make a simple script that will take inputs from the user and output a propeller hub. I've been able to create the geometry and the dialog box but can't seem to connect the two together. I am using the work flow described on this page http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-3922697A-7BF1-4799-9A5B-C8539DF57051 For some reason the user inputs do not connect to the geometry and no part is produced unless the values are defined in the Command Execute Handler. My code is posted below with the area of interest in green font. Any help or other examples of a UI customization would be greatly appreciated.

 

Thank you!

 

 

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

# Global list to keep all event handlers in scope.
# This is only needed with Python.
handlers = []

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

        # Get the CommandDefinitions collection.
        cmdDefs = ui.commandDefinitions

        # Create a button command definition.
        propButton = cmdDefs.addButtonDefinition('propButtonId', 
                                                   'Create Propeller', 
                                                   'Propeller button tooltip')
        
        # Connect to the command created event.
        propCommandCreated = propCommandCreatedEventHandler()
        propButton.commandCreated.add(propCommandCreated)
        handlers.append(propCommandCreated)
        
        # Execute the command.
        propButton.execute()
        
        # Keep the script running.
        adsk.autoTerminate(False)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

        
def stop(context):
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # Delete the command definition.
        cmdDef = ui.commandDefinitions.itemById('propButtonId')
        if cmdDef:
            cmdDef.deleteMe()            
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler for the commandCreated event.
class propCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        # Verify that a sketch is active.
        app = adsk.core.Application.get()
        
        eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
        
        # Get the command
        cmd = eventArgs.command

        # Get the CommandInputs collection to create new command inputs.            
        inputs = cmd.commandInputs

        app = adsk.core.Application.get()
        des = adsk.fusion.Design.cast(app.activeProduct)

        inputs.addValueInput('outerDiameter', 'outer diameter', 'cm', adsk.core.ValueInput.createByReal(5.0))
        inputs.addValueInput('innerDiameter','inner diameter','cm',adsk.core.ValueInput.createByReal(2.0))
        inputs.addValueInput('height','height','cm',adsk.core.ValueInput.createByReal(1.0))        
        
        
        # Connect to the execute event.
        onExecute = propCommandExecuteHandler()
        cmd.execute.add(onExecute)
        handlers.append(onExecute)
        
        # Connect to the inputChanged event.
        onInputChanged = propCommandInputChangedHandler()
        cmd.inputChanged.add(onInputChanged)
        handlers.append(onInputChanged)

		
# Event handler for the inputChanged event.
class propCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        eventArgs = adsk.core.InputChangedEventArgs.cast(args)
        

# Event handler for the execute event.
class propCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        eventArgs = adsk.core.CommandEventArgs.cast(args)

        # Get the values from the command inputs.
        inputs = eventArgs.command.commandInputs
        unitsMgr = app.activeProduct.unitsManager
        
        OD = inputs.itemById('outerDiameter').value
        ID = inputs.itembyId('innerDiameter').value
        h = inputs.itembyId('height').value
        
        #There is something wrong with getting the values from the 
        #CommandCreatedEventHanlder. When the values are defined as below it 
        #works fine but nothing happens when the values are defined as above
        #OD = 6
        #ID = adsk.core.ValueInput.createByString('4 cm')
        #h = adsk.core.ValueInput.createByString('5 cm')
        
        createHub(OD,ID,h)   
        
        
def createHub(outerDiameter, innerDiameter, distance):#def drawTriangle(baseLength, heightScale):
    app = adsk.core.Application.get()
    ui = app.userInterface     

    doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)

    design = app.activeProduct #what's open at the time

    # Get the root component of the active design.
    rootComp = design.rootComponent #sets up the top level component of the design in fusion

    # Get extrude features
    extrudes = rootComp.features.extrudeFeatures
        
    # Create a new sketch on the xy plane.
    sketches = rootComp.sketches #sketches comes from the object model(that big tree)
    xyPlane = rootComp.xYConstructionPlane # tell it to use xy plane
    sketch = sketches.add(xyPlane) #take sketches object and add it to the xy plane
    
    # Draw some circles.
    circles = sketch.sketchCurves.sketchCircles
    circle1 = circles.addByCenterRadius(adsk.core.Point3D.create(0, 0, 0), outerDiameter/2)

    #get sketch profile
    prof = sketch.profiles.item(0)
    
    #distance = adsk.core.ValueInput.createByString('5 cm')
    extrude1 = extrudes.addSimple(prof, distance, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)        
    # Get the extrusion body
    body1 = extrude1.bodies.item(0)
    body1.name = "Hub"
    
    # Get the end face of the extrusion
    endFaces = extrude1.endFaces
    endFace = endFaces.item(0)
            
    # Create a construction plane by offsetting the end face
    planes = rootComp.constructionPlanes
    planeInput = planes.createInput()
    offsetVal = adsk.core.ValueInput.createByString('0 cm')
    planeInput.setByOffset(endFace, offsetVal)
    offsetPlane = planes.add(planeInput)
    
    # Create a sketch on the new construction plane and add a sketch point
    offsetSketch = sketches.add(offsetPlane)
    offsetSketchPoints = offsetSketch.sketchPoints
    sPt0 = offsetSketchPoints.add(adsk.core.Point3D.create(0, 0, 0))
            
    # Create a hole input
    holes = rootComp.features.holeFeatures
    holeInput = holes.createSimpleInput(innerDiameter)
    holeInput.setPositionBySketchPoint(sPt0)
    holeInput.setDistanceExtent(distance)
    
    hole = holes.add(holeInput)

 

0 Likes
1,543 Views
6 Replies
Replies (6)
Message 2 of 7

ekinsb
Alumni
Alumni

What you have is very close but just contains a few mistakes.  I think you would have found the mistakes yourself if you had added try except statements in each of your functions.  What's happening in your original code is that it's hitting a problem and failing without anything about the problem being reported because the assert is not being handled anywhere.  Here's a version of your program where I added the try except statements and also fixed the few problems in the code.

 

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

# Global list to keep all event handlers in scope.
# This is only needed with Python.
handlers = []
_ui = adsk.core.UserInterface.cast(None)

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

        # Get the CommandDefinitions collection.
        cmdDefs = _ui.commandDefinitions

        # Create a button command definition.
        propButton = cmdDefs.addButtonDefinition('propButtonId', 
                                                   'Create Propeller', 
                                                   'Propeller button tooltip')
        
        # Connect to the command created event.
        propCommandCreated = propCommandCreatedEventHandler()
        propButton.commandCreated.add(propCommandCreated)
        handlers.append(propCommandCreated)
        
        # Execute the command.
        propButton.execute()
        
        # Keep the script running.
        adsk.autoTerminate(False)
    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

        
def stop(context):
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # Delete the command definition.
        cmdDef = ui.commandDefinitions.itemById('propButtonId')
        if cmdDef:
            cmdDef.deleteMe()            
    except:
        _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler for the commandCreated event.
class propCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            # Verify that a sketch is active.
            app = adsk.core.Application.get()
            
            eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
            
            # Get the command
            cmd = eventArgs.command
    
            # Get the CommandInputs collection to create new command inputs.            
            inputs = cmd.commandInputs
    
            app = adsk.core.Application.get()
            des = adsk.fusion.Design.cast(app.activeProduct)
    
            inputs.addValueInput('outerDiameter', 'outer diameter', 'cm', adsk.core.ValueInput.createByReal(5.0))
            inputs.addValueInput('innerDiameter','inner diameter','cm',adsk.core.ValueInput.createByReal(2.0))
            inputs.addValueInput('height','height','cm',adsk.core.ValueInput.createByReal(1.0))        
            
            
            # Connect to the execute event.
            onExecute = propCommandExecuteHandler()
            cmd.execute.add(onExecute)
            handlers.append(onExecute)
            
            # Connect to the inputChanged event.
            onInputChanged = propCommandInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            handlers.append(onInputChanged)
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

		
# Event handler for the inputChanged event.
class propCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        eventArgs = adsk.core.InputChangedEventArgs.cast(args)
        

# Event handler for the execute event.
class propCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandEventArgs.cast(args)
    
            # Get the values from the command inputs.
            inputs = eventArgs.command.commandInputs
            #unitsMgr = app.activeProduct.unitsManager
            
            OD = inputs.itemById('outerDiameter').value
            ID = inputs.itemById('innerDiameter').value
            h = inputs.itemById('height').value
                       
            createHub(OD,ID,h)   
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
        
        
def createHub(outerDiameter, innerDiameter, distance):#def drawTriangle(baseLength, heightScale):
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface     
    
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
    
        design = app.activeProduct #what's open at the time
    
        # Get the root component of the active design.
        rootComp = design.rootComponent #sets up the top level component of the design in fusion
    
        # Get extrude features
        extrudes = rootComp.features.extrudeFeatures
            
        # Create a new sketch on the xy plane.
        sketches = rootComp.sketches #sketches comes from the object model(that big tree)
        xyPlane = rootComp.xYConstructionPlane # tell it to use xy plane
        sketch = sketches.add(xyPlane) #take sketches object and add it to the xy plane
        
        # Draw some circles.
        circles = sketch.sketchCurves.sketchCircles
        circle1 = circles.addByCenterRadius(adsk.core.Point3D.create(0, 0, 0), outerDiameter/2)
    
        #get sketch profile
        prof = sketch.profiles.item(0)
        
        #distance = adsk.core.ValueInput.createByString('5 cm')
        extrude1 = extrudes.addSimple(prof, adsk.core.ValueInput.createByReal(distance), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)        
        # Get the extrusion body
        body1 = extrude1.bodies.item(0)
        body1.name = "Hub"
        
        # Get the end face of the extrusion
        endFaces = extrude1.endFaces
        endFace = endFaces.item(0)
                
        # Create a construction plane by offsetting the end face
        planes = rootComp.constructionPlanes
        planeInput = planes.createInput()
        offsetVal = adsk.core.ValueInput.createByString('0 cm')
        planeInput.setByOffset(endFace, offsetVal)
        offsetPlane = planes.add(planeInput)
        
        # Create a sketch on the new construction plane and add a sketch point
        offsetSketch = sketches.add(offsetPlane)
        offsetSketchPoints = offsetSketch.sketchPoints
        sPt0 = offsetSketchPoints.add(adsk.core.Point3D.create(0, 0, 0))
                
        # Create a hole input
        holes = rootComp.features.holeFeatures
        holeInput = holes.createSimpleInput(adsk.core.ValueInput.createByReal(innerDiameter))
        holeInput.setPositionBySketchPoint(sPt0)
        holeInput.setDistanceExtent(adsk.core.ValueInput.createByReal(distance))
        
        hole = holes.add(holeInput)
    except:
        _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
        

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 7

pcajp96
Explorer
Explorer

I tried to run this code and it does not seem to do anything. I'm not even getting an error message. I modified the original code to to have the syntax shown below and am now getting an error in the "ID = inputs.itembyId('innerDiameter').value" line. Is there an issue with using itembyId? Thanks in advance.

 

class propCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            app = adsk.core.Application.get()
            ui  = app.userInterface
        
            eventArgs = adsk.core.CommandEventArgs.cast(args)

            # Get the values from the command inputs.
            inputs = eventArgs.command.commandInputs
            unitsMgr = app.activeProduct.unitsManager
        
            OD = inputs.itemById('outerDiameter').value
            ID = inputs.itembyId('innerDiameter').value
            h = inputs.itembyId('height').value
            
            createHub(OD,ID,h)  
            
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes
Message 4 of 7

Anonymous
Not applicable

Have you been able to solve this issue with getting itemById to pull the right information between the event handler and the execute handler? I'm having the same issue with a hole function. 

I've tried multiple things, but I can't seem to be able to pull the points selected during the CommandCreatedEventHandler to populate as a list or array for use in the CommandExecuteHandler. See code below.

class HeatInsertCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
    
            # Get command        
            cmd = eventArgs.command
            
            # Get CommandInputs collection to create new command input
            inputs = cmd.commandInputs
            
            # Create point selection
            points = inputs.addSelectionInput('points','Select Points', 'Select Hole Location')                        
            points.setSelectionLimits(0)                     
            points.addSelectionFilter('SketchPoints')        
            
            # Create drop down menu with different inserts
            dropdownInput = inputs.addDropDownCommandInput('InsertDropdown', 'Select insert to be used', adsk.core.DropDownStyles.LabeledIconDropDownStyle)
            dropdownItems = dropdownInput.listItems
            dropdownItems.add('#0-80', True, '')
            dropdownItems.add('#2-56', True, '') 
            dropdownItems.add('#4-40', True, '')
            dropdownItems.add('#6-32', True, '')
            dropdownItems.add('#8-32', True, '')
            dropdownItems.add('#10-24', True, '') 
            dropdownItems.add('#10-32', True, '')
            dropdownItems.add('1/4-20', True, '')
            dropdownItems.add('M2', True, '')
            dropdownItems.add('M2.5', True, '') 
            dropdownItems.add('M3', True, '')
            dropdownItems.add('M4', True, '')
            dropdownItems.add('M5', True, '')
            dropdownItems.add('M6', True, '') 
            dropdownItems.add('M8', True, '') 
            
            # Connect to the execute event        
            onExecute = HeatInsertCommandExecuteHandler()
            cmd.execute.add(onExecute)
            handlers.append(onExecute)
            
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler for the execute event.
class HeatInsertCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandEventArgs.cast(args)
            
            app = adsk.core.Application.get()
            ui = app.userInterface
            ui.messageBox('In command execute event handler')
            
            product = app.activeProduct
            design = adsk.fusion.Design.cast(product)
            rootComp = design.rootComponent
            
            inputs = eventArgs.command.commandInputs
            
            sketchpoints = inputs.itemById('points').value
            
            distance = adsk.core.ValueInput.createByReal(5)
            
            holes = rootComp.features.holeFeatures
            holeInput = holes.createSimpleInput(adsk.core.ValueInput.createByString('2 mm'))
            holeInput.setPositionByPoint(sketchpoints)
            holeInput.setDistanceExtent(distance)
            
            hole = holes.add(holeInput)
            
            except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))    
0 Likes
Message 5 of 7

BrianEkins
Mentor
Mentor

I didn't try running your entire program but there's one problem I can see immediately with this line:

sketchpoints = inputs.itemById('points').value

The itemById method returns a command input object.  In this case, it's a SelectionInput.  The SelectionInput object doesn't support a value property but supports other functionality that's appropriate for something that would do selection.  What you'll want to use is the selectionCount property, which indicates how many items have been selected, and the select method which takes an index as an argument and returns a specific selected item.

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 6 of 7

Anonymous
Not applicable

Thanks Brad!

 

However, shortly after posting this I figured out what the problem was.

What I needed to do was call the entity within the input and then call the index in the entity, as the code attached.

Where "sketchpoints" are the points selected during the EventCreatedHandler. Then, during the ExecuteHandler, I grabbed the selected sketchpoints using the inputs.itemById('points') followed by the selection index and entity.

 

class HeatInsertCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandEventArgs.cast(args)
            
            app = adsk.core.Application.get()
            
            _ui = app.userInterface
            
            
            product = app.activeProduct
            design = adsk.fusion.Design.cast(product)
            rootComp = design.rootComponent
            
            inputs = eventArgs.command.commandInputs
            
            sketchpoints = inputs.itemById('points')
            pointCollection.add(sketchpoints.selection(i).entity)
            
            cutHoles(pointCollection, rootComp)
            
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))    

Cheers,


Nick

 

0 Likes
Message 7 of 7

Anonymous
Not applicable

I figured it out!

 

You have to use .selection(index).entity!

 

Try

class propCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            app = adsk.core.Application.get()
            ui  = app.userInterface
        
            eventArgs = adsk.core.CommandEventArgs.cast(args)

            # Get the values from the command inputs.
            inputs = eventArgs.command.commandInputs
            unitsMgr = app.activeProduct.unitsManager
        
            OD = (inputs.itemById('outerDiameter')).selection(0).entity
            ID = (inputs.itembyId('innerDiameter')).selection(0).entity
            h = (inputs.itembyId('height')).selection(0).entity
            
            createHub(OD,ID,h)  
            
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes