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()))
Solved! Go to Solution.
Solved by brad.bylls. Go to Solution.
Solved by kandennti. Go to 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()))
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.
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
Thanks Mike.
I would hope so.
Seems foolish that it wasn't that way to begin with.
Can't find what you're looking for? Ask the community or share your knowledge.