Message 1 of 3
Fusion ToolbarPanel potential persistence Bug
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I made a post a while ago about an odd feature of toolbar panels I had noticed (link). The thread got pretty full and I found that it may be a bug in fusion, so I am creating this post and will be closing the other. The problem comes from creating and removing toolbarPanels. If I add a panel to one toolbarTab, then remove it, then add one with the same id to a separate toolbar tab, the panel will show up in both locations. I have not found a way for me to remove it completely without a full fusion restart. My script below will take you, step by step, through the problem and should demonstrate it clearly. If anyone has any idea if this is an error on my end please let me know.
import adsk.core, adsk.fusion, adsk.cam, traceback
#List for every object
createdObjects= []
#Context manager
class errorPrint:
def __init__(self,errorReport): self.errorrep = errorReport
def __enter__(self,*args): return self
def __exit__(self,excType,excVal,excTB):
if excType is not None:
self.errorrep.append(excType.__name__ + ": \t"+ str(excVal))
return True
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#Generic function that both gets ant creates new objects depending on if they already exist and whether the command calling it wants to create it
#If an object is ever made, it gets appended to the global list of objects for proper deletion at the end of the commands life
def addGeneric(baseObj, cmdID, cmdFunc, *addArgs, TryAdd=True):
global createdObjects
generic = baseObj.itemById(cmdID)
if generic == None and TryAdd:
generic = cmdFunc(*addArgs)
createdObjects.append(generic)
return generic
#These funcs are focused on toolbar panels and the command buttons in them
#These will either create the obj if it does not exist, or it will return the object if already defined
def AddPanel(panels:adsk.core.ToolbarPanels, id='SolidScriptsAddinsPanel', name = 'Add-Ins', positionID='', isBefore=False):
return addGeneric(panels, id, panels.add, id, name,positionID,isBefore)
def NewCommand(cmdDefs:adsk.core.CommandDefinitions, cmdID, cmdName, cmdToolTip='', cmdIcon=''):
return addGeneric(cmdDefs,cmdID, cmdDefs.addButtonDefinition, cmdID,cmdName, cmdToolTip, cmdIcon)
def AddCommand(toolbarControls:adsk.core.ToolbarControls, commandDef:adsk.core.CommandDefinition, positionID='', isBefore=False):
return addGeneric(toolbarControls, commandDef.id, toolbarControls.addCommand, commandDef, positionID, isBefore)
#These are just util funcs that get me the controls i want
def GetWorkspace(workspaces:adsk.core.Workspaces, id='FusionSolidEnvironment', name='Design', icon=''):
return addGeneric(workspaces, id, workspaces.add, id, name,icon, TryAdd=False)
def GetTab(toolbarTabs:adsk.core.ToolbarTabs,id='ToolsTab', name = 'Tools'):
return addGeneric(toolbarTabs, id, toolbarTabs.add, id, name, TryAdd=False)
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def run(context):
ui = None
try:
#Setting up some objs
app:adsk.core.Application= adsk.core.Application.get()
ui = app.userInterface
ui.messageBox('Hello addin')
FusionSolid = GetWorkspace(ui.workspaces)
SolidTab = GetTab(FusionSolid.toolbarTabs, 'SolidTab')
ToolsTab = GetTab(FusionSolid.toolbarTabs, 'ToolsTab')
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Creating the toolbar panel within the solids tab
ExampleCommand:adsk.core.CommandDefinition = NewCommand(ui.commandDefinitions, '__A_Completly_Unique_ID__', 'PanelBugCommand', '', '/resources')
PanelInSolidTab:adsk.core.ToolbarPanel = AddPanel(SolidTab.toolbarPanels, 'SolidPanelTest', 'Im a solid panel')
SolidPanelCommand = AddCommand(PanelInSolidTab.controls, ExampleCommand)
SolidTab.activate()
ui.messageBox('The Toolbar panel should be visible')
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Asserting that fusion says the obects have been deleted
assert ui.commandDefinitions.itemById('__A_Completly_Unique_ID__').deleteMe()
assert ui.allToolbarPanels.itemById('SolidPanelTest').deleteMe()
DelConfirm = [] #Needed a mutable to recieve info back easily
#Trying to get fusion to complain about the objs being deleted
with errorPrint(DelConfirm): SolidPanelCommand.id
with errorPrint(DelConfirm): PanelInSolidTab.id
DelConfirm.append('Deleting the variables then accessing errors:')
#This i dont think matters since the objects are stored globally anyhow but whatever
del PanelInSolidTab
del SolidPanelCommand
with errorPrint(DelConfirm): SolidPanelCommand.id
with errorPrint(DelConfirm): PanelInSolidTab.id
ui.messageBox('The Toolbar panel and command should be be gone \n\n Errors when trying to access those variables as proof:\n'+ str('\n'.join(DelConfirm)))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ExampleCommand:adsk.core.CommandDefinition = NewCommand(ui.commandDefinitions, '__A_Completly_Unique_ID__', 'PanelBugCommand', '', '/resources')
PanelInToolsTab:adsk.core.ToolbarPanel = AddPanel(ToolsTab.toolbarPanels, 'SolidPanelTest', 'Im a solid panel')
ToolsPanelCommand = AddCommand(PanelInToolsTab.controls, ExampleCommand)
ToolsTab.activate()
ui.messageBox('The Tools tab ToolbarPanel should be visible')
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SolidTab.activate()
ui.messageBox('The Toolbar panel should not be in the Solids Tab')
assert ui.commandDefinitions.itemById('__A_Completly_Unique_ID__').deleteMe()
assert ui.allToolbarPanels.itemById('SolidPanelTest').deleteMe()
ui.messageBox('Panel and command removed')
except:TraceError(ui)
def stop(context):
app:adsk.core.Application= adsk.core.Application.get()
ui = app.userInterface
try: clearCreated(ui)
except:TraceError(ui)
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def TraceError(ui): ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def clearCreated(ui):
global createdObjects
try:
# ui.messageBox(str(len(createdObjects)))
for obj in createdObjects:
try:
obj.deleteMe()
ui.messageBox('Item')
except:pass
# one double check to make sure, more than likley fails
assert ui.allToolbarPanels.itemById('SolidPanelTest').deleteMe()
assert ui.commandDefinitions.itemById('__A_Completly_Unique_ID__').deleteMe()
except: pass
#Wipes all references to them.
createdObjects.clear()