Combine/cut script problem

Combine/cut script problem

brad.bylls
Collaborator Collaborator
1,387 Views
4 Replies
Message 1 of 5

Combine/cut script problem

brad.bylls
Collaborator
Collaborator

See video attached that explains the problem.

Here is the script.

import adsk.core, adsk.fusion, traceback
import math

# Globals
_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)
strResult = ''

_handlers = []

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

        cmdDef = _ui.commandDefinitions.itemById('adskSpurGearPythonScript')
        if not cmdDef:
            # Create a command definition.
            cmdDef = _ui.commandDefinitions.addButtonDefinition('adskSpurGearPythonScript', 'Spur Gear', 'Creates a spur gear component', '') 
        
        # Connect to the command created event.
        onCommandCreated = SketchCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)
        
        # Execute the command.
        cmdDef.execute()

        # 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()))

class SketchCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandEventArgs.cast(args)

            # 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()))

# Event handler for the commandCreated event.
class SketchCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
            
            cmd = eventArgs.command
            cmd.isExecutedWhenPreEmpted = False
            inputs = cmd.commandInputs
            
            global root, features

            design = _app.activeProduct
            root = design.rootComponent
            features = root.features

            # Verify that a Fusion design is active.
            if not design:
                _ui.messageBox('A Fusion design must be active when invoking this command.')
                return()

            cmd.okButtonText = ("Make the Cuts") # text in "OK" button
            cmd.isExecutedWhenPreEmpted = False

            # Create the command dialog
            _inputSelectTargets = inputs.addSelectionInput('target', 'Target Bodies', 'Select the Bodies\nThat Will Be Cut')
            _inputSelectTargets.addSelectionFilter(adsk.core.SelectionCommandInput.Bodies)
            _inputSelectTargets.setSelectionLimits(0)

            _inputSelectTools = inputs.addSelectionInput('tool', 'Tool Bodies', 'Select the Bodies\nThat Will Do The Cutting')
            _inputSelectTools.addSelectionFilter(adsk.core.SelectionCommandInput.Bodies)
            _inputSelectTools.setSelectionLimits(0)

            _inputHideTools = inputs.addBoolValueInput('hideTools', 'Hide Tool Bodies?', True)

            _inputErrMessage = inputs.addTextBoxCommandInput('errMessage', '', '', 2, True)
            _inputErrMessage.isFullWidth = True
            
            # Connect to the command related events.
            onExecute = SketchCommandExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)        
            
            onInputChanged = SketchCommandInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            _handlers.append(onInputChanged)    
            
            onValidateInputs = SketchCommandValidateInputsHandler()
            cmd.validateInputs.add(onValidateInputs)
            _handlers.append(onValidateInputs)

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

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

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

            target_input = inputs.itemById('target').selectionCount
            tool_input = inputs.itemById('tool').selectionCount
            toolBodies = adsk.core.ObjectCollection.create()

            for x in range (0, target_input):
                targetBody = inputs.itemById('target').selection(x).entity

                toolBodies.clear()
                toolBody = None
                for y in range (0, tool_input):
                    toolBody = inputs.itemById('tool').selection(y).entity  # Problem line 130
                    toolBodies.add(toolBody)

                CombineCutInput = root.features.combineFeatures.createInput(targetBody, toolBodies)
                CombineCutFeats = features.combineFeatures
                CombineCutInput = CombineCutFeats.createInput(targetBody, toolBodies)
                CombineCutInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation
                CombineCutInput.isKeepToolBodies = True
                CombineCutFeats.add(CombineCutInput)

            if inputs['hideTools'] == True:
                for z in range (0, tool_input):
                    toolBodies.item(z).isVisible = False
        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))   
        
# Event handler for the inputChanged event.
class SketchCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.InputChangedEventArgs.cast(args)
            changedInput = eventArgs.input
            inputs :adsk.core.CommandInputs = eventArgs.inputs
            
            if changedInput.id == 'target':
                selection_input = inputs.itemById('target')
                # selection_input.hasFocus = True
            elif changedInput.id == 'tool':
                selection_input = inputs.itemById('tool')

        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))     
        
# Event handler for the validateInputs event.
class SketchCommandValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            eventArgs = adsk.core.ValidateInputsEventArgs.cast(args)
            
            if strResult != ' ':
                return True
            else:
                return False

        except:
            if _ui:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
  
Brad Bylls
Accepted solutions (2)
1,388 Views
4 Replies
Replies (4)
Message 2 of 5

kandennti
Mentor
Mentor
Accepted solution

Hi @brad.bylls .

 

It seems that the Tool's SelectionCommandInput is cleared when the first Cut is performed.

Therefore, if I create the ObjectCollection of Tools in advance and process it, no error occurs.

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

            # tools
            toolBodies = adsk.core.ObjectCollection.create()
            tool_input: adsk.core.SelectionCommandInput = inputs.itemById('tool')
            for idx in range(0, tool_input.selectionCount):
                toolBodies.add(tool_input.selection(idx).entity)

            # CombineCut
            target_input: adsk.core.SelectionCommandInput = inputs.itemById('target')
            for idx in range(0, target_input.selectionCount):
                targetBody = target_input.selection(idx).entity

                CombineCutInput = root.features.combineFeatures.createInput(targetBody, toolBodies)
                CombineCutFeats = features.combineFeatures
                CombineCutInput = CombineCutFeats.createInput(targetBody, toolBodies)
                CombineCutInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation
                CombineCutInput.isKeepToolBodies = True
                CombineCutFeats.add(CombineCutInput)

            # hide tools
            hideTools: adsk.core.BoolValueCommandInput = inputs.itemById('hideTools')
            if hideTools.value:
                for entity in toolBodies:
                    entity.isVisible = False

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

brad.bylls
Collaborator
Collaborator
Accepted solution

Wow.

That works great.

I never would have thought of that.

You are a genius.

Thank you so much.

Now I can finish my add-in.

Brad Bylls
Message 4 of 5

MichaelT_123
Advisor
Advisor

Hi Mr BradBylls,

 

Could we dream that the problem you solved in your script would be found in a future version of the standard F360 combine tool?

 

Regards

MichaelT

MichaelT
0 Likes
Message 5 of 5

brad.bylls
Collaborator
Collaborator

Thanks Mike. 

I would hope so.

Seems foolish that it wasn't that way to begin with. 

Brad Bylls
0 Likes