Extrude Stair Script

Extrude Stair Script

Anonymous
Not applicable
852 Views
4 Replies
Message 1 of 5

Extrude Stair Script

Anonymous
Not applicable

I'm trying to write a script where it would initiate an Input Command API to where it would allow me to select a profile. The selected profile is then extruded, using the command input API generated, to the desired input.

 

The script is a lot similar to the Extrude Command except it will be extruding stairs to the appropriate height.

 

I was able to write code that would generate the Input Command API but I can't seem to make anything extrude 

 

 

import adsk.core, adsk.fusion, traceback

_app = None
_ui  = None
_rowNumber = 0
_commandId = 'DialogTextChange'
_commandName = 'Change Text and Height of Sketch'
_commandDescription = 'Make it easy to change ring Letters'


# Global set of event handlers to keep them referenced for the duration of the command
_handlers = []

# Adds a new row to the table.
def addRowToTable(tableInput):
    # Get the CommandInputs object associated with the parent command.
    cmdInputs = adsk.core.CommandInputs.cast(tableInput.commandInputs)
    
    # Create three new command inputs.
    valueInput = cmdInputs.addValueInput('TableInput_value{}'.format(_rowNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(_rowNumber))
    stringInput =  cmdInputs.addStringValueInput('TableInput_string{}'.format(_rowNumber), 'String', str(_rowNumber))
    spinnerInput = cmdInputs.addIntegerSpinnerCommandInput('spinnerInt{}'.format(_rowNumber), 'Integer Spinner', 0 , 100 , 2, int(_rowNumber))
    
    # Add the inputs to the table.
    row = tableInput.rowCount
    tableInput.addCommandInput(valueInput, row, 0)
    tableInput.addCommandInput(stringInput, row, 1)
    tableInput.addCommandInput(spinnerInput, row, 2)
    
    # Increment a counter used to make each row unique.
    global _rowNumber
    _rowNumber = _rowNumber + 1

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

            # We need access to the inputs within a command during the execute.
            tabCmdInput1 = inputs.itemById(_commandId + '_tab_1')
            tab1ChildInputs = tabCmdInput1.children
            selInput = tab1ChildInputs.itemById(_commandId + '_sel')
            input1 = tab1ChildInputs.itemById(_commandId + '_string')

        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
 
# Event handler that reacts to any changes the user makes to any of the command inputs.
class MyCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.InputChangedEventArgs.cast(args)
            inputs = eventArgs.inputs
            cmdInput = eventArgs.input
               
            tableInput = inputs.itemById('table')
            if cmdInput.id == 'tableAdd':
                addRowToTable(tableInput)
            elif cmdInput.id == 'tableDelete':
                if tableInput.selectedRow == -1:
                    _ui.messageBox('Select one row to delete.')
                else:
                    tableInput.deleteRow(tableInput.selectedRow)
                    
            command = args.firingEvent.sender
            inputs = command.commandInputs

            # We need access to the inputs within a command during the execute.
            tabCmdInput1 = inputs.itemById(_commandId + '_tab_1')
            tab1ChildInputs = tabCmdInput1.children
            selInput = tab1ChildInputs.itemById(_commandId + '_sel')
            input1 = tab1ChildInputs.itemById(_commandId + '_string')
            #input2 = tab1ChildInputs.itemById(_commandId + '_checkbox')
            
            #sketch = adsk.fusion.Sketch.cast(selInput.selection(0).entity)
            prof = selInput.selection(0)
            
            distance = input1.value
            
            design = adsk.fusion.Design.cast(_app.activeProduct)
            rootComp = design.rootComponent
            #extrudes = rootComp.features.extrudeFeatures
            extrudeInput = rootComp.features.extrudeFeatures.createInput(prof, adsk.fusion.FeatureOperations.JoinFeatureOperation)
            extrudeInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(2))
            extrude = rootComp.features.extrudeFeatures.add(extrudeInput)
          
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler that reacts to when the command is destroyed. This terminates the script.            
class MyCommandDestroyHandler(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:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler that reacts when the command definitio is executed which
# results in the command being created and this event being fired.
class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
                       
            # Get the command that was created.
            cmd = adsk.core.Command.cast(args.command)


            #Executes Handler
            onExecute = MyCommandExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)



            # Connect to the command destroyed event.
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            # Connect to the input changed event.           
            onInputChanged = MyCommandInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            _handlers.append(onInputChanged)    

            # Get the CommandInputs collection associated with the command.
            inputs = cmd.commandInputs

            #### Create a tab input.
            tabCmdInput1 = inputs.addTabCommandInput(_commandId + '_tab_1', 'Tab 1')
            tab1ChildInputs = tabCmdInput1.children


            # Create a selection input.
            selectionInput = tab1ChildInputs.addSelectionInput(_commandId + '_sel', 'Select', 'Select Face')
            #selectionInput.addSelectionFilter('Sketches')
            selectionInput.setSelectionLimits(0)

            # Create distance value input 2.
            distanceValueInput2 = tab1ChildInputs.addDistanceValueCommandInput(_commandId + '_string', 'DistanceValue 2', adsk.core.ValueInput.createByReal(1))
            distanceValueInput2.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 1, 0))
            distanceValueInput2.expression = '1 in'
            distanceValueInput2.hasMinimumValue = True
            distanceValueInput2.hasMaximumValue = False
                        
            
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


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

        global _commandId
        global _commandName
        global _commandDescription


        # Get the existing command definition or create it if it doesn't already exist.
        cmdDef = _ui.commandDefinitions.itemById(_commandId)
        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(_commandId,_commandName, _commandDescription)

        # Connect to the command created event.
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        # Execute the command definition.
        cmdDef.execute()

        # Prevent this module from being terminated 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()))

 

