From 55acf65509f33f4498643760364783cd121fa26b Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 14:04:56 -0700 Subject: [PATCH 01/21] Working new joint config tab --- .../src/UI/ConfigCommand.py | 837 ++++++++++-------- .../src/UI/CreateCommandInputsHelper.py | 93 ++ .../src/UI/CustomGraphics.py | 5 +- .../src/UI/FileDialogConfig.py | 3 +- .../src/UI/JointConfigTab.py | 305 +++++++ .../src/UI/MarkingMenu.py | 7 +- .../SynthesisFusionAddin/src/UI/OsHelper.py | 5 +- .../src/UI/TableUtilities.py | 10 +- 8 files changed, 861 insertions(+), 404 deletions(-) create mode 100644 exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py create mode 100644 exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 4c540f5bd5..a682ef8556 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -20,7 +20,24 @@ ) from .Configuration.SerialCommand import SerialCommand -import adsk.core, adsk.fusion, traceback, logging, os +# Transition: AARD-1685 +from .CreateCommandInputsHelper import ( + createTextBoxInput, + createTableInput, +) +from .JointConfigTab import ( + createJointConfigTab, + addJointToConfigTab, + removeIndexedJointFromConfigTab, + getSelectedJoints, + resetSelectedJoints +) + +import adsk.core +import adsk.fusion +import traceback +import logging +import os from types import SimpleNamespace # ====================================== CONFIG COMMAND ====================================== @@ -241,7 +258,7 @@ def notify(self, args): # ~~~~~~~~~~~~~~~~ WEIGHT CONFIGURATION ~~~~~~~~~~~~~~~~ """ - Table for weight config. + Table for weight config. - Used this to align multiple commandInputs on the same row """ weightTableInput = self.createTableInput( @@ -387,17 +404,17 @@ def notify(self, args): algorithmicIndicator.formattedText = "🟢" algorithmicIndicator.tooltipDescription = ( "(enabled)" + - "
If a sub-part of a wheel is selected (eg. a roller of an omni wheel), an algorithm will traverse the assembly to best determine the entire wheel component.
" + - "
This traversal operates on how the wheel is jointed and where the joint is placed. If the automatic selection fails, try:" + + "
If a sub-part of a wheel is selected (eg. a roller of an omni wheel), an algorithm will traverse the assembly to best determine the entire wheel component.
" + + "
This traversal operates on how the wheel is jointed and where the joint is placed. If the automatic selection fails, try:" + "" ) - + wheelTableInput.addCommandInput( algorithmicIndicator, 0, @@ -437,157 +454,158 @@ def notify(self, args): 3, ) - # AUTOMATICALLY SELECT DUPLICATES - """ - Select duplicates? - - creates a BoolValueCommandInput - """ - # self.createBooleanInput( # create bool value command input using helper - # "duplicate_selection", - # "Select Duplicates", - # wheel_inputs, - # checked=True, - # tooltip="Select duplicate wheel components.", - # tooltipadvanced="""
When this is checked, all duplicate occurrences will be automatically selected. - #
This feature may fail when duplicates are not direct copies.
""", # advanced tooltip - # enabled=True, - # ) + # Transition AARD-1685: + # This should be how all things in this class are handled. - Brandon + createJointConfigTab(args) + for joint in list( + gm.app.activeDocument.design.rootComponent.allJoints + ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): + if (joint.jointMotion.jointType == JointMotions.REVOLUTE.value + or joint.jointMotion.jointType == JointMotions.SLIDER.value + ) and not joint.isSuppressed: + addJointToConfigTab(joint) - # ~~~~~~~~~~~~~~~~ JOINT CONFIGURATION ~~~~~~~~~~~~~~~~ - """ - Joint configuration group. Container for joint selection table - """ - jointConfig = inputs.addGroupCommandInput( - "joint_config", "Joint Configuration" - ) - jointConfig.isExpanded = False - jointConfig.isVisible = True - jointConfig.tooltip = "Select and define joint occurrences in your assembly." - joint_inputs = jointConfig.children + # Transition AARD-1685: + # ~~~~~~~~~~~~~~~~ JOINT CONFIGURATION ~~~~~~~~~~~~~~~~ + # """ + # Joint configuration group. Container for joint selection table + # """ + # jointConfig = inputs.addGroupCommandInput( + # "joint_config", "Joint Configuration" + # ) + # jointConfig.isExpanded = False + # jointConfig.isVisible = True + # jointConfig.tooltip = "Select and define joint occurrences in your assembly." + + # joint_inputs = jointConfig.children + + # # JOINT SELECTION TABLE + # """ + # All selection joints appear here. + # """ + # jointTableInput = ( + # self.createTableInput( # create tablecommandinput using helper + # "joint_table", + # "Joint Table", + # joint_inputs, + # 6, + # "1:2:2:2:2:2", + # 50, + # ) + # ) - # JOINT SELECTION TABLE - """ - All selection joints appear here. - """ - jointTableInput = ( - self.createTableInput( # create tablecommandinput using helper - "joint_table", - "Joint Table", - joint_inputs, - 6, - "1:2:2:2:2:2", - 50, - ) - ) + # addJointInput = joint_inputs.addBoolValueInput( + # "joint_add", "Add", False + # ) # add button - addJointInput = joint_inputs.addBoolValueInput( - "joint_add", "Add", False - ) # add button + # removeJointInput = joint_inputs.addBoolValueInput( # remove button + # "joint_delete", "Remove", False + # ) - removeJointInput = joint_inputs.addBoolValueInput( # remove button - "joint_delete", "Remove", False - ) + # addJointInput.isEnabled = removeJointInput.isEnabled = True - addJointInput.isEnabled = removeJointInput.isEnabled = True + # addJointInput.tooltip = "Add a joint selection" # tooltips + # removeJointInput.tooltip = "Remove a joint selection" - addJointInput.tooltip = "Add a joint selection" # tooltips - removeJointInput.tooltip = "Remove a joint selection" + # jointSelectInput = joint_inputs.addSelectionInput( + # "joint_select", + # "Selection", + # "Select a joint in your drive-train assembly.", + # ) - jointSelectInput = joint_inputs.addSelectionInput( - "joint_select", - "Selection", - "Select a joint in your drive-train assembly.", - ) + # jointSelectInput.addSelectionFilter("Joints") # only allow joint selection + # jointSelectInput.setSelectionLimits(0) # set no selection count limits + # jointSelectInput.isEnabled = False + # jointSelectInput.isVisible = False # make selection box invisible + + # jointTableInput.addToolbarCommandInput( + # addJointInput + # ) # add bool inputs to the toolbar + # jointTableInput.addToolbarCommandInput( + # removeJointInput + # ) # add bool inputs to the toolbar + + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # create a textBoxCommandInput for the table header (Joint Motion), using helper + # "motion_header", + # "Motion", + # joint_inputs, + # "Motion", + # bold=False, + # ), + # 0, + # 0, + # ) - jointSelectInput.addSelectionFilter("Joints") # only allow joint selection - jointSelectInput.setSelectionLimits(0) # set no selection count limits - jointSelectInput.isEnabled = False - jointSelectInput.isVisible = False # make selection box invisible - - jointTableInput.addToolbarCommandInput( - addJointInput - ) # add bool inputs to the toolbar - jointTableInput.addToolbarCommandInput( - removeJointInput - ) # add bool inputs to the toolbar - - jointTableInput.addCommandInput( - self.createTextBoxInput( # create a textBoxCommandInput for the table header (Joint Motion), using helper - "motion_header", - "Motion", - joint_inputs, - "Motion", - bold=False, - ), - 0, - 0, - ) + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # textBoxCommandInput for table header (Joint Name), using helper + # "name_header", "Name", joint_inputs, "Joint name", bold=False + # ), + # 0, + # 1, + # ) - jointTableInput.addCommandInput( - self.createTextBoxInput( # textBoxCommandInput for table header (Joint Name), using helper - "name_header", "Name", joint_inputs, "Joint name", bold=False - ), - 0, - 1, - ) + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # another header using helper + # "parent_header", + # "Parent", + # joint_inputs, + # "Parent joint", + # background="#d9d9d9", # background color + # ), + # 0, + # 2, + # ) - jointTableInput.addCommandInput( - self.createTextBoxInput( # another header using helper - "parent_header", - "Parent", - joint_inputs, - "Parent joint", - background="#d9d9d9", # background color - ), - 0, - 2, - ) + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # another header using helper + # "signal_header", + # "Signal", + # joint_inputs, + # "Signal type", + # background="#d9d9d9", # back color + # ), + # 0, + # 3, + # ) - jointTableInput.addCommandInput( - self.createTextBoxInput( # another header using helper - "signal_header", - "Signal", - joint_inputs, - "Signal type", - background="#d9d9d9", # back color - ), - 0, - 3, - ) + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # another header using helper + # "speed_header", + # "Speed", + # joint_inputs, + # "Joint Speed", + # background="#d9d9d9", # back color + # ), + # 0, + # 4, + # ) - jointTableInput.addCommandInput( - self.createTextBoxInput( # another header using helper - "speed_header", - "Speed", - joint_inputs, - "Joint Speed", - background="#d9d9d9", # back color - ), - 0, - 4, - ) + # jointTableInput.addCommandInput( + # self.createTextBoxInput( # another header using helper + # "force_header", + # "Force", + # joint_inputs, + # "Joint Force", + # background="#d9d9d9", # back color + # ), + # 0, + # 5, + # ) - jointTableInput.addCommandInput( - self.createTextBoxInput( # another header using helper - "force_header", - "Force", - joint_inputs, - "Joint Force", - background="#d9d9d9", # back color - ), - 0, - 5, - ) + # Transition: AARD-1685 + # for joint in list( + # gm.app.activeDocument.design.rootComponent.allJoints + # ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): + # if ( + # joint.jointMotion.jointType == JointMotions.REVOLUTE.value + # or joint.jointMotion.jointType == JointMotions.SLIDER.value + # ) and not joint.isSuppressed: + # # Transition: AARD-1685 + # # addJointToTable(joint) + # addJointToConfigTab(args, joint) - for joint in list( - gm.app.activeDocument.design.rootComponent.allJoints - ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): - if ( - joint.jointMotion.jointType == JointMotions.REVOLUTE.value - or joint.jointMotion.jointType == JointMotions.SLIDER.value - ) and not joint.isSuppressed: - addJointToTable(joint) # ~~~~~~~~~~~~~~~~ GAMEPIECE CONFIGURATION ~~~~~~~~~~~~~~~~ """ @@ -996,6 +1014,7 @@ def notify(self, args): "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" ).error("Failed:\n{}".format(traceback.format_exc())) + # Transition: AARD-1685 def createBooleanInput( self, _id: str, @@ -1032,6 +1051,7 @@ def createBooleanInput( "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createBooleanInput()" ).error("Failed:\n{}".format(traceback.format_exc())) + # Transition: AARD-1685 def createTableInput( self, _id: str, @@ -1072,6 +1092,7 @@ def createTableInput( "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createTableInput()" ).error("Failed:\n{}".format(traceback.format_exc())) + # Transition: AARD-1685 def createTextBoxInput( self, _id: str, @@ -1256,7 +1277,7 @@ def notify(self, args): + ".mira" ) - if savepath == False: + if not savepath: # save was canceled return else: @@ -1274,7 +1295,7 @@ def notify(self, args): renderer = 0 _exportWheels = [] # all selected wheels, formatted for parseOptions - _exportJoints = [] # all selected joints, formatted for parseOptions + # _exportJoints = [] # all selected joints, formatted for parseOptions _exportGamepieces = [] # TODO work on the code to populate Gamepiece _robotWeight = float _mode = Mode @@ -1301,70 +1322,74 @@ def notify(self, args): WheelListGlobal[row - 1].entityToken, wheelTypeIndex, signalTypeIndex, - # onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint found, default to None + # onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint + # found, default to None ) ) + # Transition: AARD-1685 + _exportJoints = getSelectedJoints() + """ Loops through all rows in the joint table to extract the input values """ - jointTableInput = jointTable() - for row in range(jointTableInput.rowCount): - if row == 0: - continue - - parentJointIndex = jointTableInput.getInputAtPosition( - row, 2 - ).selectedItem.index # parent joint index, int - - signalTypeIndex = jointTableInput.getInputAtPosition( - row, 3 - ).selectedItem.index # signal type index, int - - # typeString = jointTableInput.getInputAtPosition( - # row, 0 - # ).name - - jointSpeed = jointTableInput.getInputAtPosition(row, 4).value - - jointForce = jointTableInput.getInputAtPosition(row, 5).value - - parentJointToken = "" - - if parentJointIndex == 0: - _exportJoints.append( - _Joint( - JointListGlobal[row - 1].entityToken, - JointParentType.ROOT, - signalTypeIndex, # index of selected signal in dropdown - jointSpeed, - jointForce / 100.0, - ) # parent joint GUID - ) - continue - elif parentJointIndex < row: - parentJointToken = JointListGlobal[ - parentJointIndex - 1 - ].entityToken # parent joint GUID, str - else: - parentJointToken = JointListGlobal[ - parentJointIndex + 1 - ].entityToken # parent joint GUID, str - - # for wheel in _exportWheels: - # find some way to get joint - # 1. Compare Joint occurrence1 to wheel.occurrence_token - # 2. if true set the parent to Root - - _exportJoints.append( - _Joint( - JointListGlobal[row - 1].entityToken, - parentJointToken, - signalTypeIndex, - jointSpeed, - jointForce, - ) - ) + # jointTableInput = jointTable() + # for row in range(jointTableInput.rowCount): + # if row == 0: + # continue + + # parentJointIndex = jointTableInput.getInputAtPosition( + # row, 2 + # ).selectedItem.index # parent joint index, int + + # signalTypeIndex = jointTableInput.getInputAtPosition( + # row, 3 + # ).selectedItem.index # signal type index, int + + # # typeString = jointTableInput.getInputAtPosition( + # # row, 0 + # # ).name + + # jointSpeed = jointTableInput.getInputAtPosition(row, 4).value + + # jointForce = jointTableInput.getInputAtPosition(row, 5).value + + # parentJointToken = "" + + # if parentJointIndex == 0: + # _exportJoints.append( + # _Joint( + # JointListGlobal[row - 1].entityToken, + # JointParentType.ROOT, + # signalTypeIndex, # index of selected signal in dropdown + # jointSpeed, + # jointForce / 100.0, + # ) # parent joint GUID + # ) + # continue + # elif parentJointIndex < row: + # parentJointToken = JointListGlobal[ + # parentJointIndex - 1 + # ].entityToken # parent joint GUID, str + # else: + # parentJointToken = JointListGlobal[ + # parentJointIndex + 1 + # ].entityToken # parent joint GUID, str + + # # for wheel in _exportWheels: + # # find some way to get joint + # # 1. Compare Joint occurrence1 to wheel.occurrence_token + # # 2. if true set the parent to Root + + # _exportJoints.append( + # _Joint( + # JointListGlobal[row - 1].entityToken, + # parentJointToken, + # signalTypeIndex, + # jointSpeed, + # jointForce, + # ) + # ) """ Loops through all rows in the gamepiece table to extract the input values @@ -1431,11 +1456,16 @@ def notify(self, args): if options.parse(False): # success - return + pass else: self.log.error( f"Error: \n\t{name} could not be written to \n {savepath}" ) + + # All selections should be reset AFTER a successful export and save. + # If we run into an exporting error we should return back to the panel with all current options + # still in tact. Even if they did not save. + resetSelectedJoints() except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) @@ -1469,15 +1499,21 @@ def notify(self, args): auto_calc_weight_f = INPUTS_ROOT.itemById("auto_calc_weight_f") removeWheelInput = INPUTS_ROOT.itemById("wheel_delete") - removeJointInput = INPUTS_ROOT.itemById("joint_delete") + removeJointInput = INPUTS_ROOT.itemById("jointRemoveButton") removeFieldInput = INPUTS_ROOT.itemById("field_delete") addWheelInput = INPUTS_ROOT.itemById("wheel_add") - addJointInput = INPUTS_ROOT.itemById("joint_add") + addJointInput = INPUTS_ROOT.itemById("jointAddButton") addFieldInput = INPUTS_ROOT.itemById("field_add") wheelTableInput = wheelTable() - jointTableInput = jointTable() + + # Transition: AARD-1685 + # jointTableInput = jointTable() + + inputs = args.command.commandInputs + jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById("jointTable") + gamepieceTableInput = gamepieceTable() if wheelTableInput.rowCount <= 1: @@ -1725,10 +1761,12 @@ def notify(self, args: adsk.core.SelectionEventArgs): WheelListGlobal.index(self.selectedJoint) ) else: - if self.selectedJoint not in JointListGlobal: - addJointToTable(self.selectedJoint) - else: - removeJointFromTable(self.selectedJoint) + # Transition: AARD-1685 + # if self.selectedJoint not in JointListGlobal: + addJointToConfigTab(self.selectedJoint) + # addJointToTable(self.selectedJoint) + # else: + # removeJointFromTable(self.selectedJoint) selectionInput.isEnabled = False selectionInput.isVisible = False @@ -1905,11 +1943,16 @@ def notify(self, args): frictionCoeff = INPUTS_ROOT.itemById("friction_coeff_override") wheelSelect = inputs.itemById("wheel_select") - jointSelect = inputs.itemById("joint_select") + jointSelect = inputs.itemById("jointSelection") gamepieceSelect = inputs.itemById("gamepiece_select") wheelTableInput = wheelTable() - jointTableInput = jointTable() + + # Transition: AARD-1685 + # jointTableInput = jointTable() + + jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") + gamepieceTableInput = gamepieceTable() weightTableInput = inputs.itemById("weight_table") @@ -1920,7 +1963,7 @@ def notify(self, args): gamepieceConfig = inputs.itemById("gamepiece_config") addWheelInput = INPUTS_ROOT.itemById("wheel_add") - addJointInput = INPUTS_ROOT.itemById("joint_add") + addJointInput = INPUTS_ROOT.itemById("jointAddButton") addFieldInput = INPUTS_ROOT.itemById("field_add") indicator = INPUTS_ROOT.itemById("algorithmic_indicator") @@ -2099,7 +2142,8 @@ def notify(self, args): addJointInput.isEnabled = True addWheelInput.isEnabled = False - elif cmdInput.id == "joint_add": + # Transition: AARD-1685 + elif cmdInput.id == "jointAddButton": self.reset() addWheelInput.isEnabled = True @@ -2128,7 +2172,7 @@ def notify(self, args): index = wheelTableInput.selectedRow - 1 removeWheelFromTable(index) - elif cmdInput.id == "joint_delete": + elif cmdInput.id == "jointRemoveButton": gm.ui.activeSelections.clear() addJointInput.isEnabled = True @@ -2138,8 +2182,13 @@ def notify(self, args): jointTableInput.selectedRow = jointTableInput.rowCount - 1 gm.ui.messageBox("Select a row to delete.") else: - joint = JointListGlobal[jointTableInput.selectedRow - 1] - removeJointFromTable(joint) + # Transition: AARD-1685 + # joint = JointListGlobal[jointTableInput.selectedRow - 1] + # removeJointFromTable(joint) + # removeJointFromConfigTab(joint) + + # Select Row is 1 indexed + removeIndexedJointFromConfigTab(jointTableInput.selectedRow - 1) elif cmdInput.id == "field_delete": gm.ui.activeSelections.clear() @@ -2159,7 +2208,7 @@ def notify(self, args): elif cmdInput.id == "wheel_select": addWheelInput.isEnabled = True - elif cmdInput.id == "joint_select": + elif cmdInput.id == "jointSelection": addJointInput.isEnabled = True elif cmdInput.id == "gamepiece_select": @@ -2168,7 +2217,7 @@ def notify(self, args): elif cmdInput.id == "friction_override": boolValue = adsk.core.BoolValueCommandInput.cast(cmdInput) - if boolValue.value == True: + if boolValue.value: frictionCoeff.isVisible = True else: frictionCoeff.isVisible = False @@ -2433,140 +2482,141 @@ def notify(self, args): ).error("Failed:\n{}".format(traceback.format_exc())) -def addJointToTable(joint: adsk.fusion.Joint) -> None: - """### Adds a Joint object to its global list and joint table. - - Args: - joint (adsk.fusion.Joint): Joint object to be added - """ - try: - JointListGlobal.append(joint) - jointTableInput = jointTable() - cmdInputs = adsk.core.CommandInputs.cast(jointTableInput.commandInputs) - - # joint type icons - if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Rigid", IconPaths.jointIcons["rigid"] - ) - icon.tooltip = "Rigid joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Revolute", IconPaths.jointIcons["revolute"] - ) - icon.tooltip = "Revolute joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Slider", IconPaths.jointIcons["slider"] - ) - icon.tooltip = "Slider joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Planar", IconPaths.jointIcons["planar"] - ) - icon.tooltip = "Planar joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"] - ) - icon.tooltip = "Pin slot joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"] - ) - icon.tooltip = "Cylindrical joint" - - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Ball", IconPaths.jointIcons["ball"] - ) - icon.tooltip = "Ball joint" - - # joint name - name = cmdInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) - name.tooltip = joint.name - name.formattedText = "

{}

".format(joint.name) - - jointType = cmdInputs.addDropDownCommandInput( - "joint_parent", - "Joint Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) - jointType.isFullWidth = True - jointType.listItems.add("Root", True) - - # after each additional joint added, add joint to the dropdown of all preview rows/joints - for row in range(jointTableInput.rowCount): - if row != 0: - dropDown = jointTableInput.getInputAtPosition(row, 2) - dropDown.listItems.add(JointListGlobal[-1].name, False) - - # add all parent joint options to added joint dropdown - for j in range(len(JointListGlobal) - 1): - jointType.listItems.add(JointListGlobal[j].name, False) - - jointType.tooltip = "Possible parent joints" - jointType.tooltipDescription = "
The root component is usually the parent." - - signalType = cmdInputs.addDropDownCommandInput( - "signal_type", - "Signal Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) - signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) - signalType.tooltip = "Signal type" - - row = jointTableInput.rowCount - - jointTableInput.addCommandInput(icon, row, 0) - jointTableInput.addCommandInput(name, row, 1) - jointTableInput.addCommandInput(jointType, row, 2) - jointTableInput.addCommandInput(signalType, row, 3) - - if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: - jointSpeed = cmdInputs.addValueInput( - "joint_speed", - "Speed", - "deg", - adsk.core.ValueInput.createByReal(3.1415926), - ) - jointSpeed.tooltip = "Degrees per second" - jointTableInput.addCommandInput(jointSpeed, row, 4) - - jointForce = cmdInputs.addValueInput( - "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) - ) - jointForce.tooltip = "Newton-Meters***" - jointTableInput.addCommandInput(jointForce, row, 5) - - if joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: - jointSpeed = cmdInputs.addValueInput( - "joint_speed", - "Speed", - "m", - adsk.core.ValueInput.createByReal(100), - ) - jointSpeed.tooltip = "Meters per second" - jointTableInput.addCommandInput(jointSpeed, row, 4) - - jointForce = cmdInputs.addValueInput( - "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) - ) - jointForce.tooltip = "Newtons" - jointTableInput.addCommandInput(jointForce, row, 5) - - except: - gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addJointToTable()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) +# Transition: AARD-1685 +# def addJointToTable(joint: adsk.fusion.Joint) -> None: +# """### Adds a Joint object to its global list and joint table. + +# Args: +# joint (adsk.fusion.Joint): Joint object to be added +# """ +# try: +# JointListGlobal.append(joint) +# jointTableInput = jointTable() +# cmdInputs = adsk.core.CommandInputs.cast(jointTableInput.commandInputs) + +# # joint type icons +# if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Rigid", IconPaths.jointIcons["rigid"] +# ) +# icon.tooltip = "Rigid joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Revolute", IconPaths.jointIcons["revolute"] +# ) +# icon.tooltip = "Revolute joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Slider", IconPaths.jointIcons["slider"] +# ) +# icon.tooltip = "Slider joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Planar", IconPaths.jointIcons["planar"] +# ) +# icon.tooltip = "Planar joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"] +# ) +# icon.tooltip = "Pin slot joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"] +# ) +# icon.tooltip = "Cylindrical joint" + +# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: +# icon = cmdInputs.addImageCommandInput( +# "placeholder", "Ball", IconPaths.jointIcons["ball"] +# ) +# icon.tooltip = "Ball joint" + +# # joint name +# name = cmdInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) +# name.tooltip = joint.name +# name.formattedText = "

{}

".format(joint.name) + +# jointType = cmdInputs.addDropDownCommandInput( +# "joint_parent", +# "Joint Type", +# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, +# ) +# jointType.isFullWidth = True +# jointType.listItems.add("Root", True) + +# # after each additional joint added, add joint to the dropdown of all preview rows/joints +# for row in range(jointTableInput.rowCount): +# if row != 0: +# dropDown = jointTableInput.getInputAtPosition(row, 2) +# dropDown.listItems.add(JointListGlobal[-1].name, False) + +# # add all parent joint options to added joint dropdown +# for j in range(len(JointListGlobal) - 1): +# jointType.listItems.add(JointListGlobal[j].name, False) + +# jointType.tooltip = "Possible parent joints" +# jointType.tooltipDescription = "
The root component is usually the parent." + +# signalType = cmdInputs.addDropDownCommandInput( +# "signal_type", +# "Signal Type", +# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, +# ) +# signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) +# signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) +# signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) +# signalType.tooltip = "Signal type" + +# row = jointTableInput.rowCount + +# jointTableInput.addCommandInput(icon, row, 0) +# jointTableInput.addCommandInput(name, row, 1) +# jointTableInput.addCommandInput(jointType, row, 2) +# jointTableInput.addCommandInput(signalType, row, 3) + +# if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: +# jointSpeed = cmdInputs.addValueInput( +# "joint_speed", +# "Speed", +# "deg", +# adsk.core.ValueInput.createByReal(3.1415926), +# ) +# jointSpeed.tooltip = "Degrees per second" +# jointTableInput.addCommandInput(jointSpeed, row, 4) + +# jointForce = cmdInputs.addValueInput( +# "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) +# ) +# jointForce.tooltip = "Newton-Meters***" +# jointTableInput.addCommandInput(jointForce, row, 5) + +# if joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: +# jointSpeed = cmdInputs.addValueInput( +# "joint_speed", +# "Speed", +# "m", +# adsk.core.ValueInput.createByReal(100), +# ) +# jointSpeed.tooltip = "Meters per second" +# jointTableInput.addCommandInput(jointSpeed, row, 4) + +# jointForce = cmdInputs.addValueInput( +# "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) +# ) +# jointForce.tooltip = "Newtons" +# jointTableInput.addCommandInput(jointForce, row, 5) + +# except: +# gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) + # logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addJointToTable()").error( + # "Failed:\n{}".format(traceback.format_exc()) + # ) def addWheelToTable(wheel: adsk.fusion.Joint) -> None: @@ -2759,42 +2809,43 @@ def removeWheelFromTable(index: int) -> None: ) -def removeJointFromTable(joint: adsk.fusion.Joint) -> None: - """### Removes a joint occurrence from its global list and joint table. - - Args: - joint (adsk.fusion.Joint): Joint object to be removed - """ - try: - index = JointListGlobal.index(joint) - jointTableInput = jointTable() - JointListGlobal.remove(joint) - - jointTableInput.deleteRow(index + 1) - - for row in range(jointTableInput.rowCount): - if row == 0: - continue - - dropDown = jointTableInput.getInputAtPosition(row, 2) - listItems = dropDown.listItems - - if row > index: - if listItems.item(index + 1).isSelected: - listItems.item(index).isSelected = True - listItems.item(index + 1).deleteMe() - else: - listItems.item(index + 1).deleteMe() - else: - if listItems.item(index).isSelected: - listItems.item(index - 1).isSelected = True - listItems.item(index).deleteMe() - else: - listItems.item(index).deleteMe() - except: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeJointFromTable()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) +# Transition: AARD-1685 +# def removeJointFromTable(joint: adsk.fusion.Joint) -> None: +# """### Removes a joint occurrence from its global list and joint table. + +# Args: +# joint (adsk.fusion.Joint): Joint object to be removed +# """ +# try: +# index = JointListGlobal.index(joint) +# jointTableInput = jointTable() +# JointListGlobal.remove(joint) + +# jointTableInput.deleteRow(index + 1) + +# for row in range(jointTableInput.rowCount): +# if row == 0: +# continue + +# dropDown = jointTableInput.getInputAtPosition(row, 2) +# listItems = dropDown.listItems + +# if row > index: +# if listItems.item(index + 1).isSelected: +# listItems.item(index).isSelected = True +# listItems.item(index + 1).deleteMe() +# else: +# listItems.item(index + 1).deleteMe() +# else: +# if listItems.item(index).isSelected: +# listItems.item(index - 1).isSelected = True +# listItems.item(index).deleteMe() +# else: +# listItems.item(index).deleteMe() +# except: +# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeJointFromTable()").error( +# "Failed:\n{}".format(traceback.format_exc()) +# ) def removeGamePieceFromTable(index: int) -> None: diff --git a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py new file mode 100644 index 0000000000..acdddc5858 --- /dev/null +++ b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py @@ -0,0 +1,93 @@ +import adsk.core +import traceback +import logging + + +def createTableInput( + id: str, + name: str, + inputs: adsk.core.CommandInputs, + columns: int, + ratio: str, + maxRows: int, + minRows=1, + columnSpacing=0, + rowSpacing=0, +) -> adsk.core.TableCommandInput: + try: + input = inputs.addTableCommandInput(id, name, columns, ratio) + input.minimumVisibleRows = minRows + input.maximumVisibleRows = maxRows + input.columnSpacing = columnSpacing + input.rowSpacing = rowSpacing + + return input + except BaseException: + logging.getLogger( + "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createTableInput()" + ).error("Failed:\n{}".format(traceback.format_exc())) + + +def createBooleanInput( + id: str, + name: str, + inputs: adsk.core.CommandInputs, + tooltip="", + tooltipadvanced="", + checked=True, + enabled=True, + isCheckBox=True, +) -> adsk.core.BoolValueCommandInput: + try: + input = inputs.addBoolValueInput(id, name, isCheckBox) + input.value = checked + input.isEnabled = enabled + input.tooltip = tooltip + input.tooltipDescription = tooltipadvanced + + return input + except BaseException: + logging.getLogger( + "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createBooleanInput()" + ).error("Failed:\n{}".format(traceback.format_exc())) + + +def createTextBoxInput( + id: str, + name: str, + inputs: adsk.core.CommandInputs, + text: str, + italics=True, + bold=True, + fontSize=10, + alignment="center", + rowCount=1, + read=True, + background="whitesmoke", + tooltip="", + advanced_tooltip="", +) -> adsk.core.TextBoxCommandInput: + try: + if bold: + text = f"{text}" + + if italics: + text = f"{text}" + + outputText = f""" +
+

