Message 1 of 7
Bug? - Attributes disappearing
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
It appears that any attribute added to an entity during an open dialog box disappears before onExecute is processed after the OK button is pressed. If I'm doing something wrong, please enlighten me - otherwise this has to be a bug! I initially thought this was related to components, but it happens with rootComponents as well.
- Create a root box, and if you want, a component box.
- Run the addon - found at the bottom of CREATE menu.
- click on the box and then OK
this will create a attribTest.log file
-Before the OK button is pressed, the log show that attributes were created.
-After the OK button press the attributes have been cleared.
-Next time addon is activated - the log shows that the attributes were persistent, but the ones created before the last OK, do not reappeared.
Attached is also a log file.
from collections import defaultdict
from pprint import pformat
import logging
import os
import adsk.core, adsk.fusion
import traceback
from . import utils
appPath = os.path.dirname(os.path.abspath(__file__))
logger = logging.getLogger('aaaa')
#clean up log handlers - seems to be an issue with f360 not playing nice with python logging
for handler in logger.handlers:
handler.flush()
handler.close()
formatter = logging.Formatter('%(lineno)d; %(funcName)s ; %(message)s')
logHandler = logging.FileHandler(os.path.join(appPath, 'attribTest.log'), mode='a')
logHandler.setFormatter(formatter)
logHandler.flush()
logger.addHandler(logHandler)
logger.setLevel(logging.DEBUG)
class AttribTestCommand(object):
COMMAND_ID = "attribTestBtn"
def __init__(self):
self.app = adsk.core.Application.get()
self.ui = self.app.userInterface
self.handlers = HandlerHelper()
self.body = None
def addButton(self):
# clean up any crashed instances of the button if existing
try:
self.removeButton()
except:
pass
# add add-in to UI
buttonAttribTest = self.ui.commandDefinitions.addButtonDefinition(
self.COMMAND_ID, 'attribTest', 'adds attributes while dialog is open and after it is executed')
buttonAttribTest.commandCreated.add(self.handlers.make_handler(adsk.core.CommandCreatedEventHandler,
self.onCreate))
createPanel = self.ui.allToolbarPanels.itemById('SolidCreatePanel')
buttonControl = createPanel.controls.addCommand(buttonAttribTest, 'attribTestBtn')
# Make the button available in the panel.
buttonControl.isPromotedByDefault = True
buttonControl.isPromoted = True
def removeButton(self):
cmdDef = self.ui.commandDefinitions.itemById(self.COMMAND_ID)
if cmdDef:
cmdDef.deleteMe()
createPanel = self.ui.allToolbarPanels.itemById('SolidCreatePanel')
cntrl = createPanel.controls.itemById(self.COMMAND_ID)
if cntrl:
cntrl.deleteMe()
def onCreate(self, args):
inputs = args.command.commandInputs
selection = inputs.addSelectionInput(
'selBody', 'Body',
'Select a body')
selection.addSelectionFilter('Bodies')
selection.setSelectionLimits(1,0)
cmd = adsk.core.Command.cast(args.command)
# Add handlers to this command.
cmd.execute.add(self.handlers.make_handler(adsk.core.CommandEventHandler, self.onExecute))
cmd.inputChanged.add(
self.handlers.make_handler(adsk.core.InputChangedEventHandler, self.onChange))
logger.debug('============================================\nattributes on creation: \n{}'.format(getAttribs(self.design)))
self.clearAttribs('AttribTest')
logger.debug('attributes cleared: \n{}'.format(getAttribs(self.design)))
def onChange(self, args):
changedInput = adsk.core.CommandInput.cast(args.input)
self.body = changedInput.selection(0).entity
logger.debug('entity: {}'.format('Component' if self.body.assemblyContext else 'Root'))
self.setAttribBefore()
logger.debug('attributes set on change: \n{}'.format(getAttribs(self.design)))
collection = adsk.core.ObjectCollection.create()
collection.add(self.body)
self.ui.activeSelections.all = collection
def clearAttribs(self, name): #not used - can be called manually during debugging
attribs = self.design.findAttributes(name, '')
for attrib in attribs:
attrib.deleteMe()
def onExecute(self, args):
logger.debug('attributes immediately onExecute:\n{}'.format(getAttribs(self.design)))
self.setAttribAfter()
logger.debug('attributes after:\n{}\n***********************************************\n'.format(getAttribs(self.design)))
@property
def design(self):
return self.app.activeProduct
@property
def rootComp(self):
return self.design.rootComponent
def setAttribBefore(self):
for face in self.body.faces:
face.nativeObject.attributes.add("AttribTest", "Native before",'') if face.assemblyContext else face.attributes.add("AttribTest", "before",'')
face.attributes.add("AttribTest", "before",'') #should be 2 sets of attributes for component and 1 set for root
def setAttribAfter(self):
for face in self.body.faces:
face.nativeObject.attributes.add("AttribTest", "Native after",'') if face.assemblyContext else face.attributes.add("AttribTest", "after",'')
face.attributes.add("AttribTest", "after",'') #should be 2 sets of attributes for component and 1 set for root
class HandlerHelper(object):
def __init__(self):
self.handlers = [] # needed to prevent GC of SWIG objects
def make_handler(self, handler_cls, notify_method, catch_exceptions=True):
class _Handler(handler_cls):
def notify(self, args):
if catch_exceptions:
try:
notify_method(args)
except:
messageBox('Failed:\n{}'.format(traceback.format_exc()))
else:
notify_method(args)
h = _Handler()
self.handlers.append(h)
return h
attribTest = AttribTestCommand()
def run(context):
try:
attribTest.addButton()
except:
messageBox(traceback.format_exc())
def messageBox(*args):
adsk.core.Application.get().userInterface.messageBox(*args)
def getAttribs(design):
return pformat( list(map(lambda x:x.name, design.findAttributes('AttribTest', ''))))
def stop(context):
try:
attribTest.removeButton()
for handler in logger.handlers:
handler.flush()
handler.close()
logger.removeHandler(handler)
except:
messageBox(traceback.format_exc())
Peter
I'm not an expert, but I know enough to be very, very dangerous.
Life long R&D Engineer (retired after 30+ years in Military Communications, Aerospace Robotics and Transport Automation).
Life long R&D Engineer (retired after 30+ years in Military Communications, Aerospace Robotics and Transport Automation).