I believe the main issue I'm facing is in "MyCommandInputChangedHandler" where correctly inputting the selected profile is "prof" in order to use it into the extrude.addSimple(prof,..)

 

Thank you

0 Likes
Accepted solutions (1)
853 Views
4 Replies
Replies (4)
Message 2 of 5

marshaltu
Autodesk
Autodesk
Accepted solution

Hello,

 

The root cause was "selInput.selection(0)" just returned a selection object instead of profile object. You have to call it like "selInput.selection(0).entity".

 

In addition, I would like to suggest you create extrude in command execute event handler, which is best practice. I modified the codes a little bit as below. Now it should work for you.

 

Thanks,

Marshal

 

import adsk.core, adsk.fusion, traceback

_app = None
_ui  = None
_rowNumber = 0
_commandId = 'DialogTextChange'
_commandName = 'Change Text and Height of Sketch'
_commandDescription = 'Make it easy to change ring Letters'


# Global set of event handlers to keep them referenced for the duration of the command
_handlers = []

# Adds a new row to the table.
def addRowToTable(tableInput):
    # Get the CommandInputs object associated with the parent command.
    cmdInputs = adsk.core.CommandInputs.cast(tableInput.commandInputs)
    
    # Create three new command inputs.
    valueInput = cmdInputs.addValueInput('TableInput_value{}'.format(_rowNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(_rowNumber))
    stringInput =  cmdInputs.addStringValueInput('TableInput_string{}'.format(_rowNumber), 'String', str(_rowNumber))
    spinnerInput = cmdInputs.addIntegerSpinnerCommandInput('spinnerInt{}'.format(_rowNumber), 'Integer Spinner', 0 , 100 , 2, int(_rowNumber))
    
    # Add the inputs to the table.
    row = tableInput.rowCount
    tableInput.addCommandInput(valueInput, row, 0)
    tableInput.addCommandInput(stringInput, row, 1)
    tableInput.addCommandInput(spinnerInput, row, 2)
    
    # Increment a counter used to make each row unique.
    global _rowNumber
    _rowNumber = _rowNumber + 1

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

            # We need access to the inputs within a command during the execute.
            tabCmdInput1 = inputs.itemById(_commandId + '_tab_1')
            tab1ChildInputs = tabCmdInput1.children
            selInput = tab1ChildInputs.itemById(_commandId + '_sel')
            input1 = tab1ChildInputs.itemById(_commandId + '_string')
            #input2 = tab1ChildInputs.itemById(_commandId + '_checkbox')
            
            #sketch = adsk.fusion.Sketch.cast(selInput.selection(0).entity)
            if selInput.selectionCount > 0:        
                prof = selInput.selection(0).entity
                
                distance = input1.value
                
                design = adsk.fusion.Design.cast(_app.activeProduct)
                rootComp = design.rootComponent
                #extrudes = rootComp.features.extrudeFeatures
                extrudeInput = rootComp.features.extrudeFeatures.createInput(prof, adsk.fusion.FeatureOperations.JoinFeatureOperation)
                extrudeInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(distance))
                extrude = rootComp.features.extrudeFeatures.add(extrudeInput)

        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
 