+ {text} +

+ + """ + + input = inputs.addTextBoxCommandInput(id, name, outputText, rowCount, read) + input.tooltip = tooltip + input.tooltipDescription = advanced_tooltip + + return input + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.createTextBoxInput()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) diff --git a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py index 9b99310657..5906c0d148 100644 --- a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py +++ b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py @@ -1,4 +1,7 @@ -import adsk.fusion, adsk.core, traceback, logging +import adsk.fusion +import adsk.core +import traceback +import logging from ..general_imports import * diff --git a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py index 0dd7e9d88b..5807fe15c3 100644 --- a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py +++ b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py @@ -4,7 +4,8 @@ from ..Types.OString import OString from typing import Union -import adsk.core, adsk.fusion +import adsk.core +import adsk.fusion def SaveFileDialog( diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py new file mode 100644 index 0000000000..a360fca8a4 --- /dev/null +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -0,0 +1,305 @@ +import logging +import traceback + +import adsk.core +import adsk.fusion + +from . import IconPaths +from .CreateCommandInputsHelper import createTableInput, createTextBoxInput + +from ..Parser.ParseOptions import _Joint, JointParentType + +# Wish we did not need this. Could look into storing everything within the design every time - Brandon +selectedJointList: list[adsk.fusion.Joint] = [] +jointConfigTable: adsk.core.TableCommandInput + + +def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: + try: + inputs = args.command.commandInputs + jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") + jointConfigTab.tooltip = "Select and configure robot joints." + jointConfigTabInputs = jointConfigTab.children + + # TODO: Change background colors and such - Brandon + global jointConfigTable + jointConfigTable = createTableInput( + "jointTable", + "Joint Table", + jointConfigTabInputs, + 6, + "1:2:2:2:2:2", + 50, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "motionHeader", + "Motion", + jointConfigTabInputs, + "Motion", + bold=False, + ), + 0, + 0, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False + ), + 0, + 1, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "parentHeader", + "Parent", + jointConfigTabInputs, + "Parent joint", + background="#d9d9d9", + ), + 0, + 2, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "signalHeader", + "Signal", + jointConfigTabInputs, + "Signal type", + background="#d9d9d9", + ), + 0, + 3, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "speedHeader", + "Speed", + jointConfigTabInputs, + "Joint Speed", + background="#d9d9d9", + ), + 0, + 4, + ) + + jointConfigTable.addCommandInput( + createTextBoxInput( + "forceHeader", + "Force", + jointConfigTabInputs, + "Joint Force", + background="#d9d9d9", + ), + 0, + 5, + ) + + jointSelect = jointConfigTabInputs.addSelectionInput( + "jointSelection", "Selection", "Select a joint in your assembly to add." + ) + jointSelect.addSelectionFilter("Joints") + jointSelect.setSelectionLimits(0) + + # Visibility is triggered by `addJointInputButton` + jointSelect.isEnabled = jointSelect.isVisible = False + + addJointInputButton = jointConfigTabInputs.addBoolValueInput("jointAddButton", "Add", False) + removeJointInputButton = jointConfigTabInputs.addBoolValueInput("jointRemoveButton", "Remove", False) + addJointInputButton.isEnabled = removeJointInputButton.isEnabled = True + + jointConfigTable.addToolbarCommandInput(addJointInputButton) + jointConfigTable.addToolbarCommandInput(removeJointInputButton) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + + +def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: + try: + if joint in selectedJointList: + removeJointFromConfigTab(joint) + return + + selectedJointList.append(joint) + commandInputs = jointConfigTable.commandInputs + + if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Rigid", IconPaths.jointIcons["rigid"]) + icon.tooltip = "Rigid joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Revolute", IconPaths.jointIcons["revolute"]) + icon.tooltip = "Revolute joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Slider", IconPaths.jointIcons["slider"]) + icon.tooltip = "Slider joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Planar", IconPaths.jointIcons["planar"]) + icon.tooltip = "Planar joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"]) + icon.tooltip = "Pin slot joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"]) + icon.tooltip = "Cylindrical joint" + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Ball", IconPaths.jointIcons["ball"]) + icon.tooltip = "Ball joint" + + name = commandInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) + name.tooltip = joint.name + name.formattedText = f"

{joint.name}

" + + jointType = commandInputs.addDropDownCommandInput( + "jointParent", + "Joint Type", + dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, + ) + + jointType.isFullWidth = True + jointType.listItems.add("Root", True) + + for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed + dropDown = jointConfigTable.getInputAtPosition(row, 2) + dropDown.listItems.add(selectedJointList[-1].name, False) + + for j in range(len(selectedJointList) - 1): + jointType.listItems.add(selectedJointList[j].name, False) + + jointType.tooltip = "Possible parent joints" + jointType.tooltipDescription = "
The root component is usually the parent." + + signalType = commandInputs.addDropDownCommandInput( + "signalType", + "Signal Type", + dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, + ) + signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) + signalType.tooltip = "Signal type" + + row = jointConfigTable.rowCount + jointConfigTable.addCommandInput(icon, row, 0) + jointConfigTable.addCommandInput(name, row, 1) + jointConfigTable.addCommandInput(jointType, row, 2) + jointConfigTable.addCommandInput(signalType, row, 3) + + # Joint speed must be added within an `if` because there is variance between different joint types + if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + jointSpeed = commandInputs.addValueInput( + "jointSpeed", + "Speed", + "deg", + adsk.core.ValueInput.createByReal(3.1415926), + ) + jointSpeed.tooltip = "Degrees per second" + jointConfigTable.addCommandInput(jointSpeed, row, 4) + + elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + jointSpeed = commandInputs.addValueInput( + "jointSpeed", + "Speed", + "m", + adsk.core.ValueInput.createByReal(100), + ) + jointSpeed.tooltip = "Meters per second" + jointConfigTable.addCommandInput(jointSpeed, row, 4) + + jointForce = commandInputs.addValueInput("jointForce", "Force", "N", adsk.core.ValueInput.createByReal(5000)) + jointForce.tooltip = "Newtons" + jointConfigTable.addCommandInput(jointForce, row, 5) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + + +def removeIndexedJointFromConfigTab(index: int) -> None: + try: + removeJointFromConfigTab(selectedJointList[index]) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeIndexedJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + + +def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: + try: + i = selectedJointList.index(joint) + selectedJointList.remove(joint) + + jointConfigTable.deleteRow(i + 1) + for row in range(jointConfigTable.rowCount): # Row is 1 indexed + listItems = jointConfigTable.getInputAtPosition(row, 2).listItems + if row > i: + if listItems.item(i + 1).isSelected: + listItems.item(i).isSelected = True + listItems.item(i + 1).deleteMe() + else: + listItems.item(i + 1).deleteMe() + else: + if listItems.item(i).isSelected: + listItems.item(i - 1).isSelected = True + listItems.item(i).deleteMe() + else: + listItems.item(i).deleteMe() + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + + +# Converts the current list of selected adsk.fusion.joints into Synthesis.Joints +def getSelectedJoints() -> list[_Joint]: + joints: list[_Joint] = [] + for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed + parentJointIndex = jointConfigTable.getInputAtPosition(row, 2).selectedItem.index + signalTypeIndex = jointConfigTable.getInputAtPosition(row, 3).selectedItem.index + jointSpeed = jointConfigTable.getInputAtPosition(row, 4).value + jointForce = jointConfigTable.getInputAtPosition(row, 5).value + parentJointToken = "" + + if parentJointIndex == 0: + joints.append( + _Joint( + selectedJointList[row - 1].entityToken, # Row is 1 indexed + JointParentType.ROOT, + signalTypeIndex, + jointSpeed, + jointForce / 100.0, + ) + ) + continue + elif parentJointIndex < row: + parentJointToken = selectedJointList[parentJointIndex - 1].entityToken + else: + parentJointToken = selectedJointList[parentJointIndex + 1].entityToken + + joints.append( + _Joint( + selectedJointList[row - 1].entityToken, + parentJointToken, + signalTypeIndex, + jointSpeed, + jointForce, + ) + ) + + return joints + + +def resetSelectedJoints() -> None: + selectedJointList.clear() diff --git a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py index 0a1fbadcbf..5c03d0168f 100644 --- a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py +++ b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py @@ -1,7 +1,10 @@ -import adsk.core, adsk.fusion, traceback +import adsk.core +import adsk.fusion +import traceback import logging.handlers -# Ripped all the boiler plate from the example code: https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622 +# Ripped all the boiler plate from the example code: +# https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622 # global mapping list of event handlers to keep them referenced for the duration of the command # handlers = {} diff --git a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py index 956c9f6fd1..3c006e3113 100644 --- a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py +++ b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py @@ -1,4 +1,5 @@ -import os, platform +import os +import platform def getOSPath(*argv) -> str: @@ -46,7 +47,7 @@ def getOS(): return platform.system() -""" Old code I believe +""" Old code I believe def openFileLocation(fileLoc: str) -> bool: osName = getOS() if osName == "Windows" or osName == "win32": diff --git a/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py b/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py index 9e274e7148..e972f2ae8e 100644 --- a/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py +++ b/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py @@ -14,7 +14,7 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: try: onSelect = gm.handlers[3] wheelTableInput = INPUTS_ROOT.itemById("wheel_table") - + # def addPreselections(child_occurrences): # for occ in child_occurrences: # onSelect.allWheelPreselections.append(occ.entityToken) @@ -22,7 +22,7 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: # if occ.childOccurrences: # addPreselections(occ.childOccurrences) - # if wheel.childOccurrences: + # if wheel.childOccurrences: # addPreselections(wheel.childOccurrences) # else: # onSelect.allWheelPreselections.append(wheel.entityToken) @@ -198,7 +198,7 @@ def addGamepieceToTable(gamepiece: adsk.fusion.Occurrence) -> None: def addPreselections(child_occurrences): for occ in child_occurrences: onSelect.allGamepiecePreselections.append(occ.entityToken) - + if occ.childOccurrences: addPreselections(occ.childOccurrences) @@ -249,7 +249,7 @@ def addPreselections(child_occurrences): "friction_coeff", "", "", valueList ) friction_coeff.valueOne = 0.5 - + type.tooltip = gamepiece.name weight.tooltip = "Weight of field element" @@ -354,7 +354,7 @@ def removeGamePieceFromTable(index: int) -> None: def removePreselections(child_occurrences): for occ in child_occurrences: onSelect.allGamepiecePreselections.remove(occ.entityToken) - + if occ.childOccurrences: removePreselections(occ.childOccurrences) try: From fdb0076181a0c842ce8003497b463c92a0737ec9 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 14:11:08 -0700 Subject: [PATCH 02/21] Updated transition comments and removed replaced code --- .../src/UI/ConfigCommand.py | 342 +----------------- 1 file changed, 4 insertions(+), 338 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index a682ef8556..b61e42d1e3 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -21,10 +21,6 @@ from .Configuration.SerialCommand import SerialCommand # Transition: AARD-1685 -from .CreateCommandInputsHelper import ( - createTextBoxInput, - createTableInput, -) from .JointConfigTab import ( createJointConfigTab, addJointToConfigTab, @@ -465,148 +461,6 @@ def notify(self, args): ) and not joint.isSuppressed: addJointToConfigTab(joint) - - # Transition AARD-1685: - # ~~~~~~~~~~~~~~~~ JOINT CONFIGURATION ~~~~~~~~~~~~~~~~ - # """ - # Joint configuration group. Container for joint selection table - # """ - # jointConfig = inputs.addGroupCommandInput( - # "joint_config", "Joint Configuration" - # ) - # jointConfig.isExpanded = False - # jointConfig.isVisible = True - # jointConfig.tooltip = "Select and define joint occurrences in your assembly." - - # joint_inputs = jointConfig.children - - # # JOINT SELECTION TABLE - # """ - # All selection joints appear here. - # """ - # jointTableInput = ( - # self.createTableInput( # create tablecommandinput using helper - # "joint_table", - # "Joint Table", - # joint_inputs, - # 6, - # "1:2:2:2:2:2", - # 50, - # ) - # ) - - # addJointInput = joint_inputs.addBoolValueInput( - # "joint_add", "Add", False - # ) # add button - - # removeJointInput = joint_inputs.addBoolValueInput( # remove button - # "joint_delete", "Remove", False - # ) - - # addJointInput.isEnabled = removeJointInput.isEnabled = True - - # addJointInput.tooltip = "Add a joint selection" # tooltips - # removeJointInput.tooltip = "Remove a joint selection" - - # jointSelectInput = joint_inputs.addSelectionInput( - # "joint_select", - # "Selection", - # "Select a joint in your drive-train assembly.", - # ) - - # jointSelectInput.addSelectionFilter("Joints") # only allow joint selection - # jointSelectInput.setSelectionLimits(0) # set no selection count limits - # jointSelectInput.isEnabled = False - # jointSelectInput.isVisible = False # make selection box invisible - - # jointTableInput.addToolbarCommandInput( - # addJointInput - # ) # add bool inputs to the toolbar - # jointTableInput.addToolbarCommandInput( - # removeJointInput - # ) # add bool inputs to the toolbar - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # create a textBoxCommandInput for the table header (Joint Motion), using helper - # "motion_header", - # "Motion", - # joint_inputs, - # "Motion", - # bold=False, - # ), - # 0, - # 0, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # textBoxCommandInput for table header (Joint Name), using helper - # "name_header", "Name", joint_inputs, "Joint name", bold=False - # ), - # 0, - # 1, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "parent_header", - # "Parent", - # joint_inputs, - # "Parent joint", - # background="#d9d9d9", # background color - # ), - # 0, - # 2, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "signal_header", - # "Signal", - # joint_inputs, - # "Signal type", - # background="#d9d9d9", # back color - # ), - # 0, - # 3, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "speed_header", - # "Speed", - # joint_inputs, - # "Joint Speed", - # background="#d9d9d9", # back color - # ), - # 0, - # 4, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "force_header", - # "Force", - # joint_inputs, - # "Joint Force", - # background="#d9d9d9", # back color - # ), - # 0, - # 5, - # ) - - # Transition: AARD-1685 - # for joint in list( - # gm.app.activeDocument.design.rootComponent.allJoints - # ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): - # if ( - # joint.jointMotion.jointType == JointMotions.REVOLUTE.value - # or joint.jointMotion.jointType == JointMotions.SLIDER.value - # ) and not joint.isSuppressed: - # # Transition: AARD-1685 - # # addJointToTable(joint) - # addJointToConfigTab(args, joint) - - # ~~~~~~~~~~~~~~~~ GAMEPIECE CONFIGURATION ~~~~~~~~~~~~~~~~ """ Gamepiece group command input, isVisible=False by default @@ -1015,6 +869,7 @@ def notify(self, args): ).error("Failed:\n{}".format(traceback.format_exc())) # Transition: AARD-1685 + # Functionality will be fully moved to `CreateCommandInputsHelper` in AARD-1683 def createBooleanInput( self, _id: str, @@ -1052,6 +907,7 @@ def createBooleanInput( ).error("Failed:\n{}".format(traceback.format_exc())) # Transition: AARD-1685 + # Functionality will be fully moved to `CreateCommandInputsHelper` in AARD-1683 def createTableInput( self, _id: str, @@ -1093,6 +949,7 @@ def createTableInput( ).error("Failed:\n{}".format(traceback.format_exc())) # Transition: AARD-1685 + # Functionality will be fully moved to `CreateCommandInputsHelper` in AARD-1683 def createTextBoxInput( self, _id: str, @@ -1508,9 +1365,6 @@ def notify(self, args): wheelTableInput = wheelTable() - # Transition: AARD-1685 - # jointTableInput = jointTable() - inputs = args.command.commandInputs jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById("jointTable") @@ -1761,12 +1615,8 @@ def notify(self, args: adsk.core.SelectionEventArgs): WheelListGlobal.index(self.selectedJoint) ) else: - # Transition: AARD-1685 - # if self.selectedJoint not in JointListGlobal: + # Will prompt for removal if already selected. addJointToConfigTab(self.selectedJoint) - # addJointToTable(self.selectedJoint) - # else: - # removeJointFromTable(self.selectedJoint) selectionInput.isEnabled = False selectionInput.isVisible = False @@ -1948,9 +1798,6 @@ def notify(self, args): wheelTableInput = wheelTable() - # Transition: AARD-1685 - # jointTableInput = jointTable() - jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") gamepieceTableInput = gamepieceTable() @@ -2182,11 +2029,6 @@ def notify(self, args): jointTableInput.selectedRow = jointTableInput.rowCount - 1 gm.ui.messageBox("Select a row to delete.") else: - # Transition: AARD-1685 - # joint = JointListGlobal[jointTableInput.selectedRow - 1] - # removeJointFromTable(joint) - # removeJointFromConfigTab(joint) - # Select Row is 1 indexed removeIndexedJointFromConfigTab(jointTableInput.selectedRow - 1) @@ -2482,143 +2324,6 @@ def notify(self, args): ).error("Failed:\n{}".format(traceback.format_exc())) -# Transition: AARD-1685 -# def addJointToTable(joint: adsk.fusion.Joint) -> None: -# """### Adds a Joint object to its global list and joint table. - -# Args: -# joint (adsk.fusion.Joint): Joint object to be added -# """ -# try: -# JointListGlobal.append(joint) -# jointTableInput = jointTable() -# cmdInputs = adsk.core.CommandInputs.cast(jointTableInput.commandInputs) - -# # joint type icons -# if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Rigid", IconPaths.jointIcons["rigid"] -# ) -# icon.tooltip = "Rigid joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Revolute", IconPaths.jointIcons["revolute"] -# ) -# icon.tooltip = "Revolute joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Slider", IconPaths.jointIcons["slider"] -# ) -# icon.tooltip = "Slider joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Planar", IconPaths.jointIcons["planar"] -# ) -# icon.tooltip = "Planar joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"] -# ) -# icon.tooltip = "Pin slot joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"] -# ) -# icon.tooltip = "Cylindrical joint" - -# elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: -# icon = cmdInputs.addImageCommandInput( -# "placeholder", "Ball", IconPaths.jointIcons["ball"] -# ) -# icon.tooltip = "Ball joint" - -# # joint name -# name = cmdInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) -# name.tooltip = joint.name -# name.formattedText = "

{}

