@Anonymous wrote:
This is helpful! I didn't know about this feature. Thanks Ross. Also, I'd very much like to see your wrapper.
Sure, first the code - then some info on how to use it 😉
class Settings(object):
def __init__(self, setting_group_name):
self.__group_name = setting_group_name
self.__tracked_inputs = dict()
@property
def group_name(self):
assert self.__group_name, 'Settings must have a group name.'
return self.__group_name
@property
def _attributes_collection(self):
return adsk.fusion.Design.cast(adsk.core.Application.get().activeProduct).attributes
def _set_fqn(self, input):
ipt = input
fqn = ipt.id
while ipt.parentCommandInput:
ipt = ipt.parentCommandInput
fqn = ipt.id + '^' + fqn
input.fqn = fqn
return fqn
def save(self):
catch_me = dict()
for k, v in self.__dict__.items():
if not re.match( r'^_Settings__.+', k ):
catch_me[k] = v
json_value = json.dumps(catch_me, sort_keys=True)
# adsk.core.Application.get().userInterface.messageBox('Preserving stored values\n' + json_value)
self._attributes_collection.add(self.group_name, 'settings', json_value)
def load(self):
settings_attr = self._attributes_collection.itemByName(self.group_name, 'settings')
if settings_attr:
json_value = settings_attr.value
# adsk.core.Application.get().userInterface.messageBox('Loaded stored values\n' + json_value)
loaded = json.loads( json_value )
for k, v in loaded.items():
self.__dict__[k] = v
def track(self, input):
self._set_fqn(input)
assert input.fqn not in self.__tracked_inputs, 'Duplicate input ID: ' + input.fqn
self.__tracked_inputs[input.fqn] = input
if input.fqn in self.__dict__:
self._restore(input)
else:
self._capture(input)
return input
def _restore(self, input):
class_type = input.classType()
if hasattr(input, 'expression'):
input.expression = self.__dict__[input.fqn]
elif hasattr(input, 'value'):
input.value = self.__dict__[input.fqn]
elif hasattr(input, 'listItems'):
selected = self.__dict__[input.fqn]
for _item in input.listItems:
item = adsk.core.ListItem.cast(_item)
item.isSelected = item.name in selected
elif hasattr(input, 'formattedText'):
input.formattedText = self.__dict__[input.fqn]
elif class_type == 'adsk::core::GroupCommandInput':
d = self.__dict__[input.fqn]
input.isExpanded = d['is_expanded']
input.isEnabledCheckBoxDisplayed = d['is_enabled_checkbox_displayed']
input.isEnabled = d['is_enabled']
elif class_type == 'adsk::core::TabCommandInput':
d = self.__dict__[input.fqn]
input.isVisable = d['is_visable']
input.isEnabled = d['is_enabled']
if d['is_active']:
input.activate()
else:
assert False, 'I dont know how to restore ' + input.fqn + ' it\'s a ' + input.classType()
return input
def _capture(self, input):
class_type = input.classType()
if hasattr(input, 'expression'):
self.__dict__[input.fqn] = input.expression
elif hasattr(input, 'value'):
self.__dict__[input.fqn] = input.value
elif hasattr(input, 'listItems'):
selected = []
for _item in input.listItems:
item = adsk.core.ListItem.cast(_item)
if item.isSelected:
selected.append(item.name)
self.__dict__[input.fqn] = selected
elif hasattr(input, 'formattedText'):
self.__dict__[input.fqn] = input.formattedText
elif class_type == 'adsk::core::GroupCommandInput':
self.__dict__[input.fqn] = {
'is_expanded': input.isExpanded,
'is_enabled_checkbox_displayed': input.isEnabledCheckBoxDisplayed,
'is_enabled': input.isEnabled
}
elif class_type == 'adsk::core::TabCommandInput':
self.__dict__[input.fqn] = {
'is_active': input.isActive,
'is_visable': input.isVisable,
'is_enabled': input.isEnabled
}
else:
assert False, 'I dont know how to capture ' + input.fqn + ' it\'s a ' + input.classType()
try:
json.dumps( self.__dict__[input.fqn] )
except TypeError:
err = input.fqn + ' is not being properly captured'
if hasattr(input, 'classType'):
err += '\n Class Type: ' + input.classType()
else:
err += '\n Type: ' + type(input).__name__
if hasattr(input, 'expression'):
err += '\n expression: ' + input.expression
if hasattr(input, 'value'):
err += '\n value: ' + str(input.value)
if hasattr(input, 'listItems'):
err += '\n listItems: ' + str(input.listItems.count)
if hasattr(input, 'formattedText'):
err += '\n formattedText: ' + input.formattedText
adsk.core.Application.get().userInterface.messageBox(err)
return input
def restore_all(self):
"""Restores tracked input field values from the values held by this settings object."""
for _, i in self.__tracked_inputs.items():
self._restore(i)
def capture_all(self):
"""Captures all tracked input field values into this settings object."""
for _, i in self.__tracked_inputs.items():
self._capture(i)
First, make an instance of this class and ensure it is appropriately scoped (e.g. make it global like your handlers)
# The argument can be any string, but it should be unique to your add-in
settings = Settings('my_command_id')
# load any saved settings
settings.load()
# next make your inputs however you usually do
input = commandInputs.addStringValueInput(...)
# tell settings to track this input
settings.track(input)
# repeat as necessary
# Finally in your execute (or possibly preview) callbacks
settings.capture_all()
settings.save()
Additionally you could use settings.restore_all() to restore the input values to the last saved state - perhaps via some "reset" button.
This Settings class does some magical stuff - for example the act of "tracking" an input will restore any saved value magically.
Let me know if you are able to make use of this class - or if it's "too much" 😉