# Event handler that reacts to any changes the user makes to any of the command inputs.
class MyCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            pass
          
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler that reacts to when the command is destroyed. This terminates the script.            
class MyCommandDestroyHandler(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:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler that reacts when the command definitio is executed which
# results in the command being created and this event being fired.
class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
                       
            # Get the command that was created.
            cmd = adsk.core.Command.cast(args.command)


            #Executes Handler
            onExecute = MyCommandExecuteHandler()
            cmd.execute.add(onExecute)
            cmd.executePreview.add(onExecute)
            _handlers.append(onExecute)



            # Connect to the command destroyed event.
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            # Connect to the input changed event.           
            onInputChanged = MyCommandInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            _handlers.append(onInputChanged)    

            # Get the CommandInputs collection associated with the command.
            inputs = cmd.commandInputs

            #### Create a tab input.
            tabCmdInput1 = inputs.addTabCommandInput(_commandId + '_tab_1', 'Tab 1')
            tab1ChildInputs = tabCmdInput1.children


            # Create a selection input.
            selectionInput = tab1ChildInputs.addSelectionInput(_commandId + '_sel', 'Select', 'Select Face')
            #selectionInput.addSelectionFilter('Sketches')
            selectionInput.setSelectionLimits(0)

            # Create distance value input 2.
            distanceValueInput2 = tab1ChildInputs.addDistanceValueCommandInput(_commandId + '_string', 'DistanceValue 2', adsk.core.ValueInput.createByReal(1))
            distanceValueInput2.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 1, 0))
            distanceValueInput2.expression = '1 in'
            distanceValueInput2.hasMinimumValue = True
            distanceValueInput2.hasMaximumValue = False
                        
            
        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


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

        global _commandId
        global _commandName
        global _commandDescription


        # Get the existing command definition or create it if it doesn't already exist.
        cmdDef = _ui.commandDefinitions.itemById(_commandId)
        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(_commandId,_commandName, _commandDescription)

        # Connect to the command created event.
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        # Execute the command definition.
        cmdDef.execute()

        # Prevent this module from being terminated 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()))


Marshal Tu
Fusion Developer
>
Message 3 of 5

Anonymous
Not applicable

that actually worked! thank you so much.

fusion API at first is not as straightforward but I'm starting to get the hang of things now thanks to you.

Much appreciated!

0 Likes
Message 4 of 5

Anonymous
Not applicable

the issue I am having now is that it will only extrude my first selection after giving an error

 

I'm posting the updated code and screenshots:

1.JPG

 

2.JPG

 

3.JPG

 

4.JPG

 

 

 

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

            # We need access to the inputs within a command during the execute.
            tabCmdInput1 = inputs.itemById(_commandId + '_tab_1')
            tab1ChildInputs = tabCmdInput1.children
            selInput = tab1ChildInputs.itemById(_commandId + '_sel')
            input1 = tab1ChildInputs.itemById(_commandId + '_string')
 
            design = adsk.fusion.Design.cast(_app.activeProduct)
            rootComp = design.rootComponent
            if selInput.selectionCount > 1:        
                
                for i in range(0,selInput.selectionCount):
                    
                    prof = selInput.selection(i).entity
                    distance = (input1.value/selInput.selectionCount)*(i+1)
                    
                    extrudeInput = rootComp.features.extrudeFeatures.createInput(prof, adsk.fusion.FeatureOperations.JoinFeatureOperation)
                    extrudeInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(distance))
                    extrude = rootComp.features.extrudeFeatures.add(extrudeInput)
                
                
        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

0 Likes
Message 5 of 5

marshaltu
Autodesk
Autodesk

Hello,

 

The problem was selection was cleared after the first extrude feature was created. You have to walk through all selections firstly and persist profiles before creating extrude features.

 

Please refer to the following codes.

 

Thanks,

Marshal

 

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

            # We need access to the inputs within a command during the execute.
            tabCmdInput1 = inputs.itemById(_commandId + '_tab_1')
            tab1ChildInputs = tabCmdInput1.children
            selInput = tab1ChildInputs.itemById(_commandId + '_sel')
            input1 = tab1ChildInputs.itemById(_commandId + '_string')
            
            profs = []
            for i in range(0, selInput.selectionCount): 
                prof = adsk.fusion.Profile.cast(selInput.selection(0).entity)
                if prof:
                    profs.append(prof)          
            
            design = adsk.fusion.Design.cast(_app.activeProduct)
            rootComp = design.rootComponent            
            selcount = len(profs)
            if selcount > 0:
                
                for i in range(0, selcount):
                    
                    prof = profs[i]
                    distance = (input1.value/selcount)*(i+1)
                    
                    extrudeInput = rootComp.features.extrudeFeatures.createInput(prof, adsk.fusion.FeatureOperations.JoinFeatureOperation)
                    extrudeInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(distance))
                    extrude = rootComp.features.extrudeFeatures.add(extrudeInput)

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


Marshal Tu
Fusion Developer
>
0 Likes