".format(joint.name) - -# jointType = cmdInputs.addDropDownCommandInput( -# "joint_parent", -# "Joint Type", -# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, -# ) -# jointType.isFullWidth = True -# jointType.listItems.add("Root", True) - -# # after each additional joint added, add joint to the dropdown of all preview rows/joints -# for row in range(jointTableInput.rowCount): -# if row != 0: -# dropDown = jointTableInput.getInputAtPosition(row, 2) -# dropDown.listItems.add(JointListGlobal[-1].name, False) - -# # add all parent joint options to added joint dropdown -# for j in range(len(JointListGlobal) - 1): -# jointType.listItems.add(JointListGlobal[j].name, False) - -# jointType.tooltip = "Possible parent joints" -# jointType.tooltipDescription = "
The root component is usually the parent." - -# signalType = cmdInputs.addDropDownCommandInput( -# "signal_type", -# "Signal Type", -# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, -# ) -# signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) -# signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) -# signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) -# signalType.tooltip = "Signal type" - -# row = jointTableInput.rowCount - -# jointTableInput.addCommandInput(icon, row, 0) -# jointTableInput.addCommandInput(name, row, 1) -# jointTableInput.addCommandInput(jointType, row, 2) -# jointTableInput.addCommandInput(signalType, row, 3) - -# if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: -# jointSpeed = cmdInputs.addValueInput( -# "joint_speed", -# "Speed", -# "deg", -# adsk.core.ValueInput.createByReal(3.1415926), -# ) -# jointSpeed.tooltip = "Degrees per second" -# jointTableInput.addCommandInput(jointSpeed, row, 4) - -# jointForce = cmdInputs.addValueInput( -# "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) -# ) -# jointForce.tooltip = "Newton-Meters***" -# jointTableInput.addCommandInput(jointForce, row, 5) - -# if joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: -# jointSpeed = cmdInputs.addValueInput( -# "joint_speed", -# "Speed", -# "m", -# adsk.core.ValueInput.createByReal(100), -# ) -# jointSpeed.tooltip = "Meters per second" -# jointTableInput.addCommandInput(jointSpeed, row, 4) - -# jointForce = cmdInputs.addValueInput( -# "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) -# ) -# jointForce.tooltip = "Newtons" -# jointTableInput.addCommandInput(jointForce, row, 5) - -# except: -# gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - # logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addJointToTable()").error( - # "Failed:\n{}".format(traceback.format_exc()) - # ) - - def addWheelToTable(wheel: adsk.fusion.Joint) -> None: """### Adds a wheel occurrence to its global list and wheel table. @@ -2809,45 +2514,6 @@ def removeWheelFromTable(index: int) -> None: ) -# Transition: AARD-1685 -# def removeJointFromTable(joint: adsk.fusion.Joint) -> None: -# """### Removes a joint occurrence from its global list and joint table. - -# Args: -# joint (adsk.fusion.Joint): Joint object to be removed -# """ -# try: -# index = JointListGlobal.index(joint) -# jointTableInput = jointTable() -# JointListGlobal.remove(joint) - -# jointTableInput.deleteRow(index + 1) - -# for row in range(jointTableInput.rowCount): -# if row == 0: -# continue - -# dropDown = jointTableInput.getInputAtPosition(row, 2) -# listItems = dropDown.listItems - -# if row > index: -# if listItems.item(index + 1).isSelected: -# listItems.item(index).isSelected = True -# listItems.item(index + 1).deleteMe() -# else: -# listItems.item(index + 1).deleteMe() -# else: -# if listItems.item(index).isSelected: -# listItems.item(index - 1).isSelected = True -# listItems.item(index).deleteMe() -# else: -# listItems.item(index).deleteMe() -# except: -# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeJointFromTable()").error( -# "Failed:\n{}".format(traceback.format_exc()) -# ) - - def removeGamePieceFromTable(index: int) -> None: """### Removes a gamepiece occurrence from its global list and gamepiece table. From 837d83cb9e7a0e38bfccbd85ff949a40f42a4740 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 14:43:57 -0700 Subject: [PATCH 03/21] Handled transition tags --- .../src/UI/ConfigCommand.py | 200 +----------------- 1 file changed, 4 insertions(+), 196 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 1a940c87f2..b2062cd340 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -419,134 +419,6 @@ def notify(self, args): )[0] addWheelToTable(wheelEntity) - # Transition: AARD-1685 - # ~~~~~~~~~~~~~~~~ JOINT CONFIGURATION ~~~~~~~~~~~~~~~~ - """ - Joint configuration group. Container for joint selection table - """ - # jointConfig = inputs.addGroupCommandInput( - # "joint_config", "Joint Configuration" - # ) - # jointConfig.isExpanded = False - # jointConfig.isVisible = True - # jointConfig.tooltip = "Select and define joint occurrences in your assembly." - - # joint_inputs = jointConfig.children - - # # JOINT SELECTION TABLE - # """ - # All selection joints appear here. - # """ - # jointTableInput = ( - # self.createTableInput( # create tablecommandinput using helper - # "joint_table", - # "Joint Table", - # joint_inputs, - # 6, - # "1:2:2:2:2:2", - # 50, - # ) - # ) - - # addJointInput = joint_inputs.addBoolValueInput( - # "joint_add", "Add", False - # ) # add button - - # removeJointInput = joint_inputs.addBoolValueInput( # remove button - # "joint_delete", "Remove", False - # ) - - # addJointInput.isEnabled = removeJointInput.isEnabled = True - - # addJointInput.tooltip = "Add a joint selection" # tooltips - # removeJointInput.tooltip = "Remove a joint selection" - - # jointSelectInput = joint_inputs.addSelectionInput( - # "joint_select", - # "Selection", - # "Select a joint in your drive-train assembly.", - # ) - - # jointSelectInput.addSelectionFilter("Joints") # only allow joint selection - # jointSelectInput.setSelectionLimits(0) # set no selection count limits - # jointSelectInput.isEnabled = False - # jointSelectInput.isVisible = False # make selection box invisible - - # jointTableInput.addToolbarCommandInput( - # addJointInput - # ) # add bool inputs to the toolbar - # jointTableInput.addToolbarCommandInput( - # removeJointInput - # ) # add bool inputs to the toolbar - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # create a textBoxCommandInput for the table header (Joint Motion), using helper - # "motion_header", - # "Motion", - # joint_inputs, - # "Motion", - # bold=False, - # ), - # 0, - # 0, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # textBoxCommandInput for table header (Joint Name), using helper - # "name_header", "Name", joint_inputs, "Joint name", bold=False - # ), - # 0, - # 1, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "parent_header", - # "Parent", - # joint_inputs, - # "Parent joint", - # background="#d9d9d9", # background color - # ), - # 0, - # 2, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "signal_header", - # "Signal", - # joint_inputs, - # "Signal type", - # background="#d9d9d9", # back color - # ), - # 0, - # 3, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "speed_header", - # "Speed", - # joint_inputs, - # "Joint Speed", - # background="#d9d9d9", # back color - # ), - # 0, - # 4, - # ) - - # jointTableInput.addCommandInput( - # self.createTextBoxInput( # another header using helper - # "force_header", - # "Force", - # joint_inputs, - # "Joint Force", - # background="#d9d9d9", # back color - # ), - # 0, - # 5, - # ) - # Transition: AARD-1685 createJointConfigTab(args) for joint in list( @@ -1129,9 +1001,7 @@ def notify(self, args): name = design.rootComponent.name.rsplit(" ", 1)[0] version = design.rootComponent.name.rsplit(" ", 1)[1] - # Transition: AARD-1685 _exportWheels = [] # all selected wheels, formatted for parseOptions - _exportJoints = [] # all selected joints, formatted for parseOptions _exportGamepieces = [] # TODO work on the code to populate Gamepiece _robotWeight = float _mode = ExportMode.ROBOT @@ -1162,71 +1032,6 @@ def notify(self, args): ) ) - # Transition: AARD-1685 - _exportJoints = getSelectedJoints() - - # Transition: AARD-1685 - """ - Loops through all rows in the joint table to extract the input values - """ - # jointTableInput = jointTable() - # for row in range(jointTableInput.rowCount): - # if row == 0: - # continue - - # parentJointIndex = jointTableInput.getInputAtPosition( - # row, 2 - # ).selectedItem.index # parent joint index, int - - # signalTypeIndex = jointTableInput.getInputAtPosition( - # row, 3 - # ).selectedItem.index # signal type index, int - - # # typeString = jointTableInput.getInputAtPosition( - # # row, 0 - # # ).name - - # jointSpeed = jointTableInput.getInputAtPosition(row, 4).value - - # jointForce = jointTableInput.getInputAtPosition(row, 5).value - - # parentJointToken = "" - - # if parentJointIndex == 0: - # _exportJoints.append( - # _Joint( - # JointListGlobal[row - 1].entityToken, - # JointParentType.ROOT, - # signalTypeIndex, # index of selected signal in dropdown - # jointSpeed, - # jointForce / 100.0, - # ) # parent joint GUID - # ) - # continue - # elif parentJointIndex < row: - # parentJointToken = JointListGlobal[ - # parentJointIndex - 1 - # ].entityToken # parent joint GUID, str - # else: - # parentJointToken = JointListGlobal[ - # parentJointIndex + 1 - # ].entityToken # parent joint GUID, str - - # # for wheel in _exportWheels: - # # find some way to get joint - # # 1. Compare Joint occurrence1 to wheel.occurrence_token - # # 2. if true set the parent to Root - - # _exportJoints.append( - # _Joint( - # JointListGlobal[row - 1].entityToken, - # parentJointToken, - # signalTypeIndex, - # jointSpeed, - # jointForce, - # ) - # ) - """ Loops through all rows in the gamepiece table to extract the input values """ @@ -1289,7 +1094,7 @@ def notify(self, args): name, version, materials=0, - joints=_exportJoints, + joints=getSelectedJoints(), wheels=_exportWheels, gamepieces=_exportGamepieces, preferredUnits=selectedUnits, @@ -1972,6 +1777,7 @@ def notify(self, args): addWheelInput.isEnabled = False # Transition: AARD-1685 + # Functionality could potentially be moved into `JointConfigTab.py` elif cmdInput.id == "jointAddButton": self.reset() @@ -2001,6 +1807,8 @@ def notify(self, args): index = wheelTableInput.selectedRow - 1 removeWheelFromTable(index) + # Transition: AARD-1685 + # Functionality could potentially be moved into `JointConfigTab.py` elif cmdInput.id == "jointRemoveButton": gm.ui.activeSelections.clear() From 90f96c923f32af0a127a45c393490a5cee2e29d3 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 15:12:08 -0700 Subject: [PATCH 04/21] Readabliity cleanups --- .../src/Parser/ExporterOptions.py | 2 +- .../src/UI/ConfigCommand.py | 25 ++++++++++--------- .../src/UI/JointConfigTab.py | 6 ++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py index 65dfbab62c..0f56b4338f 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py @@ -102,7 +102,7 @@ class ExporterOptions: default=CalculationAccuracy.LowCalculationAccuracy ) - def readFromDesign(self) -> None: + def readFromDesign(self) -> "ExporterOptions": designAttributes = adsk.core.Application.get().activeProduct.attributes for field in fields(self): attribute = designAttributes.itemByName(INTERNAL_ID, field.name) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index b2062cd340..5a6e8fb480 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -14,16 +14,15 @@ Gamepiece, ExportMode, ExporterOptions, - Joint, Wheel, WheelType, SignalType, - JointParentType, PreferredUnits, ) from .Configuration.SerialCommand import SerialCommand # Transition: AARD-1685 +# In the future all components should be handled in this way. from .JointConfigTab import ( createJointConfigTab, addJointToConfigTab, @@ -414,20 +413,22 @@ def notify(self, args): if exporterOptions.wheels: for wheel in exporterOptions.wheels: - wheelEntity = gm.app.activeDocument.design.findEntityByToken( - wheel.jointToken - )[0] + wheelEntity = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] addWheelToTable(wheelEntity) # Transition: AARD-1685 createJointConfigTab(args) - for joint in list( - gm.app.activeDocument.design.rootComponent.allJoints - ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): - if (joint.jointMotion.jointType == JointMotions.REVOLUTE.value - or joint.jointMotion.jointType == JointMotions.SLIDER.value - ) and not joint.isSuppressed: - addJointToConfigTab(joint) + if exporterOptions.joints: + for joint in exporterOptions.joints: + jointEntity = gm.app.activeDocument.design.findEntityByToken(joint.jointToken)[0] + addJointToConfigTab(jointEntity) + else: + for joint in [ + *gm.app.activeDocument.design.rootComponent.allJoints, + *gm.app.activeDocument.design.rootComponent.allAsBuiltJoints + ]: + if joint.jointMotion.jointType in (JointMotions.REVOLUTE.value, JointMotions.SLIDER.value) and not joint.isSuppressed: + addJointToConfigTab(joint) # ~~~~~~~~~~~~~~~~ GAMEPIECE CONFIGURATION ~~~~~~~~~~~~~~~~ """ diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index 27e342149a..03b111e93e 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -175,8 +175,8 @@ def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: dropDown = jointConfigTable.getInputAtPosition(row, 2) dropDown.listItems.add(selectedJointList[-1].name, False) - for j in range(len(selectedJointList) - 1): - jointType.listItems.add(selectedJointList[j].name, False) + for joint in selectedJointList: + jointType.listItems.add(joint.name, False) jointType.tooltip = "Possible parent joints" jointType.tooltipDescription = "
The root component is usually the parent." @@ -262,7 +262,7 @@ def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: ) -# Converts the current list of selected adsk.fusion.joints into Synthesis.Joints +# Converts the current list of selected adsk.fusion.joints into list[Synthesis.Joint] def getSelectedJoints() -> list[Joint]: joints: list[Joint] = [] for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed From f77570ecececb437bc2de3a7b9421e601e880362 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 17:29:15 -0700 Subject: [PATCH 05/21] Load saved joint settings --- .../src/UI/ConfigCommand.py | 20 ++--- .../src/UI/JointConfigTab.py | 73 +++++++++++++------ 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 5a6e8fb480..b921f306eb 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -50,11 +50,9 @@ """ These lists are crucial, and contain all of the relevant object selections. - WheelListGlobal: list of wheels (adsk.fusion.Occurrence) -- JointListGlobal: list of joints (adsk.fusion.Joint) - GamepieceListGlobal: list of gamepieces (adsk.fusion.Occurrence) """ WheelListGlobal = [] -JointListGlobal = [] GamepieceListGlobal = [] # Default to compressed files @@ -177,7 +175,6 @@ def __init__(self, configure): def notify(self, args): try: exporterOptions = ExporterOptions().readFromDesign() - # exporterOptions = ExporterOptions() if not Helper.check_solid_open(): return @@ -295,12 +292,8 @@ def notify(self, args): adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) - weight_unit.listItems.add( - "‎", imperialUnits, IconPaths.massIcons["LBS"] - ) # add listdropdown mass options - weight_unit.listItems.add( - "‎", not imperialUnits, IconPaths.massIcons["KG"] - ) # add listdropdown mass options + weight_unit.listItems.add("‎", imperialUnits, IconPaths.massIcons["LBS"]) + weight_unit.listItems.add("‎", not imperialUnits, IconPaths.massIcons["KG"]) weight_unit.tooltip = "Unit of mass" weight_unit.tooltipDescription = ( "
Configure the unit of mass for the weight calculation." @@ -419,9 +412,9 @@ def notify(self, args): # Transition: AARD-1685 createJointConfigTab(args) if exporterOptions.joints: - for joint in exporterOptions.joints: - jointEntity = gm.app.activeDocument.design.findEntityByToken(joint.jointToken)[0] - addJointToConfigTab(jointEntity) + for synJoint in exporterOptions.joints: + fusionJoint = gm.app.activeDocument.design.findEntityByToken(synJoint.jointToken)[0] + addJointToConfigTab(fusionJoint, synJoint) else: for joint in [ *gm.app.activeDocument.design.rootComponent.allJoints, @@ -954,7 +947,6 @@ def __init__(self): super().__init__() self.log = logging.getLogger(f"{INTERNAL_ID}.UI.{self.__class__.__name__}") self.current = SerialCommand() - self.designAttrs = adsk.core.Application.get().activeProduct.attributes def notify(self, args): try: @@ -1967,7 +1959,7 @@ def notify(self, args): onSelect = gm.handlers[3] WheelListGlobal.clear() - JointListGlobal.clear() + resetSelectedJoints() GamepieceListGlobal.clear() onSelect.allWheelPreselections.clear() onSelect.wheelJointList.clear() diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index 03b111e93e..891ad08fc4 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -121,46 +121,46 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: ) -def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: +def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) -> None: try: - if joint in selectedJointList: - removeJointFromConfigTab(joint) + if fusionJoint in selectedJointList: + removeJointFromConfigTab(fusionJoint) return - selectedJointList.append(joint) + selectedJointList.append(fusionJoint) commandInputs = jointConfigTable.commandInputs - if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: icon = commandInputs.addImageCommandInput("placeholder", "Rigid", IconPaths.jointIcons["rigid"]) icon.tooltip = "Rigid joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: icon = commandInputs.addImageCommandInput("placeholder", "Revolute", IconPaths.jointIcons["revolute"]) icon.tooltip = "Revolute joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: icon = commandInputs.addImageCommandInput("placeholder", "Slider", IconPaths.jointIcons["slider"]) icon.tooltip = "Slider joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: icon = commandInputs.addImageCommandInput("placeholder", "Planar", IconPaths.jointIcons["planar"]) icon.tooltip = "Planar joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: icon = commandInputs.addImageCommandInput("placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"]) icon.tooltip = "Pin slot joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: icon = commandInputs.addImageCommandInput("placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"]) icon.tooltip = "Cylindrical joint" - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: icon = commandInputs.addImageCommandInput("placeholder", "Ball", IconPaths.jointIcons["ball"]) icon.tooltip = "Ball joint" name = commandInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) - name.tooltip = joint.name - name.formattedText = f"

{joint.name}

" + name.tooltip = fusionJoint.name + name.formattedText = f"

{fusionJoint.name}

" jointType = commandInputs.addDropDownCommandInput( "jointParent", @@ -169,14 +169,17 @@ def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: ) jointType.isFullWidth = True + + # Transition: AARD-1685 + # Implementation of joint parent system needs to be revisited. jointType.listItems.add("Root", True) for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed dropDown = jointConfigTable.getInputAtPosition(row, 2) dropDown.listItems.add(selectedJointList[-1].name, False) - for joint in selectedJointList: - jointType.listItems.add(joint.name, False) + for fusionJoint in selectedJointList: + jointType.listItems.add(fusionJoint.name, False) jointType.tooltip = "Possible parent joints" jointType.tooltipDescription = "
The root component is usually the parent." @@ -186,9 +189,17 @@ def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) - signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) + + # TODO: Make this better, this is bad bad bad - Brandon + if synJoint: + signalType.listItems.add("‎", synJoint.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", synJoint.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", synJoint.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) + else: + signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) + signalType.tooltip = "Signal type" row = jointConfigTable.rowCount @@ -198,27 +209,43 @@ def addJointToConfigTab(joint: adsk.fusion.Joint) -> None: jointConfigTable.addCommandInput(signalType, row, 3) # Joint speed must be added within an `if` because there is variance between different joint types - if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + # Comparison by `==` over `is` because the Autodesk API does not use `Enum` for their enum classes + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + if synJoint: + jointSpeedValue = synJoint.speed + else: + jointSpeedValue = 3.1415926 + jointSpeed = commandInputs.addValueInput( "jointSpeed", "Speed", "deg", - adsk.core.ValueInput.createByReal(3.1415926), + adsk.core.ValueInput.createByReal(jointSpeedValue), ) jointSpeed.tooltip = "Degrees per second" jointConfigTable.addCommandInput(jointSpeed, row, 4) - elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + if synJoint: + jointSpeedValue = synJoint.speed + else: + jointSpeedValue = 100 + jointSpeed = commandInputs.addValueInput( "jointSpeed", "Speed", "m", - adsk.core.ValueInput.createByReal(100), + adsk.core.ValueInput.createByReal(jointSpeedValue), ) jointSpeed.tooltip = "Meters per second" jointConfigTable.addCommandInput(jointSpeed, row, 4) - jointForce = commandInputs.addValueInput("jointForce", "Force", "N", adsk.core.ValueInput.createByReal(5000)) + if synJoint: + jointForceValue = synJoint.force * 100 # Currently a factor of 100 - Should be investigated + else: + jointForceValue = 5 + + jointForce = commandInputs.addValueInput("jointForce", "Force", "N", adsk.core.ValueInput.createByReal(jointForceValue)) jointForce.tooltip = "Newtons" jointConfigTable.addCommandInput(jointForce, row, 5) except: From 57d6b931a8d24a361cbeeea71b371f7ba44d3910 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 25 Jun 2024 17:40:54 -0700 Subject: [PATCH 06/21] Restored unintentional formatting changes --- exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py | 7 ++----- exporter/SynthesisFusionAddin/src/UI/OsHelper.py | 5 ++--- exporter/SynthesisFusionAddin/src/UI/TableUtilities.py | 10 +++++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py index 5c03d0168f..0a1fbadcbf 100644 --- a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py +++ b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py @@ -1,10 +1,7 @@ -import adsk.core -import adsk.fusion -import traceback +import adsk.core, adsk.fusion, traceback import logging.handlers -# Ripped all the boiler plate from the example code: -# https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622 +# Ripped all the boiler plate from the example code: https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622 # global mapping list of event handlers to keep them referenced for the duration of the command # handlers = {} diff --git a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py index 3c006e3113..956c9f6fd1 100644 --- a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py +++ b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py @@ -1,5 +1,4 @@ -import os -import platform +import os, platform def getOSPath(*argv) -> str: @@ -47,7 +46,7 @@ def getOS(): return platform.system() -""" Old code I believe +""" Old code I believe def openFileLocation(fileLoc: str) -> bool: osName = getOS() if osName == "Windows" or osName == "win32": diff --git a/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py b/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py index e972f2ae8e..9e274e7148 100644 --- a/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py +++ b/exporter/SynthesisFusionAddin/src/UI/TableUtilities.py @@ -14,7 +14,7 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: try: onSelect = gm.handlers[3] wheelTableInput = INPUTS_ROOT.itemById("wheel_table") - + # def addPreselections(child_occurrences): # for occ in child_occurrences: # onSelect.allWheelPreselections.append(occ.entityToken) @@ -22,7 +22,7 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: # if occ.childOccurrences: # addPreselections(occ.childOccurrences) - # if wheel.childOccurrences: + # if wheel.childOccurrences: # addPreselections(wheel.childOccurrences) # else: # onSelect.allWheelPreselections.append(wheel.entityToken) @@ -198,7 +198,7 @@ def addGamepieceToTable(gamepiece: adsk.fusion.Occurrence) -> None: def addPreselections(child_occurrences): for occ in child_occurrences: onSelect.allGamepiecePreselections.append(occ.entityToken) - + if occ.childOccurrences: addPreselections(occ.childOccurrences) @@ -249,7 +249,7 @@ def addPreselections(child_occurrences): "friction_coeff", "", "", valueList ) friction_coeff.valueOne = 0.5 - + type.tooltip = gamepiece.name weight.tooltip = "Weight of field element" @@ -354,7 +354,7 @@ def removeGamePieceFromTable(index: int) -> None: def removePreselections(child_occurrences): for occ in child_occurrences: onSelect.allGamepiecePreselections.remove(occ.entityToken) - + if occ.childOccurrences: removePreselections(occ.childOccurrences) try: From 5adcd67edf1a88fbcb06adc425b4c4b0e038c9ed Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 09:03:44 -0700 Subject: [PATCH 07/21] Added confirm joint removal prompt --- .../SynthesisFusionAddin/src/UI/ConfigCommand.py | 16 ++++++++++++++-- .../src/UI/JointConfigTab.py | 7 ++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index b921f306eb..7a13b9687a 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -26,6 +26,7 @@ from .JointConfigTab import ( createJointConfigTab, addJointToConfigTab, + removeJointFromConfigTab, removeIndexedJointFromConfigTab, getSelectedJoints, resetSelectedJoints @@ -1395,8 +1396,19 @@ def notify(self, args: adsk.core.SelectionEventArgs): WheelListGlobal.index(self.selectedJoint) ) else: - # Will prompt for removal if already selected. - addJointToConfigTab(self.selectedJoint) + # Transition: AARD-1685 + # Should move selection handles into respective UI modules + if not addJointToConfigTab(self.selectedJoint): + result = gm.ui.messageBox( + "You have already selected this joint.\n" + "Would you like to remove it?", + "Synthesis: Remove Joint Confirmation", + adsk.core.MessageBoxButtonTypes.YesNoButtonType, + adsk.core.MessageBoxIconTypes.QuestionIconType, + ) + + if result == adsk.core.DialogResults.DialogYes: + removeJointFromConfigTab(self.selectedJoint) selectionInput.isEnabled = False selectionInput.isVisible = False diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index 891ad08fc4..ff85fe5158 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -121,11 +121,10 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: ) -def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) -> None: +def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) -> bool: try: if fusionJoint in selectedJointList: - removeJointFromConfigTab(fusionJoint) - return + return False selectedJointList.append(fusionJoint) commandInputs = jointConfigTable.commandInputs @@ -253,6 +252,8 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) "Failed:\n{}".format(traceback.format_exc()) ) + return True + def removeIndexedJointFromConfigTab(index: int) -> None: try: From 7c2c2a936c5fc59753bd93c358314e7c485dfd4a Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 10:26:43 -0700 Subject: [PATCH 08/21] Added joint select cancel button --- .../src/UI/ConfigCommand.py | 43 +++++++++++-------- .../src/UI/JointConfigTab.py | 4 ++ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 7a13b9687a..3af0c1ef7b 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -1134,7 +1134,8 @@ def notify(self, args): auto_calc_weight_f = INPUTS_ROOT.itemById("auto_calc_weight_f") removeWheelInput = INPUTS_ROOT.itemById("wheel_delete") - removeJointInput = INPUTS_ROOT.itemById("jointRemoveButton") + jointRemoveButton = INPUTS_ROOT.itemById("jointRemoveButton") + jointSelection = INPUTS_ROOT.itemById("jointSelection") removeFieldInput = INPUTS_ROOT.itemById("field_delete") addWheelInput = INPUTS_ROOT.itemById("wheel_add") @@ -1154,9 +1155,9 @@ def notify(self, args): removeWheelInput.isEnabled = True if jointTableInput.rowCount <= 1: - removeJointInput.isEnabled = False - else: - removeJointInput.isEnabled = True + jointRemoveButton.isEnabled = False + elif not jointSelection.isEnabled: + jointRemoveButton.isEnabled = True if gamepieceTableInput.rowCount <= 1: removeFieldInput.isEnabled = auto_calc_weight_f.isEnabled = False @@ -1177,7 +1178,7 @@ def notify(self, args): group.deleteMe() if ( - not addJointInput.isEnabled or not removeJointInput + not addJointInput.isEnabled or not jointRemoveButton.isEnabled ): # TODO: improve joint highlighting # for joint in JointListGlobal: # CustomGraphics.highlightJointedOccurrences(joint) @@ -1585,7 +1586,8 @@ def notify(self, args): frictionCoeff = INPUTS_ROOT.itemById("friction_coeff_override") wheelSelect = inputs.itemById("wheel_select") - jointSelect = inputs.itemById("jointSelection") + jointSelection = inputs.itemById("jointSelection") + jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") gamepieceSelect = inputs.itemById("gamepiece_select") wheelTableInput = wheelTable() @@ -1602,7 +1604,8 @@ def notify(self, args): gamepieceConfig = inputs.itemById("gamepiece_config") addWheelInput = INPUTS_ROOT.itemById("wheel_add") - addJointInput = INPUTS_ROOT.itemById("jointAddButton") + addJointButton = INPUTS_ROOT.itemById("jointAddButton") + removeJointButton = INPUTS_ROOT.itemById("jointRemoveButton") addFieldInput = INPUTS_ROOT.itemById("field_add") indicator = INPUTS_ROOT.itemById("algorithmic_indicator") @@ -1631,7 +1634,7 @@ def notify(self, args): gm.ui.activeSelections.clear() gm.app.activeDocument.design.rootComponent.opacity = 1 - addWheelInput.isEnabled = addJointInput.isEnabled = ( + addWheelInput.isEnabled = addJointButton.isEnabled = ( gamepieceConfig.isVisible ) = True @@ -1685,8 +1688,8 @@ def notify(self, args): or cmdInput.id == "signal_type" ): self.reset() - jointSelect.isEnabled = False - addJointInput.isEnabled = True + jointSelection.isEnabled = False + addJointButton.isEnabled = True elif ( cmdInput.id == "blank_gp" @@ -1778,7 +1781,7 @@ def notify(self, args): wheelSelect.isVisible = True wheelSelect.isEnabled = True wheelSelect.clearSelection() - addJointInput.isEnabled = True + addJointButton.isEnabled = True addWheelInput.isEnabled = False # Transition: AARD-1685 @@ -1787,10 +1790,10 @@ def notify(self, args): self.reset() addWheelInput.isEnabled = True - jointSelect.isVisible = True - jointSelect.isEnabled = True - jointSelect.clearSelection() - addJointInput.isEnabled = False + jointSelection.isVisible = jointSelection.isEnabled = True + jointSelection.clearSelection() + addJointButton.isEnabled = removeJointButton.isEnabled = False + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True elif cmdInput.id == "field_add": self.reset() @@ -1817,7 +1820,7 @@ def notify(self, args): elif cmdInput.id == "jointRemoveButton": gm.ui.activeSelections.clear() - addJointInput.isEnabled = True + addJointButton.isEnabled = True addWheelInput.isEnabled = True if jointTableInput.selectedRow == -1 or jointTableInput.selectedRow == 0: @@ -1846,7 +1849,13 @@ def notify(self, args): addWheelInput.isEnabled = True elif cmdInput.id == "jointSelection": - addJointInput.isEnabled = True + addJointButton.isEnabled = removeJointButton.isEnabled = True + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + + elif cmdInput.id == "jointSelectCancelButton": + jointSelection.isEnabled = jointSelection.isVisible = False + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + addJointButton.isEnabled = removeJointButton.isEnabled = True elif cmdInput.id == "gamepiece_select": addFieldInput.isEnabled = True diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index ff85fe5158..ed2f4a7d37 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -109,12 +109,16 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: # Visibility is triggered by `addJointInputButton` jointSelect.isEnabled = jointSelect.isVisible = False + jointSelectCancelButton = jointConfigTabInputs.addBoolValueInput("jointSelectCancelButton", "Cancel", False) + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + addJointInputButton = jointConfigTabInputs.addBoolValueInput("jointAddButton", "Add", False) removeJointInputButton = jointConfigTabInputs.addBoolValueInput("jointRemoveButton", "Remove", False) addJointInputButton.isEnabled = removeJointInputButton.isEnabled = True jointConfigTable.addToolbarCommandInput(addJointInputButton) jointConfigTable.addToolbarCommandInput(removeJointInputButton) + jointConfigTable.addToolbarCommandInput(jointSelectCancelButton) except: logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( "Failed:\n{}".format(traceback.format_exc()) From 818e784083636524575c7f5a205b66e196988aa2 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Thu, 27 Jun 2024 11:14:45 -0700 Subject: [PATCH 09/21] Created new table under joint select that autopopulates with selected wheels --- .../src/Parser/ExporterOptions.py | 29 +- .../src/UI/ConfigCommand.py | 523 +++++++++--------- .../src/UI/CreateCommandInputsHelper.py | 36 +- .../src/UI/JointConfigTab.py | 187 ++++++- 4 files changed, 480 insertions(+), 295 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py index 0f56b4338f..4f7983ee4d 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py @@ -39,6 +39,12 @@ class Joint: speed: float = field(default=None) force: float = field(default=None) + # Transition: AARD-1865 + # Should consider changing how the parser handles wheels and joints as there is overlap between + # `Joint` and `Wheel` that should be avoided + # This overlap also presents itself in 'ConfigCommand.py' and 'JointConfigTab.py' + isWheel: bool = field(default=False) + @dataclass class Gamepiece: @@ -103,17 +109,20 @@ class ExporterOptions: ) def readFromDesign(self) -> "ExporterOptions": - designAttributes = adsk.core.Application.get().activeProduct.attributes - for field in fields(self): - attribute = designAttributes.itemByName(INTERNAL_ID, field.name) - if attribute: - setattr( - self, - field.name, - self._makeObjectFromJson(field.type, json.loads(attribute.value)), - ) + try: + designAttributes = adsk.core.Application.get().activeProduct.attributes + for field in fields(self): + attribute = designAttributes.itemByName(INTERNAL_ID, field.name) + if attribute: + setattr( + self, + field.name, + self._makeObjectFromJson(field.type, json.loads(attribute.value)), + ) - return self + return self + except: + return ExporterOptions() def writeToDesign(self) -> None: designAttributes = adsk.core.Application.get().activeProduct.attributes diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 3af0c1ef7b..9f59245836 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -26,9 +26,10 @@ from .JointConfigTab import ( createJointConfigTab, addJointToConfigTab, + addWheelToConfigTab, removeJointFromConfigTab, removeIndexedJointFromConfigTab, - getSelectedJoints, + getSelectedJointsAndWheels, resetSelectedJoints ) @@ -76,22 +77,23 @@ def GUID(arg): return arg.entityToken -def wheelTable(): - """### Returns the wheel table command input +# Transition: AARD-1865 +# def wheelTable(): +# """### Returns the wheel table command input - Returns: - adsk.fusion.TableCommandInput - """ - return INPUTS_ROOT.itemById("wheel_table") +# Returns: +# adsk.fusion.TableCommandInput +# """ +# return INPUTS_ROOT.itemById("wheel_table") -def jointTable(): - """### Returns the joint table command input +# def jointTable(): +# """### Returns the joint table command input - Returns: - adsk.fusion.TableCommandInput - """ - return INPUTS_ROOT.itemById("joint_table") +# Returns: +# adsk.fusion.TableCommandInput +# """ +# return INPUTS_ROOT.itemById("joint_table") def gamepieceTable(): @@ -313,105 +315,109 @@ def notify(self, args): weight_unit, 0, 3 ) # add command inputs to table + # Transition: AARD-1685 # ~~~~~~~~~~~~~~~~ WHEEL CONFIGURATION ~~~~~~~~~~~~~~~~ """ Wheel configuration command input group - Container for wheel selection Table """ - wheelConfig = inputs.addGroupCommandInput( - "wheel_config", "Wheel Configuration" - ) - wheelConfig.isExpanded = True - wheelConfig.isEnabled = True - wheelConfig.tooltip = ( - "Select and define the drive-train wheels in your assembly." - ) - - wheel_inputs = wheelConfig.children + # wheelConfig = inputs.addGroupCommandInput( + # "wheel_config", "Wheel Configuration" + # ) + # wheelConfig.isExpanded = True + # wheelConfig.isEnabled = True + # wheelConfig.tooltip = ( + # "Select and define the drive-train wheels in your assembly." + # ) - # WHEEL SELECTION TABLE - """ - All selected wheel occurrences appear here. - """ - wheelTableInput = self.createTableInput( - "wheel_table", - "Wheel Table", - wheel_inputs, - 4, - "1:4:2:2", - 50, - ) + # wheel_inputs = wheelConfig.children + + # # WHEEL SELECTION TABLE + # """ + # All selected wheel occurrences appear here. + # """ + # wheelTableInput = self.createTableInput( + # "wheel_table", + # "Wheel Table", + # wheel_inputs, + # 4, + # "1:4:2:2", + # 50, + # ) - addWheelInput = wheel_inputs.addBoolValueInput( - "wheel_add", "Add", False - ) # add button + # addWheelInput = wheel_inputs.addBoolValueInput( + # "wheel_add", "Add", False + # ) # add button - removeWheelInput = wheel_inputs.addBoolValueInput( # remove button - "wheel_delete", "Remove", False - ) + # removeWheelInput = wheel_inputs.addBoolValueInput( # remove button + # "wheel_delete", "Remove", False + # ) - addWheelInput.tooltip = "Add a wheel joint" # tooltips - removeWheelInput.tooltip = "Remove a wheel joint" + # addWheelInput.tooltip = "Add a wheel joint" # tooltips + # removeWheelInput.tooltip = "Remove a wheel joint" - wheelSelectInput = wheel_inputs.addSelectionInput( - "wheel_select", - "Selection", - "Select the wheels joints in your drive-train assembly.", - ) - wheelSelectInput.addSelectionFilter( - "Joints" - ) # filter selection to only occurrences - - wheelSelectInput.setSelectionLimits(0) # no selection count limit - wheelSelectInput.isEnabled = False - wheelSelectInput.isVisible = False - - wheelTableInput.addToolbarCommandInput( - addWheelInput - ) # add buttons to the toolbar - wheelTableInput.addToolbarCommandInput( - removeWheelInput - ) # add buttons to the toolbar - - wheelTableInput.addCommandInput( # create textbox input using helper (component name) - self.createTextBoxInput( - "name_header", "Name", wheel_inputs, "Joint name", bold=False - ), - 0, - 1, - ) + # wheelSelectInput = wheel_inputs.addSelectionInput( + # "wheel_select", + # "Selection", + # "Select the wheels joints in your drive-train assembly.", + # ) + # wheelSelectInput.addSelectionFilter( + # "Joints" + # ) # filter selection to only occurrences + + # wheelSelectInput.setSelectionLimits(0) # no selection count limit + # wheelSelectInput.isEnabled = False + # wheelSelectInput.isVisible = False + + # wheelTableInput.addToolbarCommandInput( + # addWheelInput + # ) # add buttons to the toolbar + # wheelTableInput.addToolbarCommandInput( + # removeWheelInput + # ) # add buttons to the toolbar + + # wheelTableInput.addCommandInput( # create textbox input using helper (component name) + # self.createTextBoxInput( + # "name_header", "Name", wheel_inputs, "Joint name", bold=False + # ), + # 0, + # 1, + # ) - wheelTableInput.addCommandInput( - self.createTextBoxInput( # wheel type header - "parent_header", - "Parent", - wheel_inputs, - "Wheel type", - background="#d9d9d9", # textbox header background color - ), - 0, - 2, - ) + # wheelTableInput.addCommandInput( + # self.createTextBoxInput( # wheel type header + # "parent_header", + # "Parent", + # wheel_inputs, + # "Wheel type", + # background="#d9d9d9", # textbox header background color + # ), + # 0, + # 2, + # ) - wheelTableInput.addCommandInput( - self.createTextBoxInput( # Signal type header - "signal_header", - "Signal", - wheel_inputs, - "Signal type", - background="#d9d9d9", # textbox header background color - ), - 0, - 3, - ) + # wheelTableInput.addCommandInput( + # self.createTextBoxInput( # Signal type header + # "signal_header", + # "Signal", + # wheel_inputs, + # "Signal type", + # background="#d9d9d9", # textbox header background color + # ), + # 0, + # 3, + # ) + # Transition: AARD-1685 + # There remains some overlap between adding joints as wheels. + # Should investigate changes to improve performance. + createJointConfigTab(args) if exporterOptions.wheels: + pass for wheel in exporterOptions.wheels: - wheelEntity = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] - addWheelToTable(wheelEntity) + fusionJoint = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] + addWheelToConfigTab(fusionJoint, wheel) - # Transition: AARD-1685 - createJointConfigTab(args) if exporterOptions.joints: for synJoint in exporterOptions.joints: fusionJoint = gm.app.activeDocument.design.findEntityByToken(synJoint.jointToken)[0] @@ -1000,31 +1006,32 @@ def notify(self, args): _robotWeight = float _mode = ExportMode.ROBOT + # Transition: AARD-1865 """ Loops through all rows in the wheel table to extract all the input values """ - onSelect = gm.handlers[3] - wheelTableInput = wheelTable() - for row in range(wheelTableInput.rowCount): - if row == 0: - continue - - wheelTypeIndex = wheelTableInput.getInputAtPosition( - row, 2 - ).selectedItem.index # This must be either 0 or 1 for standard or omni - - signalTypeIndex = wheelTableInput.getInputAtPosition( - row, 3 - ).selectedItem.index - - _exportWheels.append( - Wheel( - WheelListGlobal[row - 1].entityToken, - WheelType(wheelTypeIndex + 1), - SignalType(signalTypeIndex + 1), - # onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint found, default to None - ) - ) + # onSelect = gm.handlers[3] + # wheelTableInput = wheelTable() + # for row in range(wheelTableInput.rowCount): + # if row == 0: + # continue + + # wheelTypeIndex = wheelTableInput.getInputAtPosition( + # row, 2 + # ).selectedItem.index # This must be either 0 or 1 for standard or omni + + # signalTypeIndex = wheelTableInput.getInputAtPosition( + # row, 3 + # ).selectedItem.index + + # _exportWheels.append( + # Wheel( + # WheelListGlobal[row - 1].entityToken, + # WheelType(wheelTypeIndex + 1), + # SignalType(signalTypeIndex + 1), + # # onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint found, default to None + # ) + # ) """ Loops through all rows in the gamepiece table to extract the input values @@ -1083,13 +1090,15 @@ def notify(self, args): .children.itemById("compress") ).value + selectedJoints, selectedWheels = getSelectedJointsAndWheels() + exporterOptions = ExporterOptions( savepath, name, version, materials=0, - joints=getSelectedJoints(), - wheels=_exportWheels, + joints=selectedJoints, + wheels=selectedWheels, gamepieces=_exportGamepieces, preferredUnits=selectedUnits, robotWeight=_robotWeight, @@ -1142,17 +1151,17 @@ def notify(self, args): addJointInput = INPUTS_ROOT.itemById("jointAddButton") addFieldInput = INPUTS_ROOT.itemById("field_add") - wheelTableInput = wheelTable() + # wheelTableInput = wheelTable() inputs = args.command.commandInputs jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById("jointTable") gamepieceTableInput = gamepieceTable() - if wheelTableInput.rowCount <= 1: - removeWheelInput.isEnabled = False - else: - removeWheelInput.isEnabled = True + # if wheelTableInput.rowCount <= 1: + # removeWheelInput.isEnabled = False + # else: + # removeWheelInput.isEnabled = True if jointTableInput.rowCount <= 1: jointRemoveButton.isEnabled = False @@ -1383,33 +1392,34 @@ def notify(self, args: adsk.core.SelectionEventArgs): jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value ): - if ( - jointType == JointMotions.REVOLUTE.value - and MySelectHandler.lastInputCmd.id == "wheel_select" - ): - addWheelToTable(self.selectedJoint) - elif ( - jointType == JointMotions.REVOLUTE.value - and MySelectHandler.lastInputCmd.id == "wheel_remove" - ): - if self.selectedJoint in WheelListGlobal: - removeWheelFromTable( - WheelListGlobal.index(self.selectedJoint) - ) - else: + # Transition: AARD-1685 + # if ( + # jointType == JointMotions.REVOLUTE.value + # and MySelectHandler.lastInputCmd.id == "wheel_select" + # ): + # addWheelToTable(self.selectedJoint) + # elif ( + # jointType == JointMotions.REVOLUTE.value + # and MySelectHandler.lastInputCmd.id == "wheel_remove" + # ): + # if self.selectedJoint in WheelListGlobal: + # removeWheelFromTable( + # WheelListGlobal.index(self.selectedJoint) + # ) + # else: # Transition: AARD-1685 # Should move selection handles into respective UI modules - if not addJointToConfigTab(self.selectedJoint): - result = gm.ui.messageBox( - "You have already selected this joint.\n" - "Would you like to remove it?", - "Synthesis: Remove Joint Confirmation", - adsk.core.MessageBoxButtonTypes.YesNoButtonType, - adsk.core.MessageBoxIconTypes.QuestionIconType, - ) + if not addJointToConfigTab(self.selectedJoint): + result = gm.ui.messageBox( + "You have already selected this joint.\n" + "Would you like to remove it?", + "Synthesis: Remove Joint Confirmation", + adsk.core.MessageBoxButtonTypes.YesNoButtonType, + adsk.core.MessageBoxIconTypes.QuestionIconType, + ) - if result == adsk.core.DialogResults.DialogYes: - removeJointFromConfigTab(self.selectedJoint) + if result == adsk.core.DialogResults.DialogYes: + removeJointFromConfigTab(self.selectedJoint) selectionInput.isEnabled = False selectionInput.isVisible = False @@ -1590,7 +1600,7 @@ def notify(self, args): jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") gamepieceSelect = inputs.itemById("gamepiece_select") - wheelTableInput = wheelTable() + # wheelTableInput = wheelTable() jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") @@ -1657,27 +1667,28 @@ def notify(self, args): cmdInput_str = cmdInput.id - if cmdInput_str == "placeholder_w": - position = ( - wheelTableInput.getPosition( - adsk.core.ImageCommandInput.cast(cmdInput) - )[1] - - 1 - ) - elif cmdInput_str == "name_w": - position = ( - wheelTableInput.getPosition( - adsk.core.TextBoxCommandInput.cast(cmdInput) - )[1] - - 1 - ) - elif cmdInput_str == "signal_type_w": - position = ( - wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - )[1] - - 1 - ) + # Transition: AARD-1685 + # if cmdInput_str == "placeholder_w": + # position = ( + # wheelTableInput.getPosition( + # adsk.core.ImageCommandInput.cast(cmdInput) + # )[1] + # - 1 + # ) + # elif cmdInput_str == "name_w": + # position = ( + # wheelTableInput.getPosition( + # adsk.core.TextBoxCommandInput.cast(cmdInput) + # )[1] + # - 1 + # ) + # elif cmdInput_str == "signal_type_w": + # position = ( + # wheelTableInput.getPosition( + # adsk.core.DropDownCommandInput.cast(cmdInput) + # )[1] + # - 1 + # ) gm.ui.activeSelections.add(WheelListGlobal[position]) @@ -1734,44 +1745,45 @@ def notify(self, args): gm.ui.activeSelections.add(GamepieceListGlobal[position]) - elif cmdInput.id == "wheel_type_w": - self.reset() - - wheelSelect.isEnabled = False - addWheelInput.isEnabled = True - - cmdInput_str = cmdInput.id - position = ( - wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - )[1] - - 1 - ) - wheelDropdown = adsk.core.DropDownCommandInput.cast(cmdInput) - - if wheelDropdown.selectedItem.index == 0: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) - iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - iconInput.imageFile = IconPaths.wheelIcons["standard"] - iconInput.tooltip = "Standard wheel" - - elif wheelDropdown.selectedItem.index == 1: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) - iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - iconInput.imageFile = IconPaths.wheelIcons["omni"] - iconInput.tooltip = "Omni wheel" - - elif wheelDropdown.selectedItem.index == 2: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) - iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - iconInput.imageFile = IconPaths.wheelIcons["mecanum"] - iconInput.tooltip = "Mecanum wheel" + # Transition: AARD-1685 + # elif cmdInput.id == "wheel_type_w": + # self.reset() + + # wheelSelect.isEnabled = False + # addWheelInput.isEnabled = True + + # cmdInput_str = cmdInput.id + # position = ( + # wheelTableInput.getPosition( + # adsk.core.DropDownCommandInput.cast(cmdInput) + # )[1] + # - 1 + # ) + # wheelDropdown = adsk.core.DropDownCommandInput.cast(cmdInput) + + # if wheelDropdown.selectedItem.index == 0: + # getPosition = wheelTableInput.getPosition( + # adsk.core.DropDownCommandInput.cast(cmdInput) + # ) + # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) + # iconInput.imageFile = IconPaths.wheelIcons["standard"] + # iconInput.tooltip = "Standard wheel" + + # elif wheelDropdown.selectedItem.index == 1: + # getPosition = wheelTableInput.getPosition( + # adsk.core.DropDownCommandInput.cast(cmdInput) + # ) + # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) + # iconInput.imageFile = IconPaths.wheelIcons["omni"] + # iconInput.tooltip = "Omni wheel" + + # elif wheelDropdown.selectedItem.index == 2: + # getPosition = wheelTableInput.getPosition( + # adsk.core.DropDownCommandInput.cast(cmdInput) + # ) + # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) + # iconInput.imageFile = IconPaths.wheelIcons["mecanum"] + # iconInput.tooltip = "Mecanum wheel" gm.ui.activeSelections.add(WheelListGlobal[position]) @@ -1803,17 +1815,18 @@ def notify(self, args): gamepieceSelect.clearSelection() addFieldInput.isEnabled = False - elif cmdInput.id == "wheel_delete": - # Currently causes Internal Autodesk Error - # gm.ui.activeSelections.clear() - - addWheelInput.isEnabled = True - if wheelTableInput.selectedRow == -1 or wheelTableInput.selectedRow == 0: - wheelTableInput.selectedRow = wheelTableInput.rowCount - 1 - gm.ui.messageBox("Select a row to delete.") - else: - index = wheelTableInput.selectedRow - 1 - removeWheelFromTable(index) + # Transition: AARD-1685 + # elif cmdInput.id == "wheel_delete": + # # Currently causes Internal Autodesk Error + # # gm.ui.activeSelections.clear() + + # addWheelInput.isEnabled = True + # if wheelTableInput.selectedRow == -1 or wheelTableInput.selectedRow == 0: + # wheelTableInput.selectedRow = wheelTableInput.rowCount - 1 + # gm.ui.messageBox("Select a row to delete.") + # else: + # index = wheelTableInput.selectedRow - 1 + # removeWheelFromTable(index) # Transition: AARD-1685 # Functionality could potentially be moved into `JointConfigTab.py` @@ -1999,6 +2012,7 @@ def notify(self, args): ).error("Failed:\n{}".format(traceback.format_exc())) +# Transition: AARD-1685 def addWheelToTable(wheel: adsk.fusion.Joint) -> None: """### Adds a wheel occurrence to its global list and wheel table. @@ -2015,7 +2029,7 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: # we do this before the initialization of gm.handlers[] pass - wheelTableInput = wheelTable() + wheelTableInput = None # def addPreselections(child_occurrences): # for occ in child_occurrences: # onSelect.allWheelPreselections.append(occ.entityToken) @@ -2161,39 +2175,40 @@ def addPreselections(child_occurrences): ) -def removeWheelFromTable(index: int) -> None: - """### Removes a wheel joint from its global list and wheel table. - - Args: - index (int): index of wheel item in its global list - """ - try: - onSelect = gm.handlers[3] - wheelTableInput = wheelTable() - wheel = WheelListGlobal[index] - - # def removePreselections(child_occurrences): - # for occ in child_occurrences: - # onSelect.allWheelPreselections.remove(occ.entityToken) - - # if occ.childOccurrences: - # removePreselections(occ.childOccurrences) - - # if wheel.childOccurrences: - # removePreselections(wheel.childOccurrences) - # else: - onSelect.allWheelPreselections.remove(wheel.entityToken) - - del WheelListGlobal[index] - wheelTableInput.deleteRow(index + 1) - - # updateJointTable(wheel) - except IndexError: - pass - except: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeWheelFromTable()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) +# Transition: AARD-1685 +# def removeWheelFromTable(index: int) -> None: +# """### Removes a wheel joint from its global list and wheel table. + +# Args: +# index (int): index of wheel item in its global list +# """ +# try: +# onSelect = gm.handlers[3] +# wheelTableInput = wheelTable() +# wheel = WheelListGlobal[index] + +# # def removePreselections(child_occurrences): +# # for occ in child_occurrences: +# # onSelect.allWheelPreselections.remove(occ.entityToken) + +# # if occ.childOccurrences: +# # removePreselections(occ.childOccurrences) + +# # if wheel.childOccurrences: +# # removePreselections(wheel.childOccurrences) +# # else: +# onSelect.allWheelPreselections.remove(wheel.entityToken) + +# del WheelListGlobal[index] +# wheelTableInput.deleteRow(index + 1) + +# # updateJointTable(wheel) +# except IndexError: +# pass +# except: +# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeWheelFromTable()").error( +# "Failed:\n{}".format(traceback.format_exc()) +# ) def removeGamePieceFromTable(index: int) -> None: diff --git a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py index acdddc5858..81a0530409 100644 --- a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py +++ b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py @@ -9,10 +9,10 @@ def createTableInput( inputs: adsk.core.CommandInputs, columns: int, ratio: str, - maxRows: int, - minRows=1, - columnSpacing=0, - rowSpacing=0, + minRows: int = 1, + maxRows: int = 50, + columnSpacing: int = 0, + rowSpacing: int = 0, ) -> adsk.core.TableCommandInput: try: input = inputs.addTableCommandInput(id, name, columns, ratio) @@ -32,11 +32,11 @@ def createBooleanInput( id: str, name: str, inputs: adsk.core.CommandInputs, - tooltip="", - tooltipadvanced="", - checked=True, - enabled=True, - isCheckBox=True, + tooltip: str = "", + tooltipadvanced: str = "", + checked: bool = True, + enabled: bool = True, + isCheckBox: bool = True, ) -> adsk.core.BoolValueCommandInput: try: input = inputs.addBoolValueInput(id, name, isCheckBox) @@ -57,15 +57,15 @@ def createTextBoxInput( name: str, inputs: adsk.core.CommandInputs, text: str, - italics=True, - bold=True, - fontSize=10, - alignment="center", - rowCount=1, - read=True, - background="whitesmoke", - tooltip="", - advanced_tooltip="", + italics: bool = True, + bold: bool = True, + fontSize: int = 10, + alignment: str = "center", + rowCount: int = 1, + read: bool = True, + background: str = "whitesmoke", + tooltip: str = "", + advanced_tooltip: str = "", ) -> adsk.core.TextBoxCommandInput: try: if bold: diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index ed2f4a7d37..2dc628a1a6 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -5,13 +5,15 @@ import adsk.fusion from . import IconPaths -from .CreateCommandInputsHelper import createTableInput, createTextBoxInput +from .CreateCommandInputsHelper import createTableInput, createTextBoxInput, createBooleanInput -from ..Parser.ExporterOptions import JointParentType, Joint, SignalType +from ..Parser.ExporterOptions import JointParentType, Joint, Wheel, SignalType, WheelType # Wish we did not need this. Could look into storing everything within the design every time - Brandon selectedJointList: list[adsk.fusion.Joint] = [] +jointWheelIndexMap: dict[str, int] = {} jointConfigTable: adsk.core.TableCommandInput +wheelConfigTable: adsk.core.TableCommandInput def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: @@ -27,14 +29,13 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: "jointTable", "Joint Table", jointConfigTabInputs, - 6, - "1:2:2:2:2:2", - 50, + 7, + "1:2:2:2:2:2:2", ) jointConfigTable.addCommandInput( createTextBoxInput( - "motionHeader", + "jointMotionHeader", "Motion", jointConfigTabInputs, "Motion", @@ -100,6 +101,73 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: 5, ) + jointConfigTable.addCommandInput( + createTextBoxInput( + "wheelHeader", + "Is Wheel", + jointConfigTabInputs, + "Is Wheel", + background="#d9d9d9", + ), + 0, + 6, + ) + + jointConfigTabInputs.addTextBoxCommandInput("jointTabBlankSpacer", "", "", 1, True) + + global wheelConfigTable + wheelConfigTable = createTableInput( + "wheelTable", + "Wheel Table", + jointConfigTabInputs, + 4, + "1:2:2:2", + ) + + wheelConfigTable.addCommandInput( + createTextBoxInput( + "wheelMotionHeader", + "Motion", + jointConfigTabInputs, + "Motion", + bold=False, + ), + 0, + 0, + ) + + wheelConfigTable.addCommandInput( + createTextBoxInput( + "name_header", "Name", jointConfigTabInputs, "Joint name", bold=False + ), + 0, + 1, + ) + + wheelConfigTable.addCommandInput( + createTextBoxInput( + "wheelTypeHeader", + "WheelType", + jointConfigTabInputs, + "Wheel type", + background="#d9d9d9", + ), + 0, + 2, + ) + + wheelConfigTable.addCommandInput( + createTextBoxInput( + "signalTypeHeader", + "SignalType", + jointConfigTabInputs, + "Signal type", + background="#d9d9d9", + ), + 0, + 3, + ) + jointSelect = jointConfigTabInputs.addSelectionInput( "jointSelection", "Selection", "Select a joint in your assembly to add." ) @@ -125,7 +193,7 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: ) -def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) -> bool: +def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None) -> bool: try: if fusionJoint in selectedJointList: return False @@ -251,6 +319,26 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) jointForce = commandInputs.addValueInput("jointForce", "Force", "N", adsk.core.ValueInput.createByReal(jointForceValue)) jointForce.tooltip = "Newtons" jointConfigTable.addCommandInput(jointForce, row, 5) + + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + wheelCheckboxEnabled = True + wheelCheckboxTooltip = "Determines if this joint should be counted as a wheel." + else: + wheelCheckboxEnabled = False + wheelCheckboxTooltip = "Only Revolute joints can be treated as wheels." + + isWheel = synJoint.isWheel if synJoint else False + + # Transition: AARD-1685 + # All command inputs should be created using the helpers. + jointConfigTable.addCommandInput(createBooleanInput( + "isWheel", + "Is Wheel", + commandInputs, + wheelCheckboxTooltip, + checked=isWheel, + enabled=wheelCheckboxEnabled, + ), row, 6) except: logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( "Failed:\n{}".format(traceback.format_exc()) @@ -259,6 +347,47 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint = None) return True +def addWheelToConfigTab(joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> None: + jointWheelIndexMap[joint.entityToken] = wheelConfigTable.rowCount + + commandInputs = wheelConfigTable.commandInputs + wheelIcon = commandInputs.addImageCommandInput("wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"]) + wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) + wheelName.tooltip = joint.name # TODO: Should this be the same? + wheelType = commandInputs.addDropDownCommandInput("wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle) + + if wheel: + standardWheelType = wheel.wheelType is WheelType.STANDARD + else: + standardWheelType = True + + wheelType.listItems.add("Standard", standardWheelType, "") + wheelType.listItems.add("OMNI", not standardWheelType, "") + wheelType.tooltip = "Wheel type" + wheelType.tooltipDescription = "".join(["
Omni-directional wheels can be used just like regular drive wheels", + "but they have the advantage of being able to roll freely perpendicular to", + "the drive direction.
"]) + + signalType = commandInputs.addDropDownCommandInput("wheelSignalType", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle) + signalType.isFullWidth = True + signalType.isEnabled = False + signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." + if wheel: + signalType.listItems.add("‎", wheel.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", wheel.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", wheel.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) + else: + signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) + + row = wheelConfigTable.rowCount + wheelConfigTable.addCommandInput(wheelIcon, row, 0) + wheelConfigTable.addCommandInput(wheelName, row, 1) + wheelConfigTable.addCommandInput(wheelType, row, 2) + wheelConfigTable.addCommandInput(signalType, row, 3) + + def removeIndexedJointFromConfigTab(index: int) -> None: try: removeJointFromConfigTab(selectedJointList[index]) @@ -270,12 +399,16 @@ def removeIndexedJointFromConfigTab(index: int) -> None: def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: try: + if jointWheelIndexMap.get(joint.entityToken): + removeWheelFromConfigTab(joint) + i = selectedJointList.index(joint) selectedJointList.remove(joint) - jointConfigTable.deleteRow(i + 1) for row in range(jointConfigTable.rowCount): # Row is 1 indexed + # TODO: Step through this in the debugger and figure out if this is all necessary. listItems = jointConfigTable.getInputAtPosition(row, 2).listItems + logging.getLogger(type(listItems)) if row > i: if listItems.item(i + 1).isSelected: listItems.item(i).isSelected = True @@ -294,25 +427,53 @@ def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: ) -# Converts the current list of selected adsk.fusion.joints into list[Synthesis.Joint] -def getSelectedJoints() -> list[Joint]: +# Transition: AARD-1685 +# Remove wheel by joint name to avoid storing additional data about selected wheels. +# Should investigate finding a better way of linking joints and wheels. +def removeWheelFromConfigTab(joint: adsk.fusion.Joint) -> None: + try: + row = jointWheelIndexMap[joint.entityToken] + wheelConfigTable.deleteRow(row) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + + +def getSelectedJointsAndWheels() -> tuple[list[Joint], list[Wheel]]: joints: list[Joint] = [] + wheels: list[Wheel] = [] for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed + jointEntityToken = selectedJointList[row - 1].entityToken signalTypeIndex = jointConfigTable.getInputAtPosition(row, 3).selectedItem.index + signalType = SignalType(signalTypeIndex + 1) jointSpeed = jointConfigTable.getInputAtPosition(row, 4).value jointForce = jointConfigTable.getInputAtPosition(row, 5).value + isWheel = jointConfigTable.getInputAtPosition(row, 6).value joints.append( Joint( - selectedJointList[row - 1].entityToken, # Row is 1 indexed + jointEntityToken, JointParentType.ROOT, - SignalType(signalTypeIndex + 1), + signalType, jointSpeed, jointForce / 100.0, + isWheel, ) ) - return joints + if isWheel: + wheelRow = jointWheelIndexMap[jointEntityToken] + wheelTypeIndex = wheelConfigTable.getInputAtPosition(wheelRow, 2).selectedItem.index + wheels.append( + Wheel( + jointEntityToken, + WheelType(wheelTypeIndex + 1), + signalType, + ) + ) + + return (joints, wheels) def resetSelectedJoints() -> None: From 5cd297e4d1782f06adda6dc3d481b05f8b98a6d4 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 28 Jun 2024 15:28:44 -0700 Subject: [PATCH 10/21] Working link between joints and wheels --- .../src/Parser/ExporterOptions.py | 2 +- .../src/UI/ConfigCommand.py | 122 ++++++++++-------- .../src/UI/JointConfigTab.py | 75 ++++++++--- 3 files changed, 127 insertions(+), 72 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py index 4f7983ee4d..3ff717062a 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py @@ -18,7 +18,7 @@ # Not 100% sure what this is for - Brandon JointParentType = Enum("JointParentType", ["ROOT", "END"]) -WheelType = Enum("WheelType", ["STANDARD", "OMNI"]) +WheelType = Enum("WheelType", ["STANDARD", "OMNI", "MECANUM"]) SignalType = Enum("SignalType", ["PWM", "CAN", "PASSIVE"]) ExportMode = Enum("ExportMode", ["ROBOT", "FIELD"]) # Dynamic / Static export PreferredUnits = Enum("PreferredUnits", ["METRIC", "IMPERIAL"]) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 9f59245836..4f6d378b6b 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -15,8 +15,6 @@ ExportMode, ExporterOptions, Wheel, - WheelType, - SignalType, PreferredUnits, ) from .Configuration.SerialCommand import SerialCommand @@ -30,7 +28,8 @@ removeJointFromConfigTab, removeIndexedJointFromConfigTab, getSelectedJointsAndWheels, - resetSelectedJoints + resetSelectedJoints, + handleJointConfigTabInputChanged, ) import adsk.core @@ -412,12 +411,6 @@ def notify(self, args): # There remains some overlap between adding joints as wheels. # Should investigate changes to improve performance. createJointConfigTab(args) - if exporterOptions.wheels: - pass - for wheel in exporterOptions.wheels: - fusionJoint = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] - addWheelToConfigTab(fusionJoint, wheel) - if exporterOptions.joints: for synJoint in exporterOptions.joints: fusionJoint = gm.app.activeDocument.design.findEntityByToken(synJoint.jointToken)[0] @@ -430,6 +423,15 @@ def notify(self, args): if joint.jointMotion.jointType in (JointMotions.REVOLUTE.value, JointMotions.SLIDER.value) and not joint.isSuppressed: addJointToConfigTab(joint) + # Adding saved wheels must take place after joints are added as a result of how the two types are connected. + # Transition: AARD-1685 + # Should consider changing how the parser handles wheels and joints to avoid overlap + if exporterOptions.wheels: + pass + for wheel in exporterOptions.wheels: + fusionJoint = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] + addWheelToConfigTab(fusionJoint, wheel) + # ~~~~~~~~~~~~~~~~ GAMEPIECE CONFIGURATION ~~~~~~~~~~~~~~~~ """ Gamepiece group command input, isVisible=False by default @@ -1539,6 +1541,7 @@ def __init__(self, cmd): self.allWeights = [None, None] # [lbs, kg] self.isLbs = True self.isLbs_f = True + self.called = False def reset(self): """### Process: @@ -1589,13 +1592,22 @@ def notify(self, args): try: eventArgs = adsk.core.InputChangedEventArgs.cast(args) cmdInput = eventArgs.input + + # Transition: AARD-1685 + # This should be how all events are handled in separate files + # if not self.called: + handleJointConfigTabInputChanged(cmdInput) + # self.called = True + # else: + # self.called = False + MySelectHandler.lastInputCmd = cmdInput inputs = cmdInput.commandInputs onSelect = gm.handlers[3] frictionCoeff = INPUTS_ROOT.itemById("friction_coeff_override") - wheelSelect = inputs.itemById("wheel_select") + # wheelSelect = inputs.itemById("wheel_select") jointSelection = inputs.itemById("jointSelection") jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") gamepieceSelect = inputs.itemById("gamepiece_select") @@ -1609,11 +1621,11 @@ def notify(self, args): weight_input = INPUTS_ROOT.itemById("weight_input") - wheelConfig = inputs.itemById("wheel_config") - jointConfig = inputs.itemById("joint_config") + # wheelConfig = inputs.itemById("wheel_config") + # jointConfig = inputs.itemById("joint_config") gamepieceConfig = inputs.itemById("gamepiece_config") - addWheelInput = INPUTS_ROOT.itemById("wheel_add") + # addWheelInput = INPUTS_ROOT.itemById("wheel_add") addJointButton = INPUTS_ROOT.itemById("jointAddButton") removeJointButton = INPUTS_ROOT.itemById("jointRemoveButton") addFieldInput = INPUTS_ROOT.itemById("field_add") @@ -1635,37 +1647,37 @@ def notify(self, args): gamepieceConfig.isVisible = False weightTableInput.isVisible = True - addFieldInput.isEnabled = wheelConfig.isVisible = ( - jointConfig.isVisible - ) = True + # addFieldInput.isEnabled = wheelConfig.isVisible = ( + # jointConfig.isVisible + # ) = True elif modeDropdown.selectedItem.index == 1: if gamepieceConfig: gm.ui.activeSelections.clear() gm.app.activeDocument.design.rootComponent.opacity = 1 - addWheelInput.isEnabled = addJointButton.isEnabled = ( - gamepieceConfig.isVisible - ) = True + # addWheelInput.isEnabled = addJointButton.isEnabled = ( + # gamepieceConfig.isVisible + # ) = True - jointConfig.isVisible = wheelConfig.isVisible = ( - weightTableInput.isVisible - ) = False + # jointConfig.isVisible = wheelConfig.isVisible = ( + # weightTableInput.isVisible + # ) = False - elif cmdInput.id == "joint_config": - gm.app.activeDocument.design.rootComponent.opacity = 1 + # elif cmdInput.id == "joint_config": + # gm.app.activeDocument.design.rootComponent.opacity = 1 - elif ( - cmdInput.id == "placeholder_w" - or cmdInput.id == "name_w" - or cmdInput.id == "signal_type_w" - ): - self.reset() + # elif ( + # cmdInput.id == "placeholder_w" + # or cmdInput.id == "name_w" + # or cmdInput.id == "signal_type_w" + # ): + # self.reset() - wheelSelect.isEnabled = False - addWheelInput.isEnabled = True + # wheelSelect.isEnabled = False + # addWheelInput.isEnabled = True - cmdInput_str = cmdInput.id + # cmdInput_str = cmdInput.id # Transition: AARD-1685 # if cmdInput_str == "placeholder_w": @@ -1690,17 +1702,17 @@ def notify(self, args): # - 1 # ) - gm.ui.activeSelections.add(WheelListGlobal[position]) + # gm.ui.activeSelections.add(WheelListGlobal[position]) - elif ( - cmdInput.id == "placeholder" - or cmdInput.id == "name_j" - or cmdInput.id == "joint_parent" - or cmdInput.id == "signal_type" - ): - self.reset() - jointSelection.isEnabled = False - addJointButton.isEnabled = True + # elif ( + # cmdInput.id == "placeholder" + # or cmdInput.id == "name_j" + # or cmdInput.id == "joint_parent" + # or cmdInput.id == "signal_type" + # ): + # self.reset() + # jointSelection.isEnabled = False + # addJointButton.isEnabled = True elif ( cmdInput.id == "blank_gp" @@ -1785,23 +1797,23 @@ def notify(self, args): # iconInput.imageFile = IconPaths.wheelIcons["mecanum"] # iconInput.tooltip = "Mecanum wheel" - gm.ui.activeSelections.add(WheelListGlobal[position]) + # gm.ui.activeSelections.add(WheelListGlobal[position]) - elif cmdInput.id == "wheel_add": - self.reset() + # elif cmdInput.id == "wheel_add": + # self.reset() - wheelSelect.isVisible = True - wheelSelect.isEnabled = True - wheelSelect.clearSelection() - addJointButton.isEnabled = True - addWheelInput.isEnabled = False + # wheelSelect.isVisible = True + # wheelSelect.isEnabled = True + # wheelSelect.clearSelection() + # addJointButton.isEnabled = True + # addWheelInput.isEnabled = False # Transition: AARD-1685 # Functionality could potentially be moved into `JointConfigTab.py` elif cmdInput.id == "jointAddButton": self.reset() - addWheelInput.isEnabled = True + # addWheelInput.isEnabled = True jointSelection.isVisible = jointSelection.isEnabled = True jointSelection.clearSelection() addJointButton.isEnabled = removeJointButton.isEnabled = False @@ -1834,7 +1846,7 @@ def notify(self, args): gm.ui.activeSelections.clear() addJointButton.isEnabled = True - addWheelInput.isEnabled = True + # addWheelInput.isEnabled = True if jointTableInput.selectedRow == -1 or jointTableInput.selectedRow == 0: jointTableInput.selectedRow = jointTableInput.rowCount - 1 @@ -1858,8 +1870,8 @@ def notify(self, args): index = gamepieceTableInput.selectedRow - 1 removeGamePieceFromTable(index) - elif cmdInput.id == "wheel_select": - addWheelInput.isEnabled = True + # elif cmdInput.id == "wheel_select": + # addWheelInput.isEnabled = True elif cmdInput.id == "jointSelection": addJointButton.isEnabled = removeJointButton.isEnabled = True diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index 2dc628a1a6..4776935374 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -11,6 +11,7 @@ # Wish we did not need this. Could look into storing everything within the design every time - Brandon selectedJointList: list[adsk.fusion.Joint] = [] +previousWheelCheckboxState: list[bool] = [] jointWheelIndexMap: dict[str, int] = {} jointConfigTable: adsk.core.TableCommandInput wheelConfigTable: adsk.core.TableCommandInput @@ -256,7 +257,7 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = jointType.tooltipDescription = "
The root component is usually the parent." signalType = commandInputs.addDropDownCommandInput( - "signalType", + "signalTypeJoint", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) @@ -339,6 +340,8 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = checked=isWheel, enabled=wheelCheckboxEnabled, ), row, 6) + + previousWheelCheckboxState.append(isWheel) except: logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( "Failed:\n{}".format(traceback.format_exc()) @@ -356,13 +359,10 @@ def addWheelToConfigTab(joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> wheelName.tooltip = joint.name # TODO: Should this be the same? wheelType = commandInputs.addDropDownCommandInput("wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle) - if wheel: - standardWheelType = wheel.wheelType is WheelType.STANDARD - else: - standardWheelType = True - - wheelType.listItems.add("Standard", standardWheelType, "") - wheelType.listItems.add("OMNI", not standardWheelType, "") + selectedWheelType = wheel.wheelType if wheel else WheelType.STANDARD + wheelType.listItems.add("Standard", selectedWheelType is WheelType.STANDARD, "") + wheelType.listItems.add("OMNI", selectedWheelType is WheelType.OMNI, "") + wheelType.listItems.add("Mecanum", selectedWheelType is WheelType.MECANUM, "") wheelType.tooltip = "Wheel type" wheelType.tooltipDescription = "".join(["
Omni-directional wheels can be used just like regular drive wheels", "but they have the advantage of being able to roll freely perpendicular to", @@ -372,14 +372,11 @@ def addWheelToConfigTab(joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> signalType.isFullWidth = True signalType.isEnabled = False signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." - if wheel: - signalType.listItems.add("‎", wheel.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", wheel.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", wheel.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) - else: - signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) + i = selectedJointList.index(joint) + jointSignalType = SignalType(jointConfigTable.getInputAtPosition(i + 1, 3).selectedItem.index + 1) + signalType.listItems.add("‎", jointSignalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", jointSignalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", jointSignalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) row = wheelConfigTable.rowCount wheelConfigTable.addCommandInput(wheelIcon, row, 0) @@ -404,6 +401,7 @@ def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: i = selectedJointList.index(joint) selectedJointList.remove(joint) + previousWheelCheckboxState.pop(i) jointConfigTable.deleteRow(i + 1) for row in range(jointConfigTable.rowCount): # Row is 1 indexed # TODO: Step through this in the debugger and figure out if this is all necessary. @@ -434,6 +432,10 @@ def removeWheelFromConfigTab(joint: adsk.fusion.Joint) -> None: try: row = jointWheelIndexMap[joint.entityToken] wheelConfigTable.deleteRow(row) + del jointWheelIndexMap[joint.entityToken] + for key, value in jointWheelIndexMap.items(): + if value > row - 1: + jointWheelIndexMap[key] -= 1 except: logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( "Failed:\n{}".format(traceback.format_exc()) @@ -478,3 +480,44 @@ def getSelectedJointsAndWheels() -> tuple[list[Joint], list[Wheel]]: def resetSelectedJoints() -> None: selectedJointList.clear() + previousWheelCheckboxState.clear() + jointWheelIndexMap.clear() + + +def handleJointConfigTabInputChanged(commandInput: adsk.core.CommandInput) -> None: + if commandInput.id == "wheelType": + wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + position = wheelConfigTable.getPosition(wheelTypeDropdown)[1] + iconInput = wheelConfigTable.getInputAtPosition(position, 0) + + if wheelTypeDropdown.selectedItem.index == 0: + iconInput.imageFile = IconPaths.wheelIcons["standard"] + iconInput.tooltip = "Standard wheel" + elif wheelTypeDropdown.selectedItem.index == 1: + iconInput.imageFile = IconPaths.wheelIcons["omni"] + iconInput.tooltip = "Omni wheel" + elif wheelTypeDropdown.selectedItem.index == 2: + iconInput.imageFile = IconPaths.wheelIcons["mecanum"] + iconInput.tooltip = "Mecanum wheel" + + elif commandInput.id == "isWheel": + isWheelCheckbox = adsk.core.BoolValueCommandInput.cast(commandInput) + position = jointConfigTable.getPosition(isWheelCheckbox)[1] - 1 + isAlreadyWheel = bool(jointWheelIndexMap.get(selectedJointList[position].entityToken)) + + if isWheelCheckbox.value != previousWheelCheckboxState[position]: + if not isAlreadyWheel: + addWheelToConfigTab(selectedJointList[position]) + else: + removeWheelFromConfigTab(selectedJointList[position]) + + previousWheelCheckboxState[position] = isWheelCheckbox.value + + elif commandInput.id == "signalTypeJoint": + signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + position = jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed + wheelTabPosition = jointWheelIndexMap.get(selectedJointList[position - 1].entityToken) + + if wheelTabPosition: + wheelSignalItems = wheelConfigTable.getInputAtPosition(position, 3).listItems + wheelSignalItems.item(signalTypeDropdown.selectedItem.index).isSelected = True From 4ca5692668846939154c08f07d52b32140e601c5 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 12:22:47 -0700 Subject: [PATCH 11/21] Moved event handles into seperate files --- .../src/UI/ConfigCommand.py | 180 +++++++++--------- .../src/UI/JointConfigTab.py | 101 ++++++++-- 2 files changed, 175 insertions(+), 106 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 68d80258aa..7f5fdc88f2 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -28,14 +28,14 @@ # Transition: AARD-1685 # In the future all components should be handled in this way. -from .JointConfigTab import ( +from .JointConfigTab import ( # removeIndexedJointFromConfigTab,; removeJointFromConfigTab, addJointToConfigTab, addWheelToConfigTab, createJointConfigTab, getSelectedJointsAndWheels, handleJointConfigTabInputChanged, - removeIndexedJointFromConfigTab, - removeJointFromConfigTab, + handleJointConfigTabPreviewEvent, + handleJointConfigTabSelectionEvent, resetSelectedJoints, ) @@ -1098,21 +1098,24 @@ def notify(self, args): auto_calc_weight_f = INPUTS_ROOT.itemById("auto_calc_weight_f") - removeWheelInput = INPUTS_ROOT.itemById("wheel_delete") + # removeWheelInput = INPUTS_ROOT.itemById("wheel_delete") jointRemoveButton = INPUTS_ROOT.itemById("jointRemoveButton") jointSelection = INPUTS_ROOT.itemById("jointSelection") removeFieldInput = INPUTS_ROOT.itemById("field_delete") - addWheelInput = INPUTS_ROOT.itemById("wheel_add") + # addWheelInput = INPUTS_ROOT.itemById("wheel_add") addJointInput = INPUTS_ROOT.itemById("jointAddButton") addFieldInput = INPUTS_ROOT.itemById("field_add") # wheelTableInput = wheelTable() - inputs = args.command.commandInputs - jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById( - "jointTable" - ) + # inputs = args.command.commandInputs + # jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById( + # "jointTable" + # ) + + # Transition: AARD-1685 + handleJointConfigTabPreviewEvent(args) gamepieceTableInput = gamepieceTable() @@ -1121,26 +1124,26 @@ def notify(self, args): # else: # removeWheelInput.isEnabled = True - if jointTableInput.rowCount <= 1: - jointRemoveButton.isEnabled = False - elif not jointSelection.isEnabled: - jointRemoveButton.isEnabled = True + # if jointTableInput.rowCount <= 1: + # jointRemoveButton.isEnabled = False + # elif not jointSelection.isEnabled: + # jointRemoveButton.isEnabled = True if gamepieceTableInput.rowCount <= 1: removeFieldInput.isEnabled = auto_calc_weight_f.isEnabled = False else: removeFieldInput.isEnabled = auto_calc_weight_f.isEnabled = True - if not addWheelInput.isEnabled or not removeWheelInput: - # for wheel in WheelListGlobal: - # wheel.component.opacity = 0.25 - # CustomGraphics.createTextGraphics(wheel, WheelListGlobal) + # if not addWheelInput.isEnabled or not removeWheelInput: + # for wheel in WheelListGlobal: + # wheel.component.opacity = 0.25 + # CustomGraphics.createTextGraphics(wheel, WheelListGlobal) - gm.app.activeViewport.refresh() - else: - gm.app.activeDocument.design.rootComponent.opacity = 1 - for group in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: - group.deleteMe() + # gm.app.activeViewport.refresh() + # else: + # gm.app.activeDocument.design.rootComponent.opacity = 1 + # for group in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: + # group.deleteMe() if not addJointInput.isEnabled or not jointRemoveButton.isEnabled: # TODO: improve joint highlighting # for joint in JointListGlobal: @@ -1328,40 +1331,42 @@ def notify(self, args: adsk.core.SelectionEventArgs): selectionInput.isEnabled = False selectionInput.isVisible = False + # Transition: AARD-1685 elif self.selectedJoint: - self.cmd.setCursor("", 0, 0) - jointType = self.selectedJoint.jointMotion.jointType - if jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value: - # Transition: AARD-1685 - # if ( - # jointType == JointMotions.REVOLUTE.value - # and MySelectHandler.lastInputCmd.id == "wheel_select" - # ): - # addWheelToTable(self.selectedJoint) - # elif ( - # jointType == JointMotions.REVOLUTE.value - # and MySelectHandler.lastInputCmd.id == "wheel_remove" - # ): - # if self.selectedJoint in WheelListGlobal: - # removeWheelFromTable( - # WheelListGlobal.index(self.selectedJoint) - # ) - # else: - # Transition: AARD-1685 - # Should move selection handles into respective UI modules - if not addJointToConfigTab(self.selectedJoint): - result = gm.ui.messageBox( - "You have already selected this joint.\n" "Would you like to remove it?", - "Synthesis: Remove Joint Confirmation", - adsk.core.MessageBoxButtonTypes.YesNoButtonType, - adsk.core.MessageBoxIconTypes.QuestionIconType, - ) - - if result == adsk.core.DialogResults.DialogYes: - removeJointFromConfigTab(self.selectedJoint) - - selectionInput.isEnabled = False - selectionInput.isVisible = False + handleJointConfigTabSelectionEvent(args, self.selectedJoint) + # self.cmd.setCursor("", 0, 0) + # jointType = self.selectedJoint.jointMotion.jointType + # if jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value: + # Transition: AARD-1685 + # if ( + # jointType == JointMotions.REVOLUTE.value + # and MySelectHandler.lastInputCmd.id == "wheel_select" + # ): + # addWheelToTable(self.selectedJoint) + # elif ( + # jointType == JointMotions.REVOLUTE.value + # and MySelectHandler.lastInputCmd.id == "wheel_remove" + # ): + # if self.selectedJoint in WheelListGlobal: + # removeWheelFromTable( + # WheelListGlobal.index(self.selectedJoint) + # ) + # else: + # Transition: AARD-1685 + # Should move selection handles into respective UI modules + # if not addJointToConfigTab(self.selectedJoint): + # result = gm.ui.messageBox( + # "You have already selected this joint.\n" "Would you like to remove it?", + # "Synthesis: Remove Joint Confirmation", + # adsk.core.MessageBoxButtonTypes.YesNoButtonType, + # adsk.core.MessageBoxIconTypes.QuestionIconType, + # ) + + # if result == adsk.core.DialogResults.DialogYes: + # removeJointFromConfigTab(self.selectedJoint) + + # selectionInput.isEnabled = False + # selectionInput.isVisible = False except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) @@ -1529,12 +1534,7 @@ def notify(self, args): cmdInput = eventArgs.input # Transition: AARD-1685 - # This should be how all events are handled in separate files - # if not self.called: - handleJointConfigTabInputChanged(cmdInput) - # self.called = True - # else: - # self.called = False + handleJointConfigTabInputChanged(args, INPUTS_ROOT) MySelectHandler.lastInputCmd = cmdInput inputs = cmdInput.commandInputs @@ -1543,13 +1543,13 @@ def notify(self, args): frictionCoeff = INPUTS_ROOT.itemById("friction_coeff_override") # wheelSelect = inputs.itemById("wheel_select") - jointSelection = inputs.itemById("jointSelection") - jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") + # jointSelection = inputs.itemById("jointSelection") + # jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") gamepieceSelect = inputs.itemById("gamepiece_select") # wheelTableInput = wheelTable() - jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") + # jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") gamepieceTableInput = gamepieceTable() weightTableInput = inputs.itemById("weight_table") @@ -1561,8 +1561,8 @@ def notify(self, args): gamepieceConfig = inputs.itemById("gamepiece_config") # addWheelInput = INPUTS_ROOT.itemById("wheel_add") - addJointButton = INPUTS_ROOT.itemById("jointAddButton") - removeJointButton = INPUTS_ROOT.itemById("jointRemoveButton") + # addJointButton = INPUTS_ROOT.itemById("jointAddButton") + # removeJointButton = INPUTS_ROOT.itemById("jointRemoveButton") addFieldInput = INPUTS_ROOT.itemById("field_add") indicator = INPUTS_ROOT.itemById("algorithmic_indicator") @@ -1721,14 +1721,14 @@ def notify(self, args): # Transition: AARD-1685 # Functionality could potentially be moved into `JointConfigTab.py` - elif cmdInput.id == "jointAddButton": - self.reset() + # elif cmdInput.id == "jointAddButton": + # self.reset() - # addWheelInput.isEnabled = True - jointSelection.isVisible = jointSelection.isEnabled = True - jointSelection.clearSelection() - addJointButton.isEnabled = removeJointButton.isEnabled = False - jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True + # # addWheelInput.isEnabled = True + # jointSelection.isVisible = jointSelection.isEnabled = True + # jointSelection.clearSelection() + # addJointButton.isEnabled = removeJointButton.isEnabled = False + # jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True elif cmdInput.id == "field_add": self.reset() @@ -1753,18 +1753,18 @@ def notify(self, args): # Transition: AARD-1685 # Functionality could potentially be moved into `JointConfigTab.py` - elif cmdInput.id == "jointRemoveButton": - gm.ui.activeSelections.clear() + # elif cmdInput.id == "jointRemoveButton": + # gm.ui.activeSelections.clear() - addJointButton.isEnabled = True - # addWheelInput.isEnabled = True + # addJointButton.isEnabled = True + # # addWheelInput.isEnabled = True - if jointTableInput.selectedRow == -1 or jointTableInput.selectedRow == 0: - jointTableInput.selectedRow = jointTableInput.rowCount - 1 - gm.ui.messageBox("Select a row to delete.") - else: - # Select Row is 1 indexed - removeIndexedJointFromConfigTab(jointTableInput.selectedRow - 1) + # if jointTableInput.selectedRow == -1 or jointTableInput.selectedRow == 0: + # jointTableInput.selectedRow = jointTableInput.rowCount - 1 + # gm.ui.messageBox("Select a row to delete.") + # else: + # # Select Row is 1 indexed + # removeIndexedJointFromConfigTab(jointTableInput.selectedRow - 1) elif cmdInput.id == "field_delete": gm.ui.activeSelections.clear() @@ -1781,14 +1781,14 @@ def notify(self, args): # elif cmdInput.id == "wheel_select": # addWheelInput.isEnabled = True - elif cmdInput.id == "jointSelection": - addJointButton.isEnabled = removeJointButton.isEnabled = True - jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + # elif cmdInput.id == "jointSelection": + # addJointButton.isEnabled = removeJointButton.isEnabled = True + # jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - elif cmdInput.id == "jointSelectCancelButton": - jointSelection.isEnabled = jointSelection.isVisible = False - jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - addJointButton.isEnabled = removeJointButton.isEnabled = True + # elif cmdInput.id == "jointSelectCancelButton": + # jointSelection.isEnabled = jointSelection.isVisible = False + # jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + # addJointButton.isEnabled = removeJointButton.isEnabled = True elif cmdInput.id == "gamepiece_select": addFieldInput.isEnabled = True diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index a8a6507b6a..a644eee76f 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -121,6 +121,15 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: 6, ) + jointSelect = jointConfigTabInputs.addSelectionInput( + "jointSelection", "Selection", "Select a joint in your assembly to add." + ) + jointSelect.addSelectionFilter("Joints") + jointSelect.setSelectionLimits(0) + + # Visibility is triggered by `addJointInputButton` + jointSelect.isEnabled = jointSelect.isVisible = False + jointConfigTabInputs.addTextBoxCommandInput("jointTabBlankSpacer", "", "", 1, True) global wheelConfigTable @@ -174,15 +183,6 @@ def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: 3, ) - jointSelect = jointConfigTabInputs.addSelectionInput( - "jointSelection", "Selection", "Select a joint in your assembly to add." - ) - jointSelect.addSelectionFilter("Joints") - jointSelect.setSelectionLimits(0) - - # Visibility is triggered by `addJointInputButton` - jointSelect.isEnabled = jointSelect.isVisible = False - jointSelectCancelButton = jointConfigTabInputs.addBoolValueInput("jointSelectCancelButton", "Cancel", False) jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False @@ -285,7 +285,6 @@ def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = jointConfigTable.addCommandInput(jointType, row, 2) jointConfigTable.addCommandInput(signalType, row, 3) - # Joint speed must be added within an `if` because there is variance between different joint types # Comparison by `==` over `is` because the Autodesk API does not use `Enum` for their enum classes if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: if synJoint: @@ -422,10 +421,9 @@ def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: selectedJointList.remove(joint) previousWheelCheckboxState.pop(i) jointConfigTable.deleteRow(i + 1) - for row in range(jointConfigTable.rowCount): # Row is 1 indexed + for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed # TODO: Step through this in the debugger and figure out if this is all necessary. listItems = jointConfigTable.getInputAtPosition(row, 2).listItems - logging.getLogger(type(listItems)) if row > i: if listItems.item(i + 1).isSelected: listItems.item(i).isSelected = True @@ -444,9 +442,6 @@ def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: ) -# Transition: AARD-1685 -# Remove wheel by joint name to avoid storing additional data about selected wheels. -# Should investigate finding a better way of linking joints and wheels. def removeWheelFromConfigTab(joint: adsk.fusion.Joint) -> None: try: row = jointWheelIndexMap[joint.entityToken] @@ -503,7 +498,15 @@ def resetSelectedJoints() -> None: jointWheelIndexMap.clear() -def handleJointConfigTabInputChanged(commandInput: adsk.core.CommandInput) -> None: +# Transition: AARD-1685 +# Find a way to not pass the global commandInputs into this function +# Perhaps get the joint tab from the args then get what we want? +def handleJointConfigTabInputChanged( + args: adsk.core.InputChangedEventArgs, globalCommandInputs: adsk.core.CommandInputs +) -> None: + commandInput = args.input + + # TODO: Reorder if commandInput.id == "wheelType": wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) position = wheelConfigTable.getPosition(wheelTypeDropdown)[1] @@ -540,3 +543,69 @@ def handleJointConfigTabInputChanged(commandInput: adsk.core.CommandInput) -> No if wheelTabPosition: wheelSignalItems = wheelConfigTable.getInputAtPosition(position, 3).listItems wheelSignalItems.item(signalTypeDropdown.selectedItem.index).isSelected = True + + elif commandInput.id == "jointAddButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") + jointSelection = globalCommandInputs.itemById("jointSelection") + + jointSelection.isVisible = jointSelection.isEnabled = True + jointSelection.clearSelection() + jointAddButton.isEnabled = jointRemoveButton.isEnabled = False + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True + + elif commandInput.id == "jointRemoveButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointTable = args.inputs.itemById("jointTable") + + jointAddButton.isEnabled = True + + if jointTable.selectedRow == -1 or jointTable.selectedRow == 0: + ui = adsk.core.Application.get().userInterface + ui.messageBox("Select a row to delete.") + else: + # Select Row is 1 indexed + removeIndexedJointFromConfigTab(jointTable.selectedRow - 1) + + elif commandInput.id == "jointSelectCancelButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") + jointSelection = globalCommandInputs.itemById("jointSelection") + jointSelection.isEnabled = jointSelection.isVisible = False + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + + +def handleJointConfigTabSelectionEvent(args: adsk.core.SelectionEventArgs, selectedJoint: adsk.fusion.Joint) -> None: + selectionInput = args.activeInput + jointType = selectedJoint.jointMotion.jointType + if jointType == adsk.fusion.JointTypes.RevoluteJointType or jointType == adsk.fusion.JointTypes.SliderJointType: + if not addJointToConfigTab(selectedJoint): + ui = adsk.core.Application.get().userInterface + result = ui.messageBox( + "You have already selected this joint.\n" "Would you like to remove it?", + "Synthesis: Remove Joint Confirmation", + adsk.core.MessageBoxButtonTypes.YesNoButtonType, + adsk.core.MessageBoxIconTypes.QuestionIconType, + ) + + if result == adsk.core.DialogResults.DialogYes: + removeJointFromConfigTab(selectedJoint) + + selectionInput.isEnabled = selectionInput.isVisible = False + + +def handleJointConfigTabPreviewEvent(args: adsk.core.CommandEventArgs) -> None: + jointAddButton = args.command.commandInputs.itemById("jointAddButton") + jointRemoveButton = args.command.commandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = args.command.commandInputs.itemById("jointSelectCancelButton") + jointSelection = args.command.commandInputs.itemById("jointSelection") + + if jointConfigTable.rowCount <= 1: + jointRemoveButton.isEnabled = False + + if not jointSelection.isEnabled: + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = False From 0f88cee64286f9c758cc8690182a49eba8e90361 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 14:37:48 -0700 Subject: [PATCH 12/21] Classified Joint config table --- .../src/UI/ConfigCommand.py | 170 ++- .../src/UI/JointConfigTab.py | 1032 ++++++++--------- 2 files changed, 596 insertions(+), 606 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 7f5fdc88f2..5f723463d9 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -4,7 +4,6 @@ import logging import os -import platform import traceback from enum import Enum @@ -19,28 +18,20 @@ ExportMode, Gamepiece, PreferredUnits, - Wheel, ) from ..Parser.SynthesisParser.Parser import Parser from ..Parser.SynthesisParser.Utilities import guid_occurrence -from . import CustomGraphics, FileDialogConfig, Helper, IconPaths, OsHelper +from . import CustomGraphics, FileDialogConfig, Helper, IconPaths from .Configuration.SerialCommand import SerialCommand # Transition: AARD-1685 # In the future all components should be handled in this way. -from .JointConfigTab import ( # removeIndexedJointFromConfigTab,; removeJointFromConfigTab, - addJointToConfigTab, - addWheelToConfigTab, - createJointConfigTab, - getSelectedJointsAndWheels, - handleJointConfigTabInputChanged, - handleJointConfigTabPreviewEvent, - handleJointConfigTabSelectionEvent, - resetSelectedJoints, -) +from .JointConfigTab import JointConfigTab # ====================================== CONFIG COMMAND ====================================== +jointConfigTab: JointConfigTab + """ INPUTS_ROOT (adsk.fusion.CommandInputs): - Provides access to the set of all commandInput UI elements in the panel @@ -52,7 +43,7 @@ - WheelListGlobal: list of wheels (adsk.fusion.Occurrence) - GamepieceListGlobal: list of gamepieces (adsk.fusion.Occurrence) """ -WheelListGlobal = [] +# WheelListGlobal = [] GamepieceListGlobal = [] # Default to compressed files @@ -388,14 +379,17 @@ def notify(self, args): # 3, # ) + global jointConfigTab + jointConfigTab = JointConfigTab(args) + # Transition: AARD-1685 # There remains some overlap between adding joints as wheels. # Should investigate changes to improve performance. - createJointConfigTab(args) + # createJointConfigTab(args) if exporterOptions.joints: for synJoint in exporterOptions.joints: fusionJoint = gm.app.activeDocument.design.findEntityByToken(synJoint.jointToken)[0] - addJointToConfigTab(fusionJoint, synJoint) + jointConfigTab.addJoint(fusionJoint, synJoint) else: for joint in [ *gm.app.activeDocument.design.rootComponent.allJoints, @@ -405,7 +399,7 @@ def notify(self, args): joint.jointMotion.jointType in (JointMotions.REVOLUTE.value, JointMotions.SLIDER.value) and not joint.isSuppressed ): - addJointToConfigTab(joint) + jointConfigTab.addJoint(joint) # Adding saved wheels must take place after joints are added as a result of how the two types are connected. # Transition: AARD-1685 @@ -414,7 +408,7 @@ def notify(self, args): pass for wheel in exporterOptions.wheels: fusionJoint = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] - addWheelToConfigTab(fusionJoint, wheel) + jointConfigTab.addWheel(fusionJoint, wheel) # ~~~~~~~~~~~~~~~~ GAMEPIECE CONFIGURATION ~~~~~~~~~~~~~~~~ """ @@ -1046,7 +1040,7 @@ def notify(self, args): .children.itemById("compress") ).value - selectedJoints, selectedWheels = getSelectedJointsAndWheels() + selectedJoints, selectedWheels = jointConfigTab.getSelectedJointsAndWheels() exporterOptions = ExporterOptions( savepath, @@ -1069,7 +1063,7 @@ def notify(self, args): # All selections should be reset AFTER a successful export and save. # If we run into an exporting error we should return back to the panel with all current options # still in tact. Even if they did not save. - resetSelectedJoints() + jointConfigTab.reset() except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) @@ -1115,7 +1109,8 @@ def notify(self, args): # ) # Transition: AARD-1685 - handleJointConfigTabPreviewEvent(args) + # handleJointConfigTabPreviewEvent(args) + jointConfigTab.handlePreviewEvent(args) gamepieceTableInput = gamepieceTable() @@ -1333,7 +1328,8 @@ def notify(self, args: adsk.core.SelectionEventArgs): # Transition: AARD-1685 elif self.selectedJoint: - handleJointConfigTabSelectionEvent(args, self.selectedJoint) + jointConfigTab.handleSelectionEvent(args, self.selectedJoint) + # handleJointConfigTabSelectionEvent(args, self.selectedJoint) # self.cmd.setCursor("", 0, 0) # jointType = self.selectedJoint.jointMotion.jointType # if jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value: @@ -1534,7 +1530,8 @@ def notify(self, args): cmdInput = eventArgs.input # Transition: AARD-1685 - handleJointConfigTabInputChanged(args, INPUTS_ROOT) + # handleJointConfigTabInputChanged(args) + jointConfigTab.handleInputChanged(args, INPUTS_ROOT) MySelectHandler.lastInputCmd = cmdInput inputs = cmdInput.commandInputs @@ -1910,8 +1907,9 @@ def notify(self, args): try: onSelect = gm.handlers[3] - WheelListGlobal.clear() - resetSelectedJoints() + # WheelListGlobal.clear() + # resetSelectedJoints() + jointConfigTab.reset() GamepieceListGlobal.clear() onSelect.allWheelPreselections.clear() onSelect.wheelJointList.clear() @@ -1930,78 +1928,78 @@ def notify(self, args): ) -# Transition: AARD-1685 -def addWheelToTable(wheel: adsk.fusion.Joint) -> None: - """### Adds a wheel occurrence to its global list and wheel table. +# # Transition: AARD-1685 +# def addWheelToTable(wheel: adsk.fusion.Joint) -> None: +# """### Adds a wheel occurrence to its global list and wheel table. - Args: - wheel (adsk.fusion.Occurrence): wheel Occurrence object to be added. - """ - try: - try: - onSelect = gm.handlers[3] - onSelect.allWheelPreselections.append(wheel.entityToken) - except IndexError: - # Not 100% sure what we need the select handler here for however it should not run when - # first populating the saved wheel configs. This will naturally throw a IndexError as - # we do this before the initialization of gm.handlers[] - pass - - wheelTableInput = None - # def addPreselections(child_occurrences): - # for occ in child_occurrences: - # onSelect.allWheelPreselections.append(occ.entityToken) +# Args: +# wheel (adsk.fusion.Occurrence): wheel Occurrence object to be added. +# """ +# try: +# try: +# onSelect = gm.handlers[3] +# onSelect.allWheelPreselections.append(wheel.entityToken) +# except IndexError: +# # Not 100% sure what we need the select handler here for however it should not run when +# # first populating the saved wheel configs. This will naturally throw a IndexError as +# # we do this before the initialization of gm.handlers[] +# pass + +# wheelTableInput = None +# # def addPreselections(child_occurrences): +# # for occ in child_occurrences: +# # onSelect.allWheelPreselections.append(occ.entityToken) - # if occ.childOccurrences: - # addPreselections(occ.childOccurrences) +# # if occ.childOccurrences: +# # addPreselections(occ.childOccurrences) - # if wheel.childOccurrences: - # addPreselections(wheel.childOccurrences) - # else: +# # if wheel.childOccurrences: +# # addPreselections(wheel.childOccurrences) +# # else: - WheelListGlobal.append(wheel) - cmdInputs = adsk.core.CommandInputs.cast(wheelTableInput.commandInputs) +# # WheelListGlobal.append(wheel) +# cmdInputs = adsk.core.CommandInputs.cast(wheelTableInput.commandInputs) - icon = cmdInputs.addImageCommandInput("placeholder_w", "Placeholder", IconPaths.wheelIcons["standard"]) +# icon = cmdInputs.addImageCommandInput("placeholder_w", "Placeholder", IconPaths.wheelIcons["standard"]) - name = cmdInputs.addTextBoxCommandInput("name_w", "Joint name", wheel.name, 1, True) - name.tooltip = wheel.name +# name = cmdInputs.addTextBoxCommandInput("name_w", "Joint name", wheel.name, 1, True) +# name.tooltip = wheel.name - wheelType = cmdInputs.addDropDownCommandInput( - "wheel_type_w", - "Wheel Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) - wheelType.listItems.add("Standard", True, "") - wheelType.listItems.add("Omni", False, "") - wheelType.tooltip = "Wheel type" - wheelType.tooltipDescription = "
Omni-directional wheels can be used just like regular drive wheels but they have the advantage of being able to roll freely perpendicular to the drive direction.
" - wheelType.toolClipFilename = OsHelper.getOSPath(".", "src", "Resources") + os.path.join( - "WheelIcons", "omni-wheel-preview.png" - ) +# wheelType = cmdInputs.addDropDownCommandInput( +# "wheel_type_w", +# "Wheel Type", +# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, +# ) +# wheelType.listItems.add("Standard", True, "") +# wheelType.listItems.add("Omni", False, "") +# wheelType.tooltip = "Wheel type" +# wheelType.tooltipDescription = "
Omni-directional wheels can be used just like regular drive wheels but they have the advantage of being able to roll freely perpendicular to the drive direction.
" +# wheelType.toolClipFilename = OsHelper.getOSPath(".", "src", "Resources") + os.path.join( +# "WheelIcons", "omni-wheel-preview.png" +# ) - signalType = cmdInputs.addDropDownCommandInput( - "signal_type_w", - "Signal Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) - signalType.isFullWidth = True - signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) - signalType.tooltip = "Signal type" +# signalType = cmdInputs.addDropDownCommandInput( +# "signal_type_w", +# "Signal Type", +# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, +# ) +# signalType.isFullWidth = True +# signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) +# signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) +# signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) +# signalType.tooltip = "Signal type" - row = wheelTableInput.rowCount +# row = wheelTableInput.rowCount - wheelTableInput.addCommandInput(icon, row, 0) - wheelTableInput.addCommandInput(name, row, 1) - wheelTableInput.addCommandInput(wheelType, row, 2) - wheelTableInput.addCommandInput(signalType, row, 3) +# wheelTableInput.addCommandInput(icon, row, 0) +# wheelTableInput.addCommandInput(name, row, 1) +# wheelTableInput.addCommandInput(wheelType, row, 2) +# wheelTableInput.addCommandInput(signalType, row, 3) - except: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addWheelToTable()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) +# except: +# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addWheelToTable()").error( +# "Failed:\n{}".format(traceback.format_exc()) +# ) def addGamepieceToTable(gamepiece: adsk.fusion.Occurrence) -> None: diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index a644eee76f..8ad7f1893c 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -18,594 +18,586 @@ createTextBoxInput, ) -# Wish we did not need this. Could look into storing everything within the design every time - Brandon -selectedJointList: list[adsk.fusion.Joint] = [] -previousWheelCheckboxState: list[bool] = [] -jointWheelIndexMap: dict[str, int] = {} -jointConfigTable: adsk.core.TableCommandInput -wheelConfigTable: adsk.core.TableCommandInput - - -def createJointConfigTab(args: adsk.core.CommandCreatedEventArgs) -> None: - try: - inputs = args.command.commandInputs - jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") - jointConfigTab.tooltip = "Select and configure robot joints." - jointConfigTabInputs = jointConfigTab.children - - # TODO: Change background colors and such - Brandon - global jointConfigTable - jointConfigTable = createTableInput( - "jointTable", - "Joint Table", - jointConfigTabInputs, - 7, - "1:2:2:2:2:2:2", - ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "jointMotionHeader", - "Motion", +class JointConfigTab: + selectedJointList: list[adsk.fusion.Joint] = [] + previousWheelCheckboxState: list[bool] = [] + jointWheelIndexMap: dict[str, int] = {} + jointConfigTable: adsk.core.TableCommandInput + wheelConfigTable: adsk.core.TableCommandInput + + def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: + try: + inputs = args.command.commandInputs + jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") + jointConfigTab.tooltip = "Select and configure robot joints." + jointConfigTabInputs = jointConfigTab.children + + # TODO: Change background colors and such - Brandon + self.jointConfigTable = createTableInput( + "jointTable", + "Joint Table", jointConfigTabInputs, - "Motion", - bold=False, - ), - 0, - 0, - ) + 7, + "1:2:2:2:2:2:2", + ) - jointConfigTable.addCommandInput( - createTextBoxInput("nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False), - 0, - 1, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "jointMotionHeader", + "Motion", + jointConfigTabInputs, + "Motion", + bold=False, + ), + 0, + 0, + ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "parentHeader", - "Parent", - jointConfigTabInputs, - "Parent joint", - background="#d9d9d9", - ), - 0, - 2, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput("nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False), + 0, + 1, + ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "signalHeader", - "Signal", - jointConfigTabInputs, - "Signal type", - background="#d9d9d9", - ), - 0, - 3, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "parentHeader", + "Parent", + jointConfigTabInputs, + "Parent joint", + background="#d9d9d9", + ), + 0, + 2, + ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "speedHeader", - "Speed", - jointConfigTabInputs, - "Joint Speed", - background="#d9d9d9", - ), - 0, - 4, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "signalHeader", + "Signal", + jointConfigTabInputs, + "Signal type", + background="#d9d9d9", + ), + 0, + 3, + ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "forceHeader", - "Force", - jointConfigTabInputs, - "Joint Force", - background="#d9d9d9", - ), - 0, - 5, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "speedHeader", + "Speed", + jointConfigTabInputs, + "Joint Speed", + background="#d9d9d9", + ), + 0, + 4, + ) - jointConfigTable.addCommandInput( - createTextBoxInput( - "wheelHeader", - "Is Wheel", - jointConfigTabInputs, - "Is Wheel", - background="#d9d9d9", - ), - 0, - 6, - ) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "forceHeader", + "Force", + jointConfigTabInputs, + "Joint Force", + background="#d9d9d9", + ), + 0, + 5, + ) - jointSelect = jointConfigTabInputs.addSelectionInput( - "jointSelection", "Selection", "Select a joint in your assembly to add." - ) - jointSelect.addSelectionFilter("Joints") - jointSelect.setSelectionLimits(0) + self.jointConfigTable.addCommandInput( + createTextBoxInput( + "wheelHeader", + "Is Wheel", + jointConfigTabInputs, + "Is Wheel", + background="#d9d9d9", + ), + 0, + 6, + ) - # Visibility is triggered by `addJointInputButton` - jointSelect.isEnabled = jointSelect.isVisible = False + jointSelect = jointConfigTabInputs.addSelectionInput( + "jointSelection", "Selection", "Select a joint in your assembly to add." + ) + jointSelect.addSelectionFilter("Joints") + jointSelect.setSelectionLimits(0) - jointConfigTabInputs.addTextBoxCommandInput("jointTabBlankSpacer", "", "", 1, True) + # Visibility is triggered by `addJointInputButton` + jointSelect.isEnabled = jointSelect.isVisible = False - global wheelConfigTable - wheelConfigTable = createTableInput( - "wheelTable", - "Wheel Table", - jointConfigTabInputs, - 4, - "1:2:2:2", - ) + jointConfigTabInputs.addTextBoxCommandInput("jointTabBlankSpacer", "", "", 1, True) - wheelConfigTable.addCommandInput( - createTextBoxInput( - "wheelMotionHeader", - "Motion", + self.wheelConfigTable = createTableInput( + "wheelTable", + "Wheel Table", jointConfigTabInputs, - "Motion", - bold=False, - ), - 0, - 0, - ) + 4, + "1:2:2:2", + ) - wheelConfigTable.addCommandInput( - createTextBoxInput("name_header", "Name", jointConfigTabInputs, "Joint name", bold=False), - 0, - 1, - ) + self.wheelConfigTable.addCommandInput( + createTextBoxInput( + "wheelMotionHeader", + "Motion", + jointConfigTabInputs, + "Motion", + bold=False, + ), + 0, + 0, + ) - wheelConfigTable.addCommandInput( - createTextBoxInput( - "wheelTypeHeader", - "WheelType", - jointConfigTabInputs, - "Wheel type", - background="#d9d9d9", - ), - 0, - 2, - ) + self.wheelConfigTable.addCommandInput( + createTextBoxInput("name_header", "Name", jointConfigTabInputs, "Joint name", bold=False), + 0, + 1, + ) - wheelConfigTable.addCommandInput( - createTextBoxInput( - "signalTypeHeader", - "SignalType", - jointConfigTabInputs, - "Signal type", - background="#d9d9d9", - ), - 0, - 3, - ) + self.wheelConfigTable.addCommandInput( + createTextBoxInput( + "wheelTypeHeader", + "WheelType", + jointConfigTabInputs, + "Wheel type", + background="#d9d9d9", + ), + 0, + 2, + ) - jointSelectCancelButton = jointConfigTabInputs.addBoolValueInput("jointSelectCancelButton", "Cancel", False) - jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + self.wheelConfigTable.addCommandInput( + createTextBoxInput( + "signalTypeHeader", + "SignalType", + jointConfigTabInputs, + "Signal type", + background="#d9d9d9", + ), + 0, + 3, + ) - addJointInputButton = jointConfigTabInputs.addBoolValueInput("jointAddButton", "Add", False) - removeJointInputButton = jointConfigTabInputs.addBoolValueInput("jointRemoveButton", "Remove", False) - addJointInputButton.isEnabled = removeJointInputButton.isEnabled = True + jointSelectCancelButton = jointConfigTabInputs.addBoolValueInput("jointSelectCancelButton", "Cancel", False) + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - jointConfigTable.addToolbarCommandInput(addJointInputButton) - jointConfigTable.addToolbarCommandInput(removeJointInputButton) - jointConfigTable.addToolbarCommandInput(jointSelectCancelButton) - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + addJointInputButton = jointConfigTabInputs.addBoolValueInput("jointAddButton", "Add", False) + removeJointInputButton = jointConfigTabInputs.addBoolValueInput("jointRemoveButton", "Remove", False) + addJointInputButton.isEnabled = removeJointInputButton.isEnabled = True + self.jointConfigTable.addToolbarCommandInput(addJointInputButton) + self.jointConfigTable.addToolbarCommandInput(removeJointInputButton) + self.jointConfigTable.addToolbarCommandInput(jointSelectCancelButton) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) -def addJointToConfigTab(fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None) -> bool: - try: - if fusionJoint in selectedJointList: - return False + def addJoint(self, fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None) -> bool: + try: + if fusionJoint in self.selectedJointList: + return False - selectedJointList.append(fusionJoint) - commandInputs = jointConfigTable.commandInputs + self.selectedJointList.append(fusionJoint) + commandInputs = self.jointConfigTable.commandInputs - if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Rigid", IconPaths.jointIcons["rigid"]) - icon.tooltip = "Rigid joint" + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Rigid", IconPaths.jointIcons["rigid"]) + icon.tooltip = "Rigid joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Revolute", IconPaths.jointIcons["revolute"]) - icon.tooltip = "Revolute joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Revolute", IconPaths.jointIcons["revolute"]) + icon.tooltip = "Revolute joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Slider", IconPaths.jointIcons["slider"]) - icon.tooltip = "Slider joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Slider", IconPaths.jointIcons["slider"]) + icon.tooltip = "Slider joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Planar", IconPaths.jointIcons["planar"]) - icon.tooltip = "Planar joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Planar", IconPaths.jointIcons["planar"]) + icon.tooltip = "Planar joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"]) - icon.tooltip = "Pin slot joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"]) + icon.tooltip = "Pin slot joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"]) - icon.tooltip = "Cylindrical joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: + icon = commandInputs.addImageCommandInput( + "placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"] + ) + icon.tooltip = "Cylindrical joint" - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: - icon = commandInputs.addImageCommandInput("placeholder", "Ball", IconPaths.jointIcons["ball"]) - icon.tooltip = "Ball joint" + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: + icon = commandInputs.addImageCommandInput("placeholder", "Ball", IconPaths.jointIcons["ball"]) + icon.tooltip = "Ball joint" - name = commandInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) - name.tooltip = fusionJoint.name - name.formattedText = f"

