[core] all parameter types could now be used as output attribute

This commit is contained in:
Fabien Castan 2024-05-27 21:58:53 +02:00
parent f1d0211758
commit d2ad818b2c
2 changed files with 39 additions and 30 deletions

View file

@ -63,7 +63,6 @@ class Attribute(BaseObject):
self._node = weakref.ref(node) self._node = weakref.ref(node)
self.attributeDesc = attributeDesc self.attributeDesc = attributeDesc
self._isOutput = isOutput self._isOutput = isOutput
self._value = copy.copy(attributeDesc.value)
self._label = attributeDesc.label self._label = attributeDesc.label
self._enabled = True self._enabled = True
self._validValue = True self._validValue = True
@ -72,6 +71,10 @@ class Attribute(BaseObject):
# invalidation value for output attributes # invalidation value for output attributes
self._invalidationValue = "" self._invalidationValue = ""
self._value = None # Needs to be created before setting the value
# do not emit "value changed" on initialization
self._set_value(copy.copy(attributeDesc.value), emitSignals=False)
@property @property
def node(self): def node(self):
return self._node() return self._node()
@ -183,19 +186,25 @@ class Attribute(BaseObject):
return self.getLinkParam().value return self.getLinkParam().value
return self._value return self._value
def _set_value(self, value): def _set_value(self, value, emitSignals=True):
if self._value == value: if self._value == value:
return return
if isinstance(value, Attribute) or Attribute.isLinkExpression(value): if isinstance(value, Attribute) or Attribute.isLinkExpression(value):
# if we set a link to another attribute # if we set a link to another attribute
self._value = value self._value = value
elif isinstance(value, types.FunctionType):
# evaluate the function
self._value = value(self)
else: else:
# if we set a new value, we use the attribute descriptor validator to check the validity of the value # if we set a new value, we use the attribute descriptor validator to check the validity of the value
# and apply some conversion if needed # and apply some conversion if needed
convertedValue = self.validateValue(value) convertedValue = self.validateValue(value)
self._value = convertedValue self._value = convertedValue
if not emitSignals:
return
if not self.node.isCompatibilityNode: if not self.node.isCompatibilityNode:
self.node.onAttributeChanged(self) self.node.onAttributeChanged(self)
# Request graph update when input parameter value is set # Request graph update when input parameter value is set
@ -232,7 +241,7 @@ class Attribute(BaseObject):
self._set_value(exportedValue) self._set_value(exportedValue)
def resetValue(self): def resetValue(self):
self._value = self.attributeDesc.value self.value = self.defaultValue()
def requestGraphUpdate(self): def requestGraphUpdate(self):
if self.node.graph: if self.node.graph:
@ -326,9 +335,9 @@ class Attribute(BaseObject):
def getExportValue(self): def getExportValue(self):
if self.isLink: if self.isLink:
return self.getLinkParam().asLinkExpr() return self.getLinkParam().asLinkExpr()
if self.isOutput: if self.isOutput and self.desc.isExpression:
return self.defaultValue() return self.defaultValue()
return self._value return self.value
def getEvalValue(self): def getEvalValue(self):
''' '''
@ -497,7 +506,7 @@ class ListAttribute(Attribute):
def resetValue(self): def resetValue(self):
self._value = ListModel(parent=self) self._value = ListModel(parent=self)
def _set_value(self, value): def _set_value(self, value, emitSignals=True):
if self.node.graph: if self.node.graph:
self.remove(0, len(self)) self.remove(0, len(self))
# Link to another attribute # Link to another attribute
@ -505,8 +514,13 @@ class ListAttribute(Attribute):
self._value = value self._value = value
# New value # New value
else: else:
# During initialization self._value may not be set
if self._value is None:
self._value = ListModel(parent=self)
newValue = self.desc.validateValue(value) newValue = self.desc.validateValue(value)
self.extend(newValue) self.extend(newValue)
if not emitSignals:
return
self.requestGraphUpdate() self.requestGraphUpdate()
def upgradeValue(self, exportedValues): def upgradeValue(self, exportedValues):
@ -647,7 +661,7 @@ class GroupAttribute(Attribute):
except KeyError: except KeyError:
raise AttributeError(key) raise AttributeError(key)
def _set_value(self, exportedValue): def _set_value(self, exportedValue, emitSignals=True):
value = self.validateValue(exportedValue) value = self.validateValue(exportedValue)
if isinstance(value, dict): if isinstance(value, dict):
# set individual child attribute values # set individual child attribute values

View file

@ -747,16 +747,14 @@ class BaseNode(BaseObject):
if attr.isInput: if attr.isInput:
continue # skip inputs continue # skip inputs
# Only consider File attributes for command output parameters # Apply expressions for File attributes
if not isinstance(attr.attributeDesc, desc.File): if attr.attributeDesc.isExpression:
continue defaultValue = ""
try:
try: defaultValue = attr.defaultValue()
defaultValue = attr.defaultValue() except AttributeError as e:
except AttributeError as e: # If we load an old scene, the lambda associated to the 'value' could try to access other params that could not exist yet
# If we load an old scene, the lambda associated to the 'value' could try to access other params that could not exist yet logging.warning('Invalid lambda evaluation for "{nodeName}.{attrName}"'.format(nodeName=self.name, attrName=attr.name))
logging.warning('Invalid lambda evaluation for "{nodeName}.{attrName}"'.format(nodeName=self.name, attrName=attr.name))
else:
try: try:
attr.value = defaultValue.format(**self._cmdVars) attr.value = defaultValue.format(**self._cmdVars)
attr._invalidationValue = defaultValue.format(**cmdVarsNoCache) attr._invalidationValue = defaultValue.format(**cmdVarsNoCache)
@ -1295,8 +1293,7 @@ class Node(BaseNode):
# skip missing attributes # skip missing attributes
continue continue
attr = self.attribute(k) attr = self.attribute(k)
if attr.isInput: attr.value = v
attr.value = v
def upgradeAttributeValues(self, values): def upgradeAttributeValues(self, values):
# initialize attribute values # initialize attribute values
@ -1305,11 +1302,10 @@ class Node(BaseNode):
# skip missing attributes # skip missing attributes
continue continue
attr = self.attribute(k) attr = self.attribute(k)
if attr.isInput: try:
try: attr.upgradeValue(v)
attr.upgradeValue(v) except ValueError:
except ValueError: pass
pass
def setInternalAttributeValues(self, values): def setInternalAttributeValues(self, values):
# initialize internal attribute values # initialize internal attribute values
@ -1327,11 +1323,10 @@ class Node(BaseNode):
# skip missing atributes # skip missing atributes
continue continue
attr = self.internalAttribute(k) attr = self.internalAttribute(k)
if attr.isInput: try:
try: attr.upgradeValue(v)
attr.upgradeValue(v) except ValueError:
except ValueError: pass
pass
def toDict(self): def toDict(self):
inputs = {k: v.getExportValue() for k, v in self._attributes.objects.items() if v.isInput} inputs = {k: v.getExportValue() for k, v in self._attributes.objects.items() if v.isInput}
@ -1741,7 +1736,7 @@ def nodeFactory(nodeDict, name=None, template=False, uidConflict=False):
break break
if compatibilityIssue is None: if compatibilityIssue is None:
node = Node(nodeType, position, **inputs) node = Node(nodeType, position, **inputs, **outputs)
node.setInternalAttributeValues(internalInputs) node.setInternalAttributeValues(internalInputs)
else: else:
logging.warning("Compatibility issue detected for node '{}': {}".format(name, compatibilityIssue.name)) logging.warning("Compatibility issue detected for node '{}': {}".format(name, compatibilityIssue.name))