{fusionJoint.name}

" + name = commandInputs.addTextBoxCommandInput("name_j", "Occurrence name", "", 1, True) + name.tooltip = fusionJoint.name + name.formattedText = f"

{fusionJoint.name}

" - jointType = commandInputs.addDropDownCommandInput( - "jointParent", - "Joint Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) + jointType = commandInputs.addDropDownCommandInput( + "jointParent", + "Joint Type", + dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, + ) - jointType.isFullWidth = True + jointType.isFullWidth = True - # Transition: AARD-1685 - # Implementation of joint parent system needs to be revisited. - jointType.listItems.add("Root", True) + # Transition: AARD-1685 + # Implementation of joint parent system needs to be revisited. + jointType.listItems.add("Root", True) - for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed - dropDown = jointConfigTable.getInputAtPosition(row, 2) - dropDown.listItems.add(selectedJointList[-1].name, False) + for row in range(1, self.jointConfigTable.rowCount): # Row is 1 indexed + dropDown = self.jointConfigTable.getInputAtPosition(row, 2) + dropDown.listItems.add(self.selectedJointList[-1].name, False) - for fusionJoint in selectedJointList: - jointType.listItems.add(fusionJoint.name, False) + for fusionJoint in self.selectedJointList: + jointType.listItems.add(fusionJoint.name, False) - jointType.tooltip = "Possible parent joints" - jointType.tooltipDescription = "
The root component is usually the parent." + jointType.tooltip = "Possible parent joints" + jointType.tooltipDescription = "
The root component is usually the parent." - signalType = commandInputs.addDropDownCommandInput( - "signalTypeJoint", - "Signal Type", - dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, - ) + signalType = commandInputs.addDropDownCommandInput( + "signalTypeJoint", + "Signal Type", + dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, + ) + + # TODO: Make this better, this is bad bad bad - Brandon + # if synJoint: + # signalType.listItems.add("", synJoint.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + # signalType.listItems.add("", synJoint.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + # signalType.listItems.add("", synJoint.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) + # else: + signalType.listItems.add("", True, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("", False, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("", False, IconPaths.signalIcons["PASSIVE"]) + + signalType.tooltip = "Signal type" + + row = self.jointConfigTable.rowCount + self.jointConfigTable.addCommandInput(icon, row, 0) + self.jointConfigTable.addCommandInput(name, row, 1) + self.jointConfigTable.addCommandInput(jointType, row, 2) + self.jointConfigTable.addCommandInput(signalType, row, 3) + + # Comparison by `==` over `is` because the Autodesk API does not use `Enum` for their enum classes + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + if synJoint: + jointSpeedValue = synJoint.speed + else: + jointSpeedValue = 3.1415926 + + jointSpeed = commandInputs.addValueInput( + "jointSpeed", + "Speed", + "deg", + adsk.core.ValueInput.createByReal(jointSpeedValue), + ) + jointSpeed.tooltip = "Degrees per second" + self.jointConfigTable.addCommandInput(jointSpeed, row, 4) + + elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: + if synJoint: + jointSpeedValue = synJoint.speed + else: + jointSpeedValue = 100 + + jointSpeed = commandInputs.addValueInput( + "jointSpeed", + "Speed", + "m", + adsk.core.ValueInput.createByReal(jointSpeedValue), + ) + jointSpeed.tooltip = "Meters per second" + self.jointConfigTable.addCommandInput(jointSpeed, row, 4) - # TODO: Make this better, this is bad bad bad - Brandon - if synJoint: - signalType.listItems.add("‎", synJoint.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", synJoint.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", synJoint.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) - else: - signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) - - signalType.tooltip = "Signal type" - - row = jointConfigTable.rowCount - jointConfigTable.addCommandInput(icon, row, 0) - jointConfigTable.addCommandInput(name, row, 1) - jointConfigTable.addCommandInput(jointType, row, 2) - jointConfigTable.addCommandInput(signalType, row, 3) - - # Comparison by `==` over `is` because the Autodesk API does not use `Enum` for their enum classes - if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: if synJoint: - jointSpeedValue = synJoint.speed + jointForceValue = synJoint.force * 100 # Currently a factor of 100 - Should be investigated else: - jointSpeedValue = 3.1415926 + jointForceValue = 5 - jointSpeed = commandInputs.addValueInput( - "jointSpeed", - "Speed", - "deg", - adsk.core.ValueInput.createByReal(jointSpeedValue), + jointForce = commandInputs.addValueInput( + "jointForce", "Force", "N", adsk.core.ValueInput.createByReal(jointForceValue) ) - jointSpeed.tooltip = "Degrees per second" - jointConfigTable.addCommandInput(jointSpeed, row, 4) + jointForce.tooltip = "Newtons" + self.jointConfigTable.addCommandInput(jointForce, row, 5) - elif fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: - if synJoint: - jointSpeedValue = synJoint.speed + if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: + wheelCheckboxEnabled = True + wheelCheckboxTooltip = "Determines if this joint should be counted as a wheel." else: - jointSpeedValue = 100 + wheelCheckboxEnabled = False + wheelCheckboxTooltip = "Only Revolute joints can be treated as wheels." + + isWheel = synJoint.isWheel if synJoint else False + + # Transition: AARD-1685 + # All command inputs should be created using the helpers. + self.jointConfigTable.addCommandInput( + createBooleanInput( + "isWheel", + "Is Wheel", + commandInputs, + wheelCheckboxTooltip, + checked=isWheel, + enabled=wheelCheckboxEnabled, + ), + row, + 6, + ) - jointSpeed = commandInputs.addValueInput( - "jointSpeed", - "Speed", - "m", - adsk.core.ValueInput.createByReal(jointSpeedValue), + self.previousWheelCheckboxState.append(isWheel) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) ) - jointSpeed.tooltip = "Meters per second" - jointConfigTable.addCommandInput(jointSpeed, row, 4) - if synJoint: - jointForceValue = synJoint.force * 100 # Currently a factor of 100 - Should be investigated - else: - jointForceValue = 5 + return True - jointForce = commandInputs.addValueInput( - "jointForce", "Force", "N", adsk.core.ValueInput.createByReal(jointForceValue) - ) - jointForce.tooltip = "Newtons" - jointConfigTable.addCommandInput(jointForce, row, 5) - - if fusionJoint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: - wheelCheckboxEnabled = True - wheelCheckboxTooltip = "Determines if this joint should be counted as a wheel." - else: - wheelCheckboxEnabled = False - wheelCheckboxTooltip = "Only Revolute joints can be treated as wheels." - - isWheel = synJoint.isWheel if synJoint else False - - # Transition: AARD-1685 - # All command inputs should be created using the helpers. - jointConfigTable.addCommandInput( - createBooleanInput( - "isWheel", - "Is Wheel", - commandInputs, - wheelCheckboxTooltip, - checked=isWheel, - enabled=wheelCheckboxEnabled, - ), - row, - 6, - ) + def addWheel(self, joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> None: + self.jointWheelIndexMap[joint.entityToken] = self.wheelConfigTable.rowCount - previousWheelCheckboxState.append(isWheel) - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) + commandInputs = self.wheelConfigTable.commandInputs + wheelIcon = commandInputs.addImageCommandInput( + "wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"] ) - - return True - - -def addWheelToConfigTab(joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> None: - jointWheelIndexMap[joint.entityToken] = wheelConfigTable.rowCount - - commandInputs = wheelConfigTable.commandInputs - wheelIcon = commandInputs.addImageCommandInput("wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"]) - wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) - wheelName.tooltip = joint.name # TODO: Should this be the same? - wheelType = commandInputs.addDropDownCommandInput( - "wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle - ) - - selectedWheelType = wheel.wheelType if wheel else WheelType.STANDARD - wheelType.listItems.add("Standard", selectedWheelType is WheelType.STANDARD, "") - wheelType.listItems.add("OMNI", selectedWheelType is WheelType.OMNI, "") - wheelType.listItems.add("Mecanum", selectedWheelType is WheelType.MECANUM, "") - wheelType.tooltip = "Wheel type" - wheelType.tooltipDescription = "".join( - [ - "
Omni-directional wheels can be used just like regular drive wheels", - "but they have the advantage of being able to roll freely perpendicular to", - "the drive direction.
", - ] - ) - - signalType = commandInputs.addDropDownCommandInput( - "wheelSignalType", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle - ) - signalType.isFullWidth = True - signalType.isEnabled = False - signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." - i = selectedJointList.index(joint) - jointSignalType = SignalType(jointConfigTable.getInputAtPosition(i + 1, 3).selectedItem.index + 1) - signalType.listItems.add("‎", jointSignalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", jointSignalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", jointSignalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) - - row = wheelConfigTable.rowCount - wheelConfigTable.addCommandInput(wheelIcon, row, 0) - wheelConfigTable.addCommandInput(wheelName, row, 1) - wheelConfigTable.addCommandInput(wheelType, row, 2) - wheelConfigTable.addCommandInput(signalType, row, 3) - - -def removeIndexedJointFromConfigTab(index: int) -> None: - try: - removeJointFromConfigTab(selectedJointList[index]) - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeIndexedJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) + wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) + wheelName.tooltip = joint.name # TODO: Should this be the same? + wheelType = commandInputs.addDropDownCommandInput( + "wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle ) - -def removeJointFromConfigTab(joint: adsk.fusion.Joint) -> None: - try: - if jointWheelIndexMap.get(joint.entityToken): - removeWheelFromConfigTab(joint) - - i = selectedJointList.index(joint) - selectedJointList.remove(joint) - previousWheelCheckboxState.pop(i) - jointConfigTable.deleteRow(i + 1) - for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed - # TODO: Step through this in the debugger and figure out if this is all necessary. - listItems = jointConfigTable.getInputAtPosition(row, 2).listItems - if row > i: - if listItems.item(i + 1).isSelected: - listItems.item(i).isSelected = True - listItems.item(i + 1).deleteMe() - else: - listItems.item(i + 1).deleteMe() - else: - if listItems.item(i).isSelected: - listItems.item(i - 1).isSelected = True - listItems.item(i).deleteMe() - else: - listItems.item(i).deleteMe() - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) + selectedWheelType = wheel.wheelType if wheel else WheelType.STANDARD + wheelType.listItems.add("Standard", selectedWheelType is WheelType.STANDARD, "") + wheelType.listItems.add("OMNI", selectedWheelType is WheelType.OMNI, "") + wheelType.listItems.add("Mecanum", selectedWheelType is WheelType.MECANUM, "") + wheelType.tooltip = "Wheel type" + wheelType.tooltipDescription = "".join( + [ + "
Omni-directional wheels can be used just like regular drive wheels", + "but they have the advantage of being able to roll freely perpendicular to", + "the drive direction.
", + ] ) - -def removeWheelFromConfigTab(joint: adsk.fusion.Joint) -> None: - try: - row = jointWheelIndexMap[joint.entityToken] - wheelConfigTable.deleteRow(row) - del jointWheelIndexMap[joint.entityToken] - for key, value in jointWheelIndexMap.items(): - if value > row - 1: - jointWheelIndexMap[key] -= 1 - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) + signalType = commandInputs.addDropDownCommandInput( + "wheelSignalType", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle ) + signalType.isFullWidth = True + signalType.isEnabled = False + signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." + i = self.selectedJointList.index(joint) + jointSignalType = SignalType(self.jointConfigTable.getInputAtPosition(i + 1, 3).selectedItem.index + 1) + signalType.listItems.add("‎", jointSignalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", jointSignalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", jointSignalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) + + row = self.wheelConfigTable.rowCount + self.wheelConfigTable.addCommandInput(wheelIcon, row, 0) + self.wheelConfigTable.addCommandInput(wheelName, row, 1) + self.wheelConfigTable.addCommandInput(wheelType, row, 2) + self.wheelConfigTable.addCommandInput(signalType, row, 3) + + def removeIndexedJoint(self, index: int) -> None: + try: + self.removeJoint(self.selectedJointList[index]) + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeIndexedJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) + def removeJoint(self, joint: adsk.fusion.Joint) -> None: + try: + if self.jointWheelIndexMap.get(joint.entityToken): + self.removeWheel(joint) + + i = self.selectedJointList.index(joint) + self.selectedJointList.remove(joint) + self.previousWheelCheckboxState.pop(i) + self.jointConfigTable.deleteRow(i + 1) + for row in range(1, self.jointConfigTable.rowCount): # Row is 1 indexed + # TODO: Step through this in the debugger and figure out if this is all necessary. + listItems = self.jointConfigTable.getInputAtPosition(row, 2).listItems + if row > i: + if listItems.item(i + 1).isSelected: + listItems.item(i).isSelected = True + listItems.item(i + 1).deleteMe() + else: + listItems.item(i + 1).deleteMe() + else: + if listItems.item(i).isSelected: + listItems.item(i - 1).isSelected = True + listItems.item(i).deleteMe() + else: + listItems.item(i).deleteMe() + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) -def getSelectedJointsAndWheels() -> tuple[list[Joint], list[Wheel]]: - joints: list[Joint] = [] - wheels: list[Wheel] = [] - for row in range(1, jointConfigTable.rowCount): # Row is 1 indexed - jointEntityToken = selectedJointList[row - 1].entityToken - signalTypeIndex = jointConfigTable.getInputAtPosition(row, 3).selectedItem.index - signalType = SignalType(signalTypeIndex + 1) - jointSpeed = jointConfigTable.getInputAtPosition(row, 4).value - jointForce = jointConfigTable.getInputAtPosition(row, 5).value - isWheel = jointConfigTable.getInputAtPosition(row, 6).value - - joints.append( - Joint( - jointEntityToken, - JointParentType.ROOT, - signalType, - jointSpeed, - jointForce / 100.0, - isWheel, + def removeWheel(self, joint: adsk.fusion.Joint) -> None: + try: + row = self.jointWheelIndexMap[joint.entityToken] + self.wheelConfigTable.deleteRow(row) + del self.jointWheelIndexMap[joint.entityToken] + for key, value in self.jointWheelIndexMap.items(): + if value > row - 1: + self.jointWheelIndexMap[key] -= 1 + except: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( + "Failed:\n{}".format(traceback.format_exc()) ) - ) - if isWheel: - wheelRow = jointWheelIndexMap[jointEntityToken] - wheelTypeIndex = wheelConfigTable.getInputAtPosition(wheelRow, 2).selectedItem.index - wheels.append( - Wheel( + def getSelectedJointsAndWheels(self) -> tuple[list[Joint], list[Wheel]]: + joints: list[Joint] = [] + wheels: list[Wheel] = [] + for row in range(1, self.jointConfigTable.rowCount): # Row is 1 indexed + jointEntityToken = self.selectedJointList[row - 1].entityToken + signalTypeIndex = self.jointConfigTable.getInputAtPosition(row, 3).selectedItem.index + signalType = SignalType(signalTypeIndex + 1) + jointSpeed = self.jointConfigTable.getInputAtPosition(row, 4).value + jointForce = self.jointConfigTable.getInputAtPosition(row, 5).value + isWheel = self.jointConfigTable.getInputAtPosition(row, 6).value + + joints.append( + Joint( jointEntityToken, - WheelType(wheelTypeIndex + 1), + JointParentType.ROOT, signalType, + jointSpeed, + jointForce / 100.0, + isWheel, ) ) - return (joints, wheels) - - -def resetSelectedJoints() -> None: - selectedJointList.clear() - previousWheelCheckboxState.clear() - jointWheelIndexMap.clear() - - -# Transition: AARD-1685 -# Find a way to not pass the global commandInputs into this function -# Perhaps get the joint tab from the args then get what we want? -def handleJointConfigTabInputChanged( - args: adsk.core.InputChangedEventArgs, globalCommandInputs: adsk.core.CommandInputs -) -> None: - commandInput = args.input - - # TODO: Reorder - if commandInput.id == "wheelType": - wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) - position = wheelConfigTable.getPosition(wheelTypeDropdown)[1] - iconInput = wheelConfigTable.getInputAtPosition(position, 0) - - if wheelTypeDropdown.selectedItem.index == 0: - iconInput.imageFile = IconPaths.wheelIcons["standard"] - iconInput.tooltip = "Standard wheel" - elif wheelTypeDropdown.selectedItem.index == 1: - iconInput.imageFile = IconPaths.wheelIcons["omni"] - iconInput.tooltip = "Omni wheel" - elif wheelTypeDropdown.selectedItem.index == 2: - iconInput.imageFile = IconPaths.wheelIcons["mecanum"] - iconInput.tooltip = "Mecanum wheel" - - elif commandInput.id == "isWheel": - isWheelCheckbox = adsk.core.BoolValueCommandInput.cast(commandInput) - position = jointConfigTable.getPosition(isWheelCheckbox)[1] - 1 - isAlreadyWheel = bool(jointWheelIndexMap.get(selectedJointList[position].entityToken)) - - if isWheelCheckbox.value != previousWheelCheckboxState[position]: - if not isAlreadyWheel: - addWheelToConfigTab(selectedJointList[position]) - else: - removeWheelFromConfigTab(selectedJointList[position]) - - previousWheelCheckboxState[position] = isWheelCheckbox.value - - elif commandInput.id == "signalTypeJoint": - signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) - position = jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed - wheelTabPosition = jointWheelIndexMap.get(selectedJointList[position - 1].entityToken) - - if wheelTabPosition: - wheelSignalItems = wheelConfigTable.getInputAtPosition(position, 3).listItems - wheelSignalItems.item(signalTypeDropdown.selectedItem.index).isSelected = True - - elif commandInput.id == "jointAddButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") - jointSelection = globalCommandInputs.itemById("jointSelection") - - jointSelection.isVisible = jointSelection.isEnabled = True - jointSelection.clearSelection() - jointAddButton.isEnabled = jointRemoveButton.isEnabled = False - jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True - - elif commandInput.id == "jointRemoveButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointTable = args.inputs.itemById("jointTable") - - jointAddButton.isEnabled = True - - if jointTable.selectedRow == -1 or jointTable.selectedRow == 0: - ui = adsk.core.Application.get().userInterface - ui.messageBox("Select a row to delete.") - else: - # Select Row is 1 indexed - removeIndexedJointFromConfigTab(jointTable.selectedRow - 1) - - elif commandInput.id == "jointSelectCancelButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") - jointSelection = globalCommandInputs.itemById("jointSelection") - jointSelection.isEnabled = jointSelection.isVisible = False - jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - jointAddButton.isEnabled = jointRemoveButton.isEnabled = True - - -def handleJointConfigTabSelectionEvent(args: adsk.core.SelectionEventArgs, selectedJoint: adsk.fusion.Joint) -> None: - selectionInput = args.activeInput - jointType = selectedJoint.jointMotion.jointType - if jointType == adsk.fusion.JointTypes.RevoluteJointType or jointType == adsk.fusion.JointTypes.SliderJointType: - if not addJointToConfigTab(selectedJoint): - ui = adsk.core.Application.get().userInterface - result = ui.messageBox( - "You have already selected this joint.\n" "Would you like to remove it?", - "Synthesis: Remove Joint Confirmation", - adsk.core.MessageBoxButtonTypes.YesNoButtonType, - adsk.core.MessageBoxIconTypes.QuestionIconType, - ) + if isWheel: + wheelRow = self.jointWheelIndexMap[jointEntityToken] + wheelTypeIndex = self.wheelConfigTable.getInputAtPosition(wheelRow, 2).selectedItem.index + wheels.append( + Wheel( + jointEntityToken, + WheelType(wheelTypeIndex + 1), + signalType, + ) + ) + + return (joints, wheels) + + def reset(self) -> None: + self.selectedJointList.clear() + self.previousWheelCheckboxState.clear() + self.jointWheelIndexMap.clear() + + # Transition: AARD-1685 + # Find a way to not pass the global commandInputs into this function + # Perhaps get the joint tab from the args then get what we want? + def handleInputChanged( + self, args: adsk.core.InputChangedEventArgs, globalCommandInputs: adsk.core.CommandInputs + ) -> None: + commandInput = args.input + + # TODO: Reorder + if commandInput.id == "wheelType": + wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + position = self.wheelConfigTable.getPosition(wheelTypeDropdown)[1] + iconInput = self.wheelConfigTable.getInputAtPosition(position, 0) + + if wheelTypeDropdown.selectedItem.index == 0: + iconInput.imageFile = IconPaths.wheelIcons["standard"] + iconInput.tooltip = "Standard wheel" + elif wheelTypeDropdown.selectedItem.index == 1: + iconInput.imageFile = IconPaths.wheelIcons["omni"] + iconInput.tooltip = "Omni wheel" + elif wheelTypeDropdown.selectedItem.index == 2: + iconInput.imageFile = IconPaths.wheelIcons["mecanum"] + iconInput.tooltip = "Mecanum wheel" + + elif commandInput.id == "isWheel": + isWheelCheckbox = adsk.core.BoolValueCommandInput.cast(commandInput) + position = self.jointConfigTable.getPosition(isWheelCheckbox)[1] - 1 + isAlreadyWheel = bool(self.jointWheelIndexMap.get(self.selectedJointList[position].entityToken)) + + if isWheelCheckbox.value != self.previousWheelCheckboxState[position]: + if not isAlreadyWheel: + self.addWheel(self.selectedJointList[position]) + else: + self.removeWheel(self.selectedJointList[position]) + + self.previousWheelCheckboxState[position] = isWheelCheckbox.value + + elif commandInput.id == "signalTypeJoint": + signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + position = self.jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed + wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[position - 1].entityToken) + + if wheelTabPosition: + wheelSignalItems = self.wheelConfigTable.getInputAtPosition(position, 3).listItems + wheelSignalItems.item(signalTypeDropdown.selectedItem.index).isSelected = True + + elif commandInput.id == "jointAddButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") + jointSelection = globalCommandInputs.itemById("jointSelection") - if result == adsk.core.DialogResults.DialogYes: - removeJointFromConfigTab(selectedJoint) + jointSelection.isVisible = jointSelection.isEnabled = True + jointSelection.clearSelection() + jointAddButton.isEnabled = jointRemoveButton.isEnabled = False + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True + + elif commandInput.id == "jointRemoveButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointTable = args.inputs.itemById("jointTable") + + jointAddButton.isEnabled = True + + if jointTable.selectedRow == -1 or jointTable.selectedRow == 0: + ui = adsk.core.Application.get().userInterface + ui.messageBox("Select a row to delete.") + else: + # Select Row is 1 indexed + self.removeIndexedJoint(jointTable.selectedRow - 1) + + elif commandInput.id == "jointSelectCancelButton": + jointAddButton = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") + jointSelection = globalCommandInputs.itemById("jointSelection") + jointSelection.isEnabled = jointSelection.isVisible = False + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + + def handleSelectionEvent(self, args: adsk.core.SelectionEventArgs, selectedJoint: adsk.fusion.Joint) -> None: + selectionInput = args.activeInput + jointType = selectedJoint.jointMotion.jointType + if jointType == adsk.fusion.JointTypes.RevoluteJointType or jointType == adsk.fusion.JointTypes.SliderJointType: + if not self.addJoint(selectedJoint): + ui = adsk.core.Application.get().userInterface + result = ui.messageBox( + "You have already selected this joint.\n" "Would you like to remove it?", + "Synthesis: Remove Joint Confirmation", + adsk.core.MessageBoxButtonTypes.YesNoButtonType, + adsk.core.MessageBoxIconTypes.QuestionIconType, + ) - selectionInput.isEnabled = selectionInput.isVisible = False + if result == adsk.core.DialogResults.DialogYes: + self.removeJoint(selectedJoint) + selectionInput.isEnabled = selectionInput.isVisible = False -def handleJointConfigTabPreviewEvent(args: adsk.core.CommandEventArgs) -> None: - jointAddButton = args.command.commandInputs.itemById("jointAddButton") - jointRemoveButton = args.command.commandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = args.command.commandInputs.itemById("jointSelectCancelButton") - jointSelection = args.command.commandInputs.itemById("jointSelection") + def handlePreviewEvent(self, args: adsk.core.CommandEventArgs) -> None: + jointAddButton = args.command.commandInputs.itemById("jointAddButton") + jointRemoveButton = args.command.commandInputs.itemById("jointRemoveButton") + jointSelectCancelButton = args.command.commandInputs.itemById("jointSelectCancelButton") + jointSelection = args.command.commandInputs.itemById("jointSelection") - if jointConfigTable.rowCount <= 1: - jointRemoveButton.isEnabled = False + if self.jointConfigTable.rowCount <= 1: + jointRemoveButton.isEnabled = False - if not jointSelection.isEnabled: - jointAddButton.isEnabled = jointRemoveButton.isEnabled = True - jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = False + if not jointSelection.isEnabled: + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = False From f1c318b6ca809b63e480a384401f0d0a2ebde608 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 14:43:56 -0700 Subject: [PATCH 13/21] Removed replaced code and handled transition tags --- .../src/UI/ConfigCommand.py | 482 +----------------- 1 file changed, 5 insertions(+), 477 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 5f723463d9..936d15ea4c 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -40,10 +40,8 @@ """ These lists are crucial, and contain all of the relevant object selections. -- WheelListGlobal: list of wheels (adsk.fusion.Occurrence) - GamepieceListGlobal: list of gamepieces (adsk.fusion.Occurrence) """ -# WheelListGlobal = [] GamepieceListGlobal = [] # Default to compressed files @@ -66,25 +64,6 @@ def GUID(arg): return arg.entityToken -# Transition: AARD-1865 -# def wheelTable(): -# """### Returns the wheel table command input - -# Returns: -# adsk.fusion.TableCommandInput -# """ -# return INPUTS_ROOT.itemById("wheel_table") - - -# def jointTable(): -# """### Returns the joint table command input - -# Returns: -# adsk.fusion.TableCommandInput -# """ -# return INPUTS_ROOT.itemById("joint_table") - - def gamepieceTable(): """### Returns the gamepiece table command input @@ -286,106 +265,12 @@ def notify(self, args): weightTableInput.addCommandInput(weight_input, 0, 2) # add command inputs to table weightTableInput.addCommandInput(weight_unit, 0, 3) # add command inputs to table - # Transition: AARD-1685 - # ~~~~~~~~~~~~~~~~ WHEEL CONFIGURATION ~~~~~~~~~~~~~~~~ - """ - Wheel configuration command input group - - Container for wheel selection Table - """ - # wheelConfig = inputs.addGroupCommandInput( - # "wheel_config", "Wheel Configuration" - # ) - # wheelConfig.isExpanded = True - # wheelConfig.isEnabled = True - # wheelConfig.tooltip = ( - # "Select and define the drive-train wheels in your assembly." - # ) - - # wheel_inputs = wheelConfig.children - - # # WHEEL SELECTION TABLE - # """ - # All selected wheel occurrences appear here. - # """ - # wheelTableInput = self.createTableInput( - # "wheel_table", - # "Wheel Table", - # wheel_inputs, - # 4, - # "1:4:2:2", - # 50, - # ) - - # addWheelInput = wheel_inputs.addBoolValueInput( - # "wheel_add", "Add", False - # ) # add button - - # removeWheelInput = wheel_inputs.addBoolValueInput( # remove button - # "wheel_delete", "Remove", False - # ) - - # addWheelInput.tooltip = "Add a wheel joint" # tooltips - # removeWheelInput.tooltip = "Remove a wheel joint" - - # wheelSelectInput = wheel_inputs.addSelectionInput( - # "wheel_select", - # "Selection", - # "Select the wheels joints in your drive-train assembly.", - # ) - # wheelSelectInput.addSelectionFilter( - # "Joints" - # ) # filter selection to only occurrences - - # wheelSelectInput.setSelectionLimits(0) # no selection count limit - # wheelSelectInput.isEnabled = False - # wheelSelectInput.isVisible = False - - # wheelTableInput.addToolbarCommandInput( - # addWheelInput - # ) # add buttons to the toolbar - # wheelTableInput.addToolbarCommandInput( - # removeWheelInput - # ) # add buttons to the toolbar - - # wheelTableInput.addCommandInput( # create textbox input using helper (component name) - # self.createTextBoxInput( - # "name_header", "Name", wheel_inputs, "Joint name", bold=False - # ), - # 0, - # 1, - # ) - - # wheelTableInput.addCommandInput( - # self.createTextBoxInput( # wheel type header - # "parent_header", - # "Parent", - # wheel_inputs, - # "Wheel type", - # background="#d9d9d9", # textbox header background color - # ), - # 0, - # 2, - # ) - - # wheelTableInput.addCommandInput( - # self.createTextBoxInput( # Signal type header - # "signal_header", - # "Signal", - # wheel_inputs, - # "Signal type", - # background="#d9d9d9", # textbox header background color - # ), - # 0, - # 3, - # ) - global jointConfigTab jointConfigTab = JointConfigTab(args) # Transition: AARD-1685 # There remains some overlap between adding joints as wheels. # Should investigate changes to improve performance. - # createJointConfigTab(args) if exporterOptions.joints: for synJoint in exporterOptions.joints: fusionJoint = gm.app.activeDocument.design.findEntityByToken(synJoint.jointToken)[0] @@ -1092,65 +977,19 @@ def notify(self, args): auto_calc_weight_f = INPUTS_ROOT.itemById("auto_calc_weight_f") - # removeWheelInput = INPUTS_ROOT.itemById("wheel_delete") - jointRemoveButton = INPUTS_ROOT.itemById("jointRemoveButton") - jointSelection = INPUTS_ROOT.itemById("jointSelection") - removeFieldInput = INPUTS_ROOT.itemById("field_delete") - - # addWheelInput = INPUTS_ROOT.itemById("wheel_add") - addJointInput = INPUTS_ROOT.itemById("jointAddButton") addFieldInput = INPUTS_ROOT.itemById("field_add") - - # wheelTableInput = wheelTable() - - # inputs = args.command.commandInputs - # jointTableInput: adsk.core.TableCommandInput = inputs.itemById("jointSettings").children.itemById( - # "jointTable" - # ) + removeFieldInput = INPUTS_ROOT.itemById("field_delete") # Transition: AARD-1685 - # handleJointConfigTabPreviewEvent(args) + # This is how all preview handles should be done in the future jointConfigTab.handlePreviewEvent(args) gamepieceTableInput = gamepieceTable() - - # if wheelTableInput.rowCount <= 1: - # removeWheelInput.isEnabled = False - # else: - # removeWheelInput.isEnabled = True - - # if jointTableInput.rowCount <= 1: - # jointRemoveButton.isEnabled = False - # elif not jointSelection.isEnabled: - # jointRemoveButton.isEnabled = True - if gamepieceTableInput.rowCount <= 1: removeFieldInput.isEnabled = auto_calc_weight_f.isEnabled = False else: removeFieldInput.isEnabled = auto_calc_weight_f.isEnabled = True - # if not addWheelInput.isEnabled or not removeWheelInput: - # for wheel in WheelListGlobal: - # wheel.component.opacity = 0.25 - # CustomGraphics.createTextGraphics(wheel, WheelListGlobal) - - # gm.app.activeViewport.refresh() - # else: - # gm.app.activeDocument.design.rootComponent.opacity = 1 - # for group in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: - # group.deleteMe() - - if not addJointInput.isEnabled or not jointRemoveButton.isEnabled: # TODO: improve joint highlighting - # for joint in JointListGlobal: - # CustomGraphics.highlightJointedOccurrences(joint) - - # gm.app.activeViewport.refresh() - gm.app.activeDocument.design.rootComponent.opacity = 0.15 - # else: - # for group in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: - # group.deleteMe() - # gm.app.activeDocument.design.rootComponent.opacity = 1 - if not addFieldInput.isEnabled or not removeFieldInput: for gamepiece in GamepieceListGlobal: gamepiece.component.opacity = 0.25 @@ -1327,42 +1166,10 @@ def notify(self, args: adsk.core.SelectionEventArgs): selectionInput.isVisible = False # Transition: AARD-1685 + # This is how all handle selection events should be done in the future although it will look + # slightly differently for each type of handle. elif self.selectedJoint: jointConfigTab.handleSelectionEvent(args, self.selectedJoint) - # handleJointConfigTabSelectionEvent(args, self.selectedJoint) - # self.cmd.setCursor("", 0, 0) - # jointType = self.selectedJoint.jointMotion.jointType - # if jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value: - # Transition: AARD-1685 - # if ( - # jointType == JointMotions.REVOLUTE.value - # and MySelectHandler.lastInputCmd.id == "wheel_select" - # ): - # addWheelToTable(self.selectedJoint) - # elif ( - # jointType == JointMotions.REVOLUTE.value - # and MySelectHandler.lastInputCmd.id == "wheel_remove" - # ): - # if self.selectedJoint in WheelListGlobal: - # removeWheelFromTable( - # WheelListGlobal.index(self.selectedJoint) - # ) - # else: - # Transition: AARD-1685 - # Should move selection handles into respective UI modules - # if not addJointToConfigTab(self.selectedJoint): - # result = gm.ui.messageBox( - # "You have already selected this joint.\n" "Would you like to remove it?", - # "Synthesis: Remove Joint Confirmation", - # adsk.core.MessageBoxButtonTypes.YesNoButtonType, - # adsk.core.MessageBoxIconTypes.QuestionIconType, - # ) - - # if result == adsk.core.DialogResults.DialogYes: - # removeJointFromConfigTab(self.selectedJoint) - - # selectionInput.isEnabled = False - # selectionInput.isVisible = False except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) @@ -1530,7 +1337,7 @@ def notify(self, args): cmdInput = eventArgs.input # Transition: AARD-1685 - # handleJointConfigTabInputChanged(args) + # Should be how all input changed handles are done in the future jointConfigTab.handleInputChanged(args, INPUTS_ROOT) MySelectHandler.lastInputCmd = cmdInput @@ -1539,27 +1346,12 @@ def notify(self, args): frictionCoeff = INPUTS_ROOT.itemById("friction_coeff_override") - # wheelSelect = inputs.itemById("wheel_select") - # jointSelection = inputs.itemById("jointSelection") - # jointSelectCancelButton = INPUTS_ROOT.itemById("jointSelectCancelButton") gamepieceSelect = inputs.itemById("gamepiece_select") - - # wheelTableInput = wheelTable() - - # jointTableInput: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") - gamepieceTableInput = gamepieceTable() weightTableInput = inputs.itemById("weight_table") weight_input = INPUTS_ROOT.itemById("weight_input") - - # wheelConfig = inputs.itemById("wheel_config") - # jointConfig = inputs.itemById("joint_config") gamepieceConfig = inputs.itemById("gamepiece_config") - - # addWheelInput = INPUTS_ROOT.itemById("wheel_add") - # addJointButton = INPUTS_ROOT.itemById("jointAddButton") - # removeJointButton = INPUTS_ROOT.itemById("jointRemoveButton") addFieldInput = INPUTS_ROOT.itemById("field_add") indicator = INPUTS_ROOT.itemById("algorithmic_indicator") @@ -1596,56 +1388,6 @@ def notify(self, args): # weightTableInput.isVisible # ) = False - # elif cmdInput.id == "joint_config": - # gm.app.activeDocument.design.rootComponent.opacity = 1 - - # elif ( - # cmdInput.id == "placeholder_w" - # or cmdInput.id == "name_w" - # or cmdInput.id == "signal_type_w" - # ): - # self.reset() - - # wheelSelect.isEnabled = False - # addWheelInput.isEnabled = True - - # cmdInput_str = cmdInput.id - - # Transition: AARD-1685 - # if cmdInput_str == "placeholder_w": - # position = ( - # wheelTableInput.getPosition( - # adsk.core.ImageCommandInput.cast(cmdInput) - # )[1] - # - 1 - # ) - # elif cmdInput_str == "name_w": - # position = ( - # wheelTableInput.getPosition( - # adsk.core.TextBoxCommandInput.cast(cmdInput) - # )[1] - # - 1 - # ) - # elif cmdInput_str == "signal_type_w": - # position = ( - # wheelTableInput.getPosition( - # adsk.core.DropDownCommandInput.cast(cmdInput) - # )[1] - # - 1 - # ) - - # gm.ui.activeSelections.add(WheelListGlobal[position]) - - # elif ( - # cmdInput.id == "placeholder" - # or cmdInput.id == "name_j" - # or cmdInput.id == "joint_parent" - # or cmdInput.id == "signal_type" - # ): - # self.reset() - # jointSelection.isEnabled = False - # addJointButton.isEnabled = True - elif cmdInput.id == "blank_gp" or cmdInput.id == "name_gp" or cmdInput.id == "weight_gp": self.reset() @@ -1665,68 +1407,6 @@ def notify(self, args): gm.ui.activeSelections.add(GamepieceListGlobal[position]) - # Transition: AARD-1685 - # elif cmdInput.id == "wheel_type_w": - # self.reset() - - # wheelSelect.isEnabled = False - # addWheelInput.isEnabled = True - - # cmdInput_str = cmdInput.id - # position = ( - # wheelTableInput.getPosition( - # adsk.core.DropDownCommandInput.cast(cmdInput) - # )[1] - # - 1 - # ) - # wheelDropdown = adsk.core.DropDownCommandInput.cast(cmdInput) - - # if wheelDropdown.selectedItem.index == 0: - # getPosition = wheelTableInput.getPosition( - # adsk.core.DropDownCommandInput.cast(cmdInput) - # ) - # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - # iconInput.imageFile = IconPaths.wheelIcons["standard"] - # iconInput.tooltip = "Standard wheel" - - # elif wheelDropdown.selectedItem.index == 1: - # getPosition = wheelTableInput.getPosition( - # adsk.core.DropDownCommandInput.cast(cmdInput) - # ) - # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - # iconInput.imageFile = IconPaths.wheelIcons["omni"] - # iconInput.tooltip = "Omni wheel" - - # elif wheelDropdown.selectedItem.index == 2: - # getPosition = wheelTableInput.getPosition( - # adsk.core.DropDownCommandInput.cast(cmdInput) - # ) - # iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) - # iconInput.imageFile = IconPaths.wheelIcons["mecanum"] - # iconInput.tooltip = "Mecanum wheel" - - # gm.ui.activeSelections.add(WheelListGlobal[position]) - - # elif cmdInput.id == "wheel_add": - # self.reset() - - # wheelSelect.isVisible = True - # wheelSelect.isEnabled = True - # wheelSelect.clearSelection() - # addJointButton.isEnabled = True - # addWheelInput.isEnabled = False - - # Transition: AARD-1685 - # Functionality could potentially be moved into `JointConfigTab.py` - # elif cmdInput.id == "jointAddButton": - # self.reset() - - # # addWheelInput.isEnabled = True - # jointSelection.isVisible = jointSelection.isEnabled = True - # jointSelection.clearSelection() - # addJointButton.isEnabled = removeJointButton.isEnabled = False - # jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True - elif cmdInput.id == "field_add": self.reset() @@ -1735,34 +1415,6 @@ def notify(self, args): gamepieceSelect.clearSelection() addFieldInput.isEnabled = False - # Transition: AARD-1685 - # elif cmdInput.id == "wheel_delete": - # # Currently causes Internal Autodesk Error - # # gm.ui.activeSelections.clear() - - # addWheelInput.isEnabled = True - # if wheelTableInput.selectedRow == -1 or wheelTableInput.selectedRow == 0: - # wheelTableInput.selectedRow = wheelTableInput.rowCount - 1 - # gm.ui.messageBox("Select a row to delete.") - # else: - # index = wheelTableInput.selectedRow - 1 - # removeWheelFromTable(index) - - # Transition: AARD-1685 - # Functionality could potentially be moved into `JointConfigTab.py` - # elif cmdInput.id == "jointRemoveButton": - # gm.ui.activeSelections.clear() - - # addJointButton.isEnabled = True - # # addWheelInput.isEnabled = True - - # if jointTableInput.selectedRow == -1 or jointTableInput.selectedRow == 0: - # jointTableInput.selectedRow = jointTableInput.rowCount - 1 - # gm.ui.messageBox("Select a row to delete.") - # else: - # # Select Row is 1 indexed - # removeIndexedJointFromConfigTab(jointTableInput.selectedRow - 1) - elif cmdInput.id == "field_delete": gm.ui.activeSelections.clear() @@ -1775,18 +1427,6 @@ def notify(self, args): index = gamepieceTableInput.selectedRow - 1 removeGamePieceFromTable(index) - # elif cmdInput.id == "wheel_select": - # addWheelInput.isEnabled = True - - # elif cmdInput.id == "jointSelection": - # addJointButton.isEnabled = removeJointButton.isEnabled = True - # jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - - # elif cmdInput.id == "jointSelectCancelButton": - # jointSelection.isEnabled = jointSelection.isVisible = False - # jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - # addJointButton.isEnabled = removeJointButton.isEnabled = True - elif cmdInput.id == "gamepiece_select": addFieldInput.isEnabled = True @@ -1907,8 +1547,6 @@ def notify(self, args): try: onSelect = gm.handlers[3] - # WheelListGlobal.clear() - # resetSelectedJoints() jointConfigTab.reset() GamepieceListGlobal.clear() onSelect.allWheelPreselections.clear() @@ -1928,80 +1566,6 @@ def notify(self, args): ) -# # Transition: AARD-1685 -# def addWheelToTable(wheel: adsk.fusion.Joint) -> None: -# """### Adds a wheel occurrence to its global list and wheel table. - -# Args: -# wheel (adsk.fusion.Occurrence): wheel Occurrence object to be added. -# """ -# try: -# try: -# onSelect = gm.handlers[3] -# onSelect.allWheelPreselections.append(wheel.entityToken) -# except IndexError: -# # Not 100% sure what we need the select handler here for however it should not run when -# # first populating the saved wheel configs. This will naturally throw a IndexError as -# # we do this before the initialization of gm.handlers[] -# pass - -# wheelTableInput = None -# # def addPreselections(child_occurrences): -# # for occ in child_occurrences: -# # onSelect.allWheelPreselections.append(occ.entityToken) - -# # if occ.childOccurrences: -# # addPreselections(occ.childOccurrences) - -# # if wheel.childOccurrences: -# # addPreselections(wheel.childOccurrences) -# # else: - -# # WheelListGlobal.append(wheel) -# cmdInputs = adsk.core.CommandInputs.cast(wheelTableInput.commandInputs) - -# icon = cmdInputs.addImageCommandInput("placeholder_w", "Placeholder", IconPaths.wheelIcons["standard"]) - -# name = cmdInputs.addTextBoxCommandInput("name_w", "Joint name", wheel.name, 1, True) -# name.tooltip = wheel.name - -# wheelType = cmdInputs.addDropDownCommandInput( -# "wheel_type_w", -# "Wheel Type", -# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, -# ) -# wheelType.listItems.add("Standard", True, "") -# wheelType.listItems.add("Omni", False, "") -# wheelType.tooltip = "Wheel type" -# wheelType.tooltipDescription = "
Omni-directional wheels can be used just like regular drive wheels but they have the advantage of being able to roll freely perpendicular to the drive direction.
" -# wheelType.toolClipFilename = OsHelper.getOSPath(".", "src", "Resources") + os.path.join( -# "WheelIcons", "omni-wheel-preview.png" -# ) - -# signalType = cmdInputs.addDropDownCommandInput( -# "signal_type_w", -# "Signal Type", -# dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, -# ) -# signalType.isFullWidth = True -# signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) -# signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) -# signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) -# signalType.tooltip = "Signal type" - -# row = wheelTableInput.rowCount - -# wheelTableInput.addCommandInput(icon, row, 0) -# wheelTableInput.addCommandInput(name, row, 1) -# wheelTableInput.addCommandInput(wheelType, row, 2) -# wheelTableInput.addCommandInput(signalType, row, 3) - -# except: -# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.addWheelToTable()").error( -# "Failed:\n{}".format(traceback.format_exc()) -# ) - - def addGamepieceToTable(gamepiece: adsk.fusion.Occurrence) -> None: """### Adds a gamepiece occurrence to its global list and gamepiece table. @@ -2077,42 +1641,6 @@ def addPreselections(child_occurrences): ) -# Transition: AARD-1685 -# def removeWheelFromTable(index: int) -> None: -# """### Removes a wheel joint from its global list and wheel table. - -# Args: -# index (int): index of wheel item in its global list -# """ -# try: -# onSelect = gm.handlers[3] -# wheelTableInput = wheelTable() -# wheel = WheelListGlobal[index] - -# # def removePreselections(child_occurrences): -# # for occ in child_occurrences: -# # onSelect.allWheelPreselections.remove(occ.entityToken) - -# # if occ.childOccurrences: -# # removePreselections(occ.childOccurrences) - -# # if wheel.childOccurrences: -# # removePreselections(wheel.childOccurrences) -# # else: -# onSelect.allWheelPreselections.remove(wheel.entityToken) - -# del WheelListGlobal[index] -# wheelTableInput.deleteRow(index + 1) - -# # updateJointTable(wheel) -# except IndexError: -# pass -# except: -# logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeWheelFromTable()").error( -# "Failed:\n{}".format(traceback.format_exc()) -# ) - - def removeGamePieceFromTable(index: int) -> None: """### Removes a gamepiece occurrence from its global list and gamepiece table. From 3bfb556f8898dbdb98b9c5dab72ed75b1ac1c3b1 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 15:04:34 -0700 Subject: [PATCH 14/21] Bogus bug fixes --- .../src/UI/JointConfigTab.py | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index 8ad7f1893c..d9b7aaaad7 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -191,6 +191,8 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: self.jointConfigTable.addToolbarCommandInput(addJointInputButton) self.jointConfigTable.addToolbarCommandInput(removeJointInputButton) self.jointConfigTable.addToolbarCommandInput(jointSelectCancelButton) + + self.reset() except: logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( "Failed:\n{}".format(traceback.format_exc()) @@ -266,15 +268,18 @@ def addJoint(self, fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) - # TODO: Make this better, this is bad bad bad - Brandon - # if synJoint: - # signalType.listItems.add("", synJoint.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) - # signalType.listItems.add("", synJoint.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) - # signalType.listItems.add("", synJoint.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) - # else: - signalType.listItems.add("", True, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("", False, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("", False, IconPaths.signalIcons["PASSIVE"]) + # Invisible white space characters are required in the list item name field to make this work. + # I have no idea why, Fusion API needs some special education help - Brandon + if synJoint: + signalType.listItems.add("‎", synJoint.signalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", synJoint.signalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add( + "‎", synJoint.signalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"] + ) + else: + signalType.listItems.add("‎", True, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", False, IconPaths.signalIcons["PASSIVE"]) signalType.tooltip = "Signal type" @@ -531,12 +536,13 @@ def handleInputChanged( elif commandInput.id == "signalTypeJoint": signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) - position = self.jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed - wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[position - 1].entityToken) + jointTabPosition = self.jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed + wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[jointTabPosition - 1].entityToken) if wheelTabPosition: - wheelSignalItems = self.wheelConfigTable.getInputAtPosition(position, 3).listItems - wheelSignalItems.item(signalTypeDropdown.selectedItem.index).isSelected = True + wheelSignalItems: adsk.core.DropDownCommandInput + wheelSignalItems = self.wheelConfigTable.getInputAtPosition(wheelTabPosition, 3) + wheelSignalItems.listItems.item(signalTypeDropdown.selectedItem.index).isSelected = True elif commandInput.id == "jointAddButton": jointAddButton = globalCommandInputs.itemById("jointAddButton") From 35c3820ba93eb2f0d8b41d7658adb6e89d909016 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 15:40:18 -0700 Subject: [PATCH 15/21] Added typing and improved comments + formatting --- .../src/UI/ConfigCommand.py | 1 + .../src/UI/JointConfigTab.py | 162 ++++++------------ 2 files changed, 49 insertions(+), 114 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 936d15ea4c..0ecdc91faa 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -26,6 +26,7 @@ # Transition: AARD-1685 # In the future all components should be handled in this way. +# This import broke everything when attempting to use absolute imports??? Investigate? from .JointConfigTab import JointConfigTab # ====================================== CONFIG COMMAND ====================================== diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index d9b7aaaad7..f734c3171c 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -23,99 +23,57 @@ class JointConfigTab: selectedJointList: list[adsk.fusion.Joint] = [] previousWheelCheckboxState: list[bool] = [] jointWheelIndexMap: dict[str, int] = {} + jointConfigTab: adsk.core.TabCommandInput jointConfigTable: adsk.core.TableCommandInput wheelConfigTable: adsk.core.TableCommandInput def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: try: inputs = args.command.commandInputs - jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") - jointConfigTab.tooltip = "Select and configure robot joints." - jointConfigTabInputs = jointConfigTab.children + self.jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") + self.jointConfigTab.tooltip = "Select and configure robot joints." + jointConfigTabInputs = self.jointConfigTab.children - # TODO: Change background colors and such - Brandon self.jointConfigTable = createTableInput( - "jointTable", - "Joint Table", - jointConfigTabInputs, - 7, - "1:2:2:2:2:2:2", + "jointTable", "Joint Table", jointConfigTabInputs, 7, "1:2:2:2:2:2:2" ) self.jointConfigTable.addCommandInput( - createTextBoxInput( - "jointMotionHeader", - "Motion", - jointConfigTabInputs, - "Motion", - bold=False, - ), - 0, - 0, + createTextBoxInput("jointMotionHeader", "Motion", jointConfigTabInputs, "Motion", bold=False), 0, 0 ) self.jointConfigTable.addCommandInput( - createTextBoxInput("nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False), - 0, - 1, + createTextBoxInput("nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False), 0, 1 ) self.jointConfigTable.addCommandInput( createTextBoxInput( - "parentHeader", - "Parent", - jointConfigTabInputs, - "Parent joint", - background="#d9d9d9", + "parentHeader", "Parent", jointConfigTabInputs, "Parent joint", background="#d9d9d9" ), 0, 2, ) self.jointConfigTable.addCommandInput( - createTextBoxInput( - "signalHeader", - "Signal", - jointConfigTabInputs, - "Signal type", - background="#d9d9d9", - ), + createTextBoxInput("signalHeader", "Signal", jointConfigTabInputs, "Signal type", background="#d9d9d9"), 0, 3, ) self.jointConfigTable.addCommandInput( - createTextBoxInput( - "speedHeader", - "Speed", - jointConfigTabInputs, - "Joint Speed", - background="#d9d9d9", - ), + createTextBoxInput("speedHeader", "Speed", jointConfigTabInputs, "Joint Speed", background="#d9d9d9"), 0, 4, ) self.jointConfigTable.addCommandInput( - createTextBoxInput( - "forceHeader", - "Force", - jointConfigTabInputs, - "Joint Force", - background="#d9d9d9", - ), + createTextBoxInput("forceHeader", "Force", jointConfigTabInputs, "Joint Force", background="#d9d9d9"), 0, 5, ) self.jointConfigTable.addCommandInput( - createTextBoxInput( - "wheelHeader", - "Is Wheel", - jointConfigTabInputs, - "Is Wheel", - background="#d9d9d9", - ), + createTextBoxInput("wheelHeader", "Is Wheel", jointConfigTabInputs, "Is Wheel", background="#d9d9d9"), 0, 6, ) @@ -125,57 +83,27 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: ) jointSelect.addSelectionFilter("Joints") jointSelect.setSelectionLimits(0) - - # Visibility is triggered by `addJointInputButton` - jointSelect.isEnabled = jointSelect.isVisible = False + jointSelect.isEnabled = jointSelect.isVisible = False # Visibility is triggered by `addJointInputButton` jointConfigTabInputs.addTextBoxCommandInput("jointTabBlankSpacer", "", "", 1, True) - self.wheelConfigTable = createTableInput( - "wheelTable", - "Wheel Table", - jointConfigTabInputs, - 4, - "1:2:2:2", - ) - + self.wheelConfigTable = createTableInput("wheelTable", "Wheel Table", jointConfigTabInputs, 4, "1:2:2:2") self.wheelConfigTable.addCommandInput( - createTextBoxInput( - "wheelMotionHeader", - "Motion", - jointConfigTabInputs, - "Motion", - bold=False, - ), - 0, - 0, + createTextBoxInput("wheelMotionHeader", "Motion", jointConfigTabInputs, "Motion", bold=False), 0, 0 ) - self.wheelConfigTable.addCommandInput( - createTextBoxInput("name_header", "Name", jointConfigTabInputs, "Joint name", bold=False), - 0, - 1, + createTextBoxInput("name_header", "Name", jointConfigTabInputs, "Joint name", bold=False), 0, 1 ) - self.wheelConfigTable.addCommandInput( createTextBoxInput( - "wheelTypeHeader", - "WheelType", - jointConfigTabInputs, - "Wheel type", - background="#d9d9d9", + "wheelTypeHeader", "WheelType", jointConfigTabInputs, "Wheel type", background="#d9d9d9" ), 0, 2, ) - self.wheelConfigTable.addCommandInput( createTextBoxInput( - "signalTypeHeader", - "SignalType", - jointConfigTabInputs, - "Signal type", - background="#d9d9d9", + "signalTypeHeader", "SignalType", jointConfigTabInputs, "Signal type", background="#d9d9d9" ), 0, 3, @@ -370,6 +298,7 @@ def addWheel(self, joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> None wheelIcon = commandInputs.addImageCommandInput( "wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"] ) + wheelIcon.tooltip = "Standard wheel" wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) wheelName.tooltip = joint.name # TODO: Should this be the same? wheelType = commandInputs.addDropDownCommandInput( @@ -464,9 +393,9 @@ def getSelectedJointsAndWheels(self) -> tuple[list[Joint], list[Wheel]]: jointEntityToken = self.selectedJointList[row - 1].entityToken signalTypeIndex = self.jointConfigTable.getInputAtPosition(row, 3).selectedItem.index signalType = SignalType(signalTypeIndex + 1) - jointSpeed = self.jointConfigTable.getInputAtPosition(row, 4).value - jointForce = self.jointConfigTable.getInputAtPosition(row, 5).value - isWheel = self.jointConfigTable.getInputAtPosition(row, 6).value + jointSpeed: float = self.jointConfigTable.getInputAtPosition(row, 4).value + jointForce: float = self.jointConfigTable.getInputAtPosition(row, 5).value + isWheel: bool = self.jointConfigTable.getInputAtPosition(row, 6).value joints.append( Joint( @@ -500,16 +429,16 @@ def reset(self) -> None: # Transition: AARD-1685 # Find a way to not pass the global commandInputs into this function # Perhaps get the joint tab from the args then get what we want? + # Idk the Fusion API seems to think that you would never need to change anything other than the effected + # commandInput in a input changed handle for some reason. def handleInputChanged( self, args: adsk.core.InputChangedEventArgs, globalCommandInputs: adsk.core.CommandInputs ) -> None: commandInput = args.input - - # TODO: Reorder if commandInput.id == "wheelType": wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) position = self.wheelConfigTable.getPosition(wheelTypeDropdown)[1] - iconInput = self.wheelConfigTable.getInputAtPosition(position, 0) + iconInput: adsk.core.ImageCommandInput = self.wheelConfigTable.getInputAtPosition(position, 0) if wheelTypeDropdown.selectedItem.index == 0: iconInput.imageFile = IconPaths.wheelIcons["standard"] @@ -540,15 +469,18 @@ def handleInputChanged( wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[jointTabPosition - 1].entityToken) if wheelTabPosition: - wheelSignalItems: adsk.core.DropDownCommandInput - wheelSignalItems = self.wheelConfigTable.getInputAtPosition(wheelTabPosition, 3) + wheelSignalItems: adsk.core.DropDownCommandInput = self.wheelConfigTable.getInputAtPosition( + wheelTabPosition, 3 + ) wheelSignalItems.listItems.item(signalTypeDropdown.selectedItem.index).isSelected = True elif commandInput.id == "jointAddButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") - jointSelection = globalCommandInputs.itemById("jointSelection") + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( + "jointSelectCancelButton" + ) + jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") jointSelection.isVisible = jointSelection.isEnabled = True jointSelection.clearSelection() @@ -556,8 +488,8 @@ def handleInputChanged( jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True elif commandInput.id == "jointRemoveButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointTable = args.inputs.itemById("jointTable") + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointTable: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") jointAddButton.isEnabled = True @@ -565,14 +497,15 @@ def handleInputChanged( ui = adsk.core.Application.get().userInterface ui.messageBox("Select a row to delete.") else: - # Select Row is 1 indexed - self.removeIndexedJoint(jointTable.selectedRow - 1) + self.removeIndexedJoint(jointTable.selectedRow - 1) # selectedRow is 1 indexed elif commandInput.id == "jointSelectCancelButton": - jointAddButton = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = globalCommandInputs.itemById("jointSelectCancelButton") - jointSelection = globalCommandInputs.itemById("jointSelection") + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( + "jointSelectCancelButton" + ) + jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") jointSelection.isEnabled = jointSelection.isVisible = False jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False jointAddButton.isEnabled = jointRemoveButton.isEnabled = True @@ -596,10 +529,11 @@ def handleSelectionEvent(self, args: adsk.core.SelectionEventArgs, selectedJoint selectionInput.isEnabled = selectionInput.isVisible = False def handlePreviewEvent(self, args: adsk.core.CommandEventArgs) -> None: - jointAddButton = args.command.commandInputs.itemById("jointAddButton") - jointRemoveButton = args.command.commandInputs.itemById("jointRemoveButton") - jointSelectCancelButton = args.command.commandInputs.itemById("jointSelectCancelButton") - jointSelection = args.command.commandInputs.itemById("jointSelection") + commandInputs = args.command.commandInputs + jointAddButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointSelectCancelButton") + jointSelection: adsk.core.SelectionCommandInput = commandInputs.itemById("jointSelection") if self.jointConfigTable.rowCount <= 1: jointRemoveButton.isEnabled = False From 19abf609093e54823fec6a931a05a0f00772c484 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 15:41:30 -0700 Subject: [PATCH 16/21] Last bit of formatting --- exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index f734c3171c..f59e96eab7 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -33,19 +33,15 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: self.jointConfigTab = inputs.addTabCommandInput("jointSettings", "Joint Settings") self.jointConfigTab.tooltip = "Select and configure robot joints." jointConfigTabInputs = self.jointConfigTab.children - self.jointConfigTable = createTableInput( "jointTable", "Joint Table", jointConfigTabInputs, 7, "1:2:2:2:2:2:2" ) - self.jointConfigTable.addCommandInput( createTextBoxInput("jointMotionHeader", "Motion", jointConfigTabInputs, "Motion", bold=False), 0, 0 ) - self.jointConfigTable.addCommandInput( createTextBoxInput("nameHeader", "Name", jointConfigTabInputs, "Joint name", bold=False), 0, 1 ) - self.jointConfigTable.addCommandInput( createTextBoxInput( "parentHeader", "Parent", jointConfigTabInputs, "Parent joint", background="#d9d9d9" @@ -53,25 +49,21 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: 0, 2, ) - self.jointConfigTable.addCommandInput( createTextBoxInput("signalHeader", "Signal", jointConfigTabInputs, "Signal type", background="#d9d9d9"), 0, 3, ) - self.jointConfigTable.addCommandInput( createTextBoxInput("speedHeader", "Speed", jointConfigTabInputs, "Joint Speed", background="#d9d9d9"), 0, 4, ) - self.jointConfigTable.addCommandInput( createTextBoxInput("forceHeader", "Force", jointConfigTabInputs, "Joint Force", background="#d9d9d9"), 0, 5, ) - self.jointConfigTable.addCommandInput( createTextBoxInput("wheelHeader", "Is Wheel", jointConfigTabInputs, "Is Wheel", background="#d9d9d9"), 0, From 004f857b93f97d8ad32f5266d823e682ccfab855 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 15:50:00 -0700 Subject: [PATCH 17/21] Cleanup catches and try except logging --- .../src/UI/ConfigCommand.py | 42 +- .../src/UI/JointConfigTab.py | 374 +++++++++--------- 2 files changed, 192 insertions(+), 224 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 0ecdc91faa..b2632902a1 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -291,7 +291,6 @@ def notify(self, args): # Transition: AARD-1685 # Should consider changing how the parser handles wheels and joints to avoid overlap if exporterOptions.wheels: - pass for wheel in exporterOptions.wheels: fusionJoint = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0] jointConfigTab.addWheel(fusionJoint, wheel) @@ -841,38 +840,10 @@ def notify(self, args): name = design.rootComponent.name.rsplit(" ", 1)[0] version = design.rootComponent.name.rsplit(" ", 1)[1] - _exportWheels = [] # all selected wheels, formatted for parseOptions _exportGamepieces = [] # TODO work on the code to populate Gamepiece _robotWeight = float _mode = ExportMode.ROBOT - # Transition: AARD-1865 - """ - Loops through all rows in the wheel table to extract all the input values - """ - # onSelect = gm.handlers[3] - # wheelTableInput = wheelTable() - # for row in range(wheelTableInput.rowCount): - # if row == 0: - # continue - - # wheelTypeIndex = wheelTableInput.getInputAtPosition( - # row, 2 - # ).selectedItem.index # This must be either 0 or 1 for standard or omni - - # signalTypeIndex = wheelTableInput.getInputAtPosition( - # row, 3 - # ).selectedItem.index - - # _exportWheels.append( - # Wheel( - # WheelListGlobal[row - 1].entityToken, - # WheelType(wheelTypeIndex + 1), - # SignalType(signalTypeIndex + 1), - # # onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint found, default to None - # ) - # ) - """ Loops through all rows in the gamepiece table to extract the input values """ @@ -1285,7 +1256,6 @@ def __init__(self, cmd): self.allWeights = [None, None] # [lbs, kg] self.isLbs = True self.isLbs_f = True - self.called = False def reset(self): """### Process: @@ -1372,23 +1342,13 @@ def notify(self, args): gamepieceConfig.isVisible = False weightTableInput.isVisible = True - # addFieldInput.isEnabled = wheelConfig.isVisible = ( - # jointConfig.isVisible - # ) = True + addFieldInput.isEnabled = True elif modeDropdown.selectedItem.index == 1: if gamepieceConfig: gm.ui.activeSelections.clear() gm.app.activeDocument.design.rootComponent.opacity = 1 - # addWheelInput.isEnabled = addJointButton.isEnabled = ( - # gamepieceConfig.isVisible - # ) = True - - # jointConfig.isVisible = wheelConfig.isVisible = ( - # weightTableInput.isVisible - # ) = False - elif cmdInput.id == "blank_gp" or cmdInput.id == "name_gp" or cmdInput.id == "weight_gp": self.reset() diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index f59e96eab7..e6f79b0f77 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -113,10 +113,8 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs) -> None: self.jointConfigTable.addToolbarCommandInput(jointSelectCancelButton) self.reset() - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.createJointConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def addJoint(self, fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None) -> bool: try: @@ -276,65 +274,64 @@ def addJoint(self, fusionJoint: adsk.fusion.Joint, synJoint: Joint | None = None ) self.previousWheelCheckboxState.append(isWheel) - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.addJointToConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) return True def addWheel(self, joint: adsk.fusion.Joint, wheel: Wheel | None = None) -> None: - self.jointWheelIndexMap[joint.entityToken] = self.wheelConfigTable.rowCount - - commandInputs = self.wheelConfigTable.commandInputs - wheelIcon = commandInputs.addImageCommandInput( - "wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"] - ) - wheelIcon.tooltip = "Standard wheel" - wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) - wheelName.tooltip = joint.name # TODO: Should this be the same? - wheelType = commandInputs.addDropDownCommandInput( - "wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle - ) - - selectedWheelType = wheel.wheelType if wheel else WheelType.STANDARD - wheelType.listItems.add("Standard", selectedWheelType is WheelType.STANDARD, "") - wheelType.listItems.add("OMNI", selectedWheelType is WheelType.OMNI, "") - wheelType.listItems.add("Mecanum", selectedWheelType is WheelType.MECANUM, "") - wheelType.tooltip = "Wheel type" - wheelType.tooltipDescription = "".join( - [ - "
Omni-directional wheels can be used just like regular drive wheels", - "but they have the advantage of being able to roll freely perpendicular to", - "the drive direction.
", - ] - ) - - signalType = commandInputs.addDropDownCommandInput( - "wheelSignalType", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle - ) - signalType.isFullWidth = True - signalType.isEnabled = False - signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." - i = self.selectedJointList.index(joint) - jointSignalType = SignalType(self.jointConfigTable.getInputAtPosition(i + 1, 3).selectedItem.index + 1) - signalType.listItems.add("‎", jointSignalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) - signalType.listItems.add("‎", jointSignalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) - signalType.listItems.add("‎", jointSignalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) - - row = self.wheelConfigTable.rowCount - self.wheelConfigTable.addCommandInput(wheelIcon, row, 0) - self.wheelConfigTable.addCommandInput(wheelName, row, 1) - self.wheelConfigTable.addCommandInput(wheelType, row, 2) - self.wheelConfigTable.addCommandInput(signalType, row, 3) + try: + self.jointWheelIndexMap[joint.entityToken] = self.wheelConfigTable.rowCount + + commandInputs = self.wheelConfigTable.commandInputs + wheelIcon = commandInputs.addImageCommandInput( + "wheelPlaceholder", "Placeholder", IconPaths.wheelIcons["standard"] + ) + wheelIcon.tooltip = "Standard wheel" + wheelName = commandInputs.addTextBoxCommandInput("wheelName", "Joint Name", joint.name, 1, True) + wheelName.tooltip = joint.name # TODO: Should this be the same? + wheelType = commandInputs.addDropDownCommandInput( + "wheelType", "Wheel Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle + ) + + selectedWheelType = wheel.wheelType if wheel else WheelType.STANDARD + wheelType.listItems.add("Standard", selectedWheelType is WheelType.STANDARD, "") + wheelType.listItems.add("OMNI", selectedWheelType is WheelType.OMNI, "") + wheelType.listItems.add("Mecanum", selectedWheelType is WheelType.MECANUM, "") + wheelType.tooltip = "Wheel type" + wheelType.tooltipDescription = "".join( + [ + "
Omni-directional wheels can be used just like regular drive wheels", + "but they have the advantage of being able to roll freely perpendicular to", + "the drive direction.
", + ] + ) + + signalType = commandInputs.addDropDownCommandInput( + "wheelSignalType", "Signal Type", dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle + ) + signalType.isFullWidth = True + signalType.isEnabled = False + signalType.tooltip = "Wheel signal type is linked with the respective joint signal type." + i = self.selectedJointList.index(joint) + jointSignalType = SignalType(self.jointConfigTable.getInputAtPosition(i + 1, 3).selectedItem.index + 1) + signalType.listItems.add("‎", jointSignalType is SignalType.PWM, IconPaths.signalIcons["PWM"]) + signalType.listItems.add("‎", jointSignalType is SignalType.CAN, IconPaths.signalIcons["CAN"]) + signalType.listItems.add("‎", jointSignalType is SignalType.PASSIVE, IconPaths.signalIcons["PASSIVE"]) + + row = self.wheelConfigTable.rowCount + self.wheelConfigTable.addCommandInput(wheelIcon, row, 0) + self.wheelConfigTable.addCommandInput(wheelName, row, 1) + self.wheelConfigTable.addCommandInput(wheelType, row, 2) + self.wheelConfigTable.addCommandInput(signalType, row, 3) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def removeIndexedJoint(self, index: int) -> None: try: self.removeJoint(self.selectedJointList[index]) - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeIndexedJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def removeJoint(self, joint: adsk.fusion.Joint) -> None: try: @@ -360,10 +357,8 @@ def removeJoint(self, joint: adsk.fusion.Joint) -> None: listItems.item(i).deleteMe() else: listItems.item(i).deleteMe() - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def removeWheel(self, joint: adsk.fusion.Joint) -> None: try: @@ -373,45 +368,46 @@ def removeWheel(self, joint: adsk.fusion.Joint) -> None: for key, value in self.jointWheelIndexMap.items(): if value > row - 1: self.jointWheelIndexMap[key] -= 1 - except: - logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab.removeJointFromConfigTab()").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def getSelectedJointsAndWheels(self) -> tuple[list[Joint], list[Wheel]]: - joints: list[Joint] = [] - wheels: list[Wheel] = [] - for row in range(1, self.jointConfigTable.rowCount): # Row is 1 indexed - jointEntityToken = self.selectedJointList[row - 1].entityToken - signalTypeIndex = self.jointConfigTable.getInputAtPosition(row, 3).selectedItem.index - signalType = SignalType(signalTypeIndex + 1) - jointSpeed: float = self.jointConfigTable.getInputAtPosition(row, 4).value - jointForce: float = self.jointConfigTable.getInputAtPosition(row, 5).value - isWheel: bool = self.jointConfigTable.getInputAtPosition(row, 6).value - - joints.append( - Joint( - jointEntityToken, - JointParentType.ROOT, - signalType, - jointSpeed, - jointForce / 100.0, - isWheel, - ) - ) - - if isWheel: - wheelRow = self.jointWheelIndexMap[jointEntityToken] - wheelTypeIndex = self.wheelConfigTable.getInputAtPosition(wheelRow, 2).selectedItem.index - wheels.append( - Wheel( + try: + joints: list[Joint] = [] + wheels: list[Wheel] = [] + for row in range(1, self.jointConfigTable.rowCount): # Row is 1 indexed + jointEntityToken = self.selectedJointList[row - 1].entityToken + signalTypeIndex = self.jointConfigTable.getInputAtPosition(row, 3).selectedItem.index + signalType = SignalType(signalTypeIndex + 1) + jointSpeed: float = self.jointConfigTable.getInputAtPosition(row, 4).value + jointForce: float = self.jointConfigTable.getInputAtPosition(row, 5).value + isWheel: bool = self.jointConfigTable.getInputAtPosition(row, 6).value + + joints.append( + Joint( jointEntityToken, - WheelType(wheelTypeIndex + 1), + JointParentType.ROOT, signalType, + jointSpeed, + jointForce / 100.0, + isWheel, ) ) - return (joints, wheels) + if isWheel: + wheelRow = self.jointWheelIndexMap[jointEntityToken] + wheelTypeIndex = self.wheelConfigTable.getInputAtPosition(wheelRow, 2).selectedItem.index + wheels.append( + Wheel( + jointEntityToken, + WheelType(wheelTypeIndex + 1), + signalType, + ) + ) + + return (joints, wheels) + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def reset(self) -> None: self.selectedJointList.clear() @@ -426,110 +422,122 @@ def reset(self) -> None: def handleInputChanged( self, args: adsk.core.InputChangedEventArgs, globalCommandInputs: adsk.core.CommandInputs ) -> None: - commandInput = args.input - if commandInput.id == "wheelType": - wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) - position = self.wheelConfigTable.getPosition(wheelTypeDropdown)[1] - iconInput: adsk.core.ImageCommandInput = self.wheelConfigTable.getInputAtPosition(position, 0) - - if wheelTypeDropdown.selectedItem.index == 0: - iconInput.imageFile = IconPaths.wheelIcons["standard"] - iconInput.tooltip = "Standard wheel" - elif wheelTypeDropdown.selectedItem.index == 1: - iconInput.imageFile = IconPaths.wheelIcons["omni"] - iconInput.tooltip = "Omni wheel" - elif wheelTypeDropdown.selectedItem.index == 2: - iconInput.imageFile = IconPaths.wheelIcons["mecanum"] - iconInput.tooltip = "Mecanum wheel" - - elif commandInput.id == "isWheel": - isWheelCheckbox = adsk.core.BoolValueCommandInput.cast(commandInput) - position = self.jointConfigTable.getPosition(isWheelCheckbox)[1] - 1 - isAlreadyWheel = bool(self.jointWheelIndexMap.get(self.selectedJointList[position].entityToken)) - - if isWheelCheckbox.value != self.previousWheelCheckboxState[position]: - if not isAlreadyWheel: - self.addWheel(self.selectedJointList[position]) - else: - self.removeWheel(self.selectedJointList[position]) + try: + commandInput = args.input + if commandInput.id == "wheelType": + wheelTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + position = self.wheelConfigTable.getPosition(wheelTypeDropdown)[1] + iconInput: adsk.core.ImageCommandInput = self.wheelConfigTable.getInputAtPosition(position, 0) + + if wheelTypeDropdown.selectedItem.index == 0: + iconInput.imageFile = IconPaths.wheelIcons["standard"] + iconInput.tooltip = "Standard wheel" + elif wheelTypeDropdown.selectedItem.index == 1: + iconInput.imageFile = IconPaths.wheelIcons["omni"] + iconInput.tooltip = "Omni wheel" + elif wheelTypeDropdown.selectedItem.index == 2: + iconInput.imageFile = IconPaths.wheelIcons["mecanum"] + iconInput.tooltip = "Mecanum wheel" + + elif commandInput.id == "isWheel": + isWheelCheckbox = adsk.core.BoolValueCommandInput.cast(commandInput) + position = self.jointConfigTable.getPosition(isWheelCheckbox)[1] - 1 + isAlreadyWheel = bool(self.jointWheelIndexMap.get(self.selectedJointList[position].entityToken)) + + if isWheelCheckbox.value != self.previousWheelCheckboxState[position]: + if not isAlreadyWheel: + self.addWheel(self.selectedJointList[position]) + else: + self.removeWheel(self.selectedJointList[position]) - self.previousWheelCheckboxState[position] = isWheelCheckbox.value + self.previousWheelCheckboxState[position] = isWheelCheckbox.value - elif commandInput.id == "signalTypeJoint": - signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) - jointTabPosition = self.jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed - wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[jointTabPosition - 1].entityToken) + elif commandInput.id == "signalTypeJoint": + signalTypeDropdown = adsk.core.DropDownCommandInput.cast(commandInput) + jointTabPosition = self.jointConfigTable.getPosition(signalTypeDropdown)[1] # 1 indexed + wheelTabPosition = self.jointWheelIndexMap.get(self.selectedJointList[jointTabPosition - 1].entityToken) - if wheelTabPosition: - wheelSignalItems: adsk.core.DropDownCommandInput = self.wheelConfigTable.getInputAtPosition( - wheelTabPosition, 3 - ) - wheelSignalItems.listItems.item(signalTypeDropdown.selectedItem.index).isSelected = True + if wheelTabPosition: + wheelSignalItems: adsk.core.DropDownCommandInput = self.wheelConfigTable.getInputAtPosition( + wheelTabPosition, 3 + ) + wheelSignalItems.listItems.item(signalTypeDropdown.selectedItem.index).isSelected = True - elif commandInput.id == "jointAddButton": - jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( - "jointSelectCancelButton" - ) - jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") + elif commandInput.id == "jointAddButton": + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( + "jointSelectCancelButton" + ) + jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") - jointSelection.isVisible = jointSelection.isEnabled = True - jointSelection.clearSelection() - jointAddButton.isEnabled = jointRemoveButton.isEnabled = False - jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True + jointSelection.isVisible = jointSelection.isEnabled = True + jointSelection.clearSelection() + jointAddButton.isEnabled = jointRemoveButton.isEnabled = False + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = True - elif commandInput.id == "jointRemoveButton": - jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") - jointTable: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") + elif commandInput.id == "jointRemoveButton": + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointTable: adsk.core.TableCommandInput = args.inputs.itemById("jointTable") - jointAddButton.isEnabled = True + jointAddButton.isEnabled = True - if jointTable.selectedRow == -1 or jointTable.selectedRow == 0: - ui = adsk.core.Application.get().userInterface - ui.messageBox("Select a row to delete.") - else: - self.removeIndexedJoint(jointTable.selectedRow - 1) # selectedRow is 1 indexed + if jointTable.selectedRow == -1 or jointTable.selectedRow == 0: + ui = adsk.core.Application.get().userInterface + ui.messageBox("Select a row to delete.") + else: + self.removeIndexedJoint(jointTable.selectedRow - 1) # selectedRow is 1 indexed - elif commandInput.id == "jointSelectCancelButton": - jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") - jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") - jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( - "jointSelectCancelButton" - ) - jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") - jointSelection.isEnabled = jointSelection.isVisible = False - jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False - jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + elif commandInput.id == "jointSelectCancelButton": + jointAddButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = globalCommandInputs.itemById( + "jointSelectCancelButton" + ) + jointSelection: adsk.core.SelectionCommandInput = globalCommandInputs.itemById("jointSelection") + jointSelection.isEnabled = jointSelection.isVisible = False + jointSelectCancelButton.isEnabled = jointSelectCancelButton.isVisible = False + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def handleSelectionEvent(self, args: adsk.core.SelectionEventArgs, selectedJoint: adsk.fusion.Joint) -> None: - selectionInput = args.activeInput - jointType = selectedJoint.jointMotion.jointType - if jointType == adsk.fusion.JointTypes.RevoluteJointType or jointType == adsk.fusion.JointTypes.SliderJointType: - if not self.addJoint(selectedJoint): - ui = adsk.core.Application.get().userInterface - result = ui.messageBox( - "You have already selected this joint.\n" "Would you like to remove it?", - "Synthesis: Remove Joint Confirmation", - adsk.core.MessageBoxButtonTypes.YesNoButtonType, - adsk.core.MessageBoxIconTypes.QuestionIconType, - ) + try: + selectionInput = args.activeInput + jointType = selectedJoint.jointMotion.jointType + if ( + jointType == adsk.fusion.JointTypes.RevoluteJointType + or jointType == adsk.fusion.JointTypes.SliderJointType + ): + if not self.addJoint(selectedJoint): + ui = adsk.core.Application.get().userInterface + result = ui.messageBox( + "You have already selected this joint.\n" "Would you like to remove it?", + "Synthesis: Remove Joint Confirmation", + adsk.core.MessageBoxButtonTypes.YesNoButtonType, + adsk.core.MessageBoxIconTypes.QuestionIconType, + ) - if result == adsk.core.DialogResults.DialogYes: - self.removeJoint(selectedJoint) + if result == adsk.core.DialogResults.DialogYes: + self.removeJoint(selectedJoint) - selectionInput.isEnabled = selectionInput.isVisible = False + selectionInput.isEnabled = selectionInput.isVisible = False + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) def handlePreviewEvent(self, args: adsk.core.CommandEventArgs) -> None: - commandInputs = args.command.commandInputs - jointAddButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointAddButton") - jointRemoveButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointRemoveButton") - jointSelectCancelButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointSelectCancelButton") - jointSelection: adsk.core.SelectionCommandInput = commandInputs.itemById("jointSelection") - - if self.jointConfigTable.rowCount <= 1: - jointRemoveButton.isEnabled = False - - if not jointSelection.isEnabled: - jointAddButton.isEnabled = jointRemoveButton.isEnabled = True - jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = False + try: + commandInputs = args.command.commandInputs + jointAddButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointAddButton") + jointRemoveButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointRemoveButton") + jointSelectCancelButton: adsk.core.BoolValueCommandInput = commandInputs.itemById("jointSelectCancelButton") + jointSelection: adsk.core.SelectionCommandInput = commandInputs.itemById("jointSelection") + + if self.jointConfigTable.rowCount <= 1: + jointRemoveButton.isEnabled = False + + if not jointSelection.isEnabled: + jointAddButton.isEnabled = jointRemoveButton.isEnabled = True + jointSelectCancelButton.isVisible = jointSelectCancelButton.isEnabled = False + except BaseException: + logging.getLogger("{INTERNAL_ID}.UI.JointConfigTab").error("Failed:\n{}".format(traceback.format_exc())) From 9a099f2bdd7a31bb217d479575ee0347d3978967 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Mon, 1 Jul 2024 15:53:31 -0700 Subject: [PATCH 18/21] Helper module logging updates --- .../src/UI/CreateCommandInputsHelper.py | 8 +++++--- exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py index 243bd1c386..ac3996b537 100644 --- a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py +++ b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py @@ -3,6 +3,8 @@ import adsk.core +from ..general_imports import INTERNAL_ID + def createTableInput( id: str, @@ -24,7 +26,7 @@ def createTableInput( return input except BaseException: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createTableInput()").error( + logging.getLogger("{INTERNAL_ID}.UI.CreateCommandInputsHelper").error( "Failed:\n{}".format(traceback.format_exc()) ) @@ -48,7 +50,7 @@ def createBooleanInput( return input except BaseException: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createBooleanInput()").error( + logging.getLogger("{INTERNAL_ID}.UI.CreateCommandInputsHelper").error( "Failed:\n{}".format(traceback.format_exc()) ) @@ -89,6 +91,6 @@ def createTextBoxInput( return input except BaseException: - logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.createTextBoxInput()").error( + logging.getLogger("{INTERNAL_ID}.UI.CreateCommandInputsHelper").error( "Failed:\n{}".format(traceback.format_exc()) ) diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py index e6f79b0f77..5f9be302b3 100644 --- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py +++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py @@ -4,6 +4,7 @@ import adsk.core import adsk.fusion +from ..general_imports import INTERNAL_ID from ..Parser.ExporterOptions import ( Joint, JointParentType, From b30c1f591ebe117886eafcac0da958c82fc36c2e Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 12 Jul 2024 16:05:24 -0700 Subject: [PATCH 19/21] Fixed a bug for Hunter's computer only :( --- .../src/Parser/ExporterOptions.py | 5 ++++- .../SynthesisFusionAddin/src/UI/ConfigCommand.py | 15 +-------------- .../src/UI/FileDialogConfig.py | 12 ++++-------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py index 569d29e158..4c0ac5698c 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py @@ -83,7 +83,10 @@ class ModelHierarchy(Enum): @dataclass class ExporterOptions: - fileLocation: str = field( + # Python's `os` module can return `None` when attempting to find the home directory if the + # user's computer has conflicting configs of some sort. This has happened and should be accounted + # for accordingly. + fileLocation: str | None = field( default=(os.getenv("HOME") if platform.system() == "Windows" else os.path.expanduser("~")) ) name: str = field(default=None) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index b2632902a1..d5a0e1980b 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -811,20 +811,7 @@ def notify(self, args): .children.itemById("export_as_part") ).value - processedFileName = gm.app.activeDocument.name.replace(" ", "_") - dropdownExportMode = INPUTS_ROOT.itemById("mode") - if dropdownExportMode.selectedItem.index == 0: - isRobot = True - elif dropdownExportMode.selectedItem.index == 1: - isRobot = False - - if isRobot: - savepath = FileDialogConfig.SaveFileDialog( - defaultPath=exporterOptions.fileLocation, - ext="Synthesis File (*.synth)", - ) - else: - savepath = FileDialogConfig.SaveFileDialog(defaultPath=exporterOptions.fileLocation) + savepath = FileDialogConfig.saveFileDialog(defaultPath=exporterOptions.fileLocation) if not savepath: # save was canceled diff --git a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py index e49cf240b7..7af7a1e73a 100644 --- a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py +++ b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py @@ -9,7 +9,7 @@ from ..Types.OString import OString -def SaveFileDialog(defaultPath="", defaultName="", ext="MiraBuf Package (*.mira)") -> Union[str, bool]: +def saveFileDialog(defaultPath: str | None = None, defaultName: str | None = None) -> str | bool: """Function to generate the Save File Dialog for the Hellion Data files Args: @@ -21,22 +21,18 @@ def SaveFileDialog(defaultPath="", defaultName="", ext="MiraBuf Package (*.mira) str: full file path """ - ext = "MiraBuf Package (*.mira)" - fileDialog: adsk.core.FileDialog = gm.ui.createFileDialog() fileDialog.isMultiSelectEnabled = False fileDialog.title = "Save Export Result" - fileDialog.filter = f"{ext}" + fileDialog.filter = "MiraBuf Package (*.mira)" - if defaultPath == "": + if not defaultPath: defaultPath = generateFilePath() fileDialog.initialDirectory = defaultPath - # print(defaultPath) - - if defaultName == "": + if not defaultName: defaultName = generateFileName() fileDialog.initialFilename = defaultName From 9a35c0a39cb7d897091abf83c3480ed994a9dc6a Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Thu, 18 Jul 2024 08:16:55 -0700 Subject: [PATCH 20/21] Fix: Reset select cursor back to normal after joint selection --- exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py | 1 + 1 file changed, 1 insertion(+) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index d5a0e1980b..3fecde2755 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -1128,6 +1128,7 @@ def notify(self, args: adsk.core.SelectionEventArgs): # This is how all handle selection events should be done in the future although it will look # slightly differently for each type of handle. elif self.selectedJoint: + self.cmd.setCursor("", 0, 0) # Reset select cursor back to normal cursor. jointConfigTab.handleSelectionEvent(args, self.selectedJoint) except: if gm.ui: From 5285fad0bee3e8d99bbc5999874048d300c511b3 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 19 Jul 2024 12:11:14 -0700 Subject: [PATCH 21/21] Resolve merge conflict from `dev` --- exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index ecf23608aa..51564dada9 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -815,12 +815,6 @@ def notify(self, args): self.log.error("Could not execute configuration due to failure") return - export_as_part_boolean = ( - eventArgs.command.commandInputs.itemById("advanced_settings") - .children.itemById("exporter_settings") - .children.itemById("export_as_part") - ).value - processedFileName = gm.app.activeDocument.name.replace(" ", "_") dropdownExportMode = INPUTS_ROOT.itemById("mode") if dropdownExportMode.selectedItem.index == 0: