Skip to content

Commit de33f55

Browse files
authored
Merge pull request #2872 from alicevision/dev/attributeRefactoring
[core] Attribute Refactoring
2 parents 402b692 + 9760d65 commit de33f55

20 files changed

+667
-678
lines changed

meshroom/core/attribute.py

Lines changed: 542 additions & 553 deletions
Large diffs are not rendered by default.

meshroom/core/desc/computation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def computeSize(self, node):
9292
param = node.attribute(self._param)
9393
# Link: use linked node's size
9494
if param.isLink:
95-
return param.getLinkParam().node.size
95+
return param.inputLink.node.size
9696
# ListAttribute: use list size
9797
if isinstance(param.desc, ListAttribute):
9898
return len(param)
@@ -120,7 +120,7 @@ def computeSize(self, node):
120120
for param in self._params:
121121
param = node.attribute(param)
122122
if param.isLink:
123-
size += param.getLinkParam().node.size
123+
size += param.inputLink.node.size
124124
elif isinstance(param.desc, ListAttribute):
125125
size += len(param)
126126
else:

meshroom/core/graph.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ def duplicateNodes(self, srcNodes):
560560

561561
# re-create edges taking into account what has been duplicated
562562
for attr, linkExpression in duplicateEdges.items():
563-
# logging.warning("attr={} linkExpression={}".format(attr.fullName, linkExpression))
563+
# logging.warning("attr={} linkExpression={}".format(attr.rootName, linkExpression))
564564
link = linkExpression[1:-1] # remove starting '{' and trailing '}'
565565
# get source node and attribute name
566566
edgeSrcNodeName, edgeSrcAttrName = link.split(".", 1)
@@ -594,12 +594,12 @@ def removeNode(self, nodeName):
594594
Remove the node identified by 'nodeName' from the graph.
595595
Returns:
596596
- a dictionary containing the incoming edges removed by this operation:
597-
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
597+
{dstAttr.fullName, srcAttr.fullName}
598598
- a dictionary containing the outgoing edges removed by this operation:
599-
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
599+
{dstAttr.fullName, srcAttr.fullName}
600600
- a dictionary containing the values, indices and keys of attributes that were connected to a ListAttribute
601601
prior to the removal of all edges:
602-
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)}
602+
{dstAttr.fullName, (dstAttr.root.fullName, dstAttr.index, dstAttr.value)}
603603
"""
604604
node = self.node(nodeName)
605605
inEdges = {}
@@ -614,13 +614,13 @@ def removeNode(self, nodeName):
614614
# - once we have collected all the information, the edges (and perhaps the entries in ListAttributes) can
615615
# actually be removed
616616
for edge in self.nodeOutEdges(node):
617-
outEdges[edge.dst.getFullNameToNode()] = edge.src.getFullNameToNode()
617+
outEdges[edge.dst.fullName] = edge.src.fullName
618618

619619
if isinstance(edge.dst.root, ListAttribute):
620620
index = edge.dst.root.index(edge.dst)
621-
outListAttributes[edge.dst.getFullNameToNode()] = (edge.dst.root.getFullNameToNode(),
622-
index, edge.dst.value
623-
if edge.dst.value else None)
621+
outListAttributes[edge.dst.fullName] = (edge.dst.root.fullName,
622+
index, edge.dst.value
623+
if edge.dst.value else None)
624624

625625
for edge in self.nodeOutEdges(node):
626626
self.removeEdge(edge.dst)
@@ -632,7 +632,7 @@ def removeNode(self, nodeName):
632632

633633
for edge in self.nodeInEdges(node):
634634
self.removeEdge(edge.dst)
635-
inEdges[edge.dst.getFullNameToNode()] = edge.src.getFullNameToNode()
635+
inEdges[edge.dst.fullName] = edge.src.fullName
636636

637637
node.alive = False
638638
self._nodes.remove(node)
@@ -698,12 +698,12 @@ def upgradeNode(self, nodeName) -> Node:
698698
Returns:
699699
- the upgraded (newly created) node
700700
- a dictionary containing the incoming edges removed by this operation:
701-
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
701+
{dstAttr.fullName, srcAttr.fullName}
702702
- a dictionary containing the outgoing edges removed by this operation:
703-
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
703+
{dstAttr.fullName, srcAttr.fullName}
704704
- a dictionary containing the values, indices and keys of attributes that were connected to a ListAttribute
705705
prior to the removal of all edges:
706-
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)}
706+
{dstAttr.fullName, (dstAttr.root.fullName, dstAttr.index, dstAttr.value)}
707707
"""
708708
node = self.node(nodeName)
709709
if not isinstance(node, CompatibilityNode):
@@ -730,10 +730,10 @@ def _restoreOutEdges(self, outEdges: dict[str, str], outListAttributes):
730730
731731
Args:
732732
outEdges: a dictionary containing the outgoing edges removed by a call to "removeNode".
733-
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
733+
{dstAttr.fullName, srcAttr.fullName}
734734
outListAttributes: a dictionary containing the values, indices and keys of attributes that were connected
735735
to a ListAttribute prior to the removal of all edges.
736-
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)}
736+
{dstAttr.fullName, (dstAttr.root.fullName, dstAttr.index, dstAttr.value)}
737737
"""
738738
def _recreateTargetListAttributeChildren(listAttrName: str, index: int, value: Any):
739739
listAttr = self.attribute(listAttrName)
@@ -899,13 +899,13 @@ def addEdge(self, srcAttr, dstAttr):
899899
if srcAttr.node.graph != self or dstAttr.node.graph != self:
900900
raise RuntimeError('The attributes of the edge should be part of a common graph.')
901901
if dstAttr in self.edges.keys():
902-
raise RuntimeError(f'Destination attribute "{dstAttr.getFullNameToNode()}" is already connected.')
902+
raise RuntimeError(f'Destination attribute "{dstAttr.fullName}" is already connected.')
903903
edge = Edge(srcAttr, dstAttr)
904904
self.edges.add(edge)
905905
self.markNodesDirty(dstAttr.node)
906906
dstAttr.valueChanged.emit()
907-
dstAttr.isLinkChanged.emit()
908-
srcAttr.hasOutputConnectionsChanged.emit()
907+
dstAttr.inputLinksChanged.emit()
908+
srcAttr.outputLinksChanged.emit()
909909
return edge
910910

911911
def addEdges(self, *edges):
@@ -916,12 +916,12 @@ def addEdges(self, *edges):
916916
@changeTopology
917917
def removeEdge(self, dstAttr):
918918
if dstAttr not in self.edges.keys():
919-
raise RuntimeError(f'Attribute "{dstAttr.getFullNameToNode()}" is not connected')
919+
raise RuntimeError(f'Attribute "{dstAttr.fullName}" is not connected')
920920
edge = self.edges.pop(dstAttr)
921921
self.markNodesDirty(dstAttr.node)
922922
dstAttr.valueChanged.emit()
923-
dstAttr.isLinkChanged.emit()
924-
edge.src.hasOutputConnectionsChanged.emit()
923+
dstAttr.inputLinksChanged.emit()
924+
edge.src.outputLinksChanged.emit()
925925

926926
def getDepth(self, node, minimal=False):
927927
""" Return node's depth in this Graph.
@@ -1242,7 +1242,7 @@ def getEdges(self, dependenciesOnly=False):
12421242
attr = e.src
12431243
if dependenciesOnly:
12441244
if attr.isLink:
1245-
attr = attr.getLinkParam(recursive=True)
1245+
attr = attr.inputRootLink
12461246
if not attr.isOutput:
12471247
continue
12481248
newE = Edge(attr, e.dst)

meshroom/core/graphIO.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,18 @@ def _serializeAttribute(self, attribute: Attribute) -> Any:
200200
Serialize `attribute` (recursively for list/groups) and deal with attributes being connected
201201
to nodes that are not part of the partial list of nodes to serialize.
202202
"""
203-
linkParam = attribute.getLinkParam()
203+
linkAttribute = attribute.inputLink
204204

205-
if linkParam is not None:
205+
if linkAttribute is not None:
206206
# Use standard link serialization if upstream node is part of the serialization.
207-
if linkParam.node in self.nodes:
208-
return attribute.getExportValue()
207+
if linkAttribute.node in self.nodes:
208+
return attribute.getSerializedValue()
209209
# Skip link serialization otherwise.
210210
# If part of a list, this entry can be discarded.
211211
if isinstance(attribute.root, ListAttribute):
212212
return None
213213
# Otherwise, return the default value for this attribute.
214-
return attribute.defaultValue()
214+
return attribute.getDefaultValue()
215215

216216
if isinstance(attribute, ListAttribute):
217217
# Recusively serialize each child of the ListAttribute, skipping those for which the attribute
@@ -226,4 +226,4 @@ def _serializeAttribute(self, attribute: Attribute) -> Any:
226226
# Recursively serialize each child of the group attribute.
227227
return {name: self._serializeAttribute(child) for name, child in attribute.value.items()}
228228

229-
return attribute.getExportValue()
229+
return attribute.getSerializedValue()

meshroom/core/node.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -875,14 +875,14 @@ def _computeUid(self):
875875
for attr in self.invalidatingAttributes:
876876
if not attr.enabled:
877877
continue # Disabled params do not contribute to the uid
878-
dynamicOutputAttr = attr.isLink and attr.getLinkParam(recursive=True).desc.isDynamicValue
878+
dynamicOutputAttr = attr.isLink and attr.inputRootLink.desc.isDynamicValue
879879
# For dynamic output attributes, the UID does not depend on the attribute value.
880880
# In particular, when loading a project file, the UIDs are updated first,
881881
# and the node status and the dynamic output values are not yet loaded,
882882
# so we should not read the attribute value.
883-
if not dynamicOutputAttr and attr.value == attr.uidIgnoreValue:
883+
if not dynamicOutputAttr and attr.value == attr.desc.uidIgnoreValue:
884884
continue # For non-dynamic attributes, check if the value should be ignored
885-
uidAttributes.append((attr.getName(), attr.uid()))
885+
uidAttributes.append((attr.name, attr.uid()))
886886
uidAttributes.sort()
887887

888888
# Adding the node type prevents ending up with two identical UIDs for different node types
@@ -897,8 +897,8 @@ def _buildCmdVars(self):
897897
"""
898898
def _buildAttributeCmdVars(cmdVars, name, attr):
899899
if attr.enabled:
900-
group = attr.attributeDesc.group(attr.node) \
901-
if isinstance(attr.attributeDesc.group, types.FunctionType) else attr.attributeDesc.group
900+
group = attr.desc.group(attr.node) \
901+
if isinstance(attr.desc.group, types.FunctionType) else attr.desc.group
902902
if group is not None:
903903
# If there is a valid command line "group"
904904
v = attr.getValueStr(withQuotes=True)
@@ -944,13 +944,13 @@ def _buildAttributeCmdVars(cmdVars, name, attr):
944944
continue # skip inputs
945945

946946
# Apply expressions for File attributes
947-
if attr.attributeDesc.isExpression:
947+
if attr.desc.isExpression:
948948
defaultValue = ""
949949
# Do not evaluate expression for disabled attributes
950950
# (the expression may refer to other attributes that are not defined)
951951
if attr.enabled:
952952
try:
953-
defaultValue = attr.defaultValue()
953+
defaultValue = attr.getDefaultValue()
954954
except AttributeError:
955955
# If we load an old scene, the lambda associated to the 'value' could try to
956956
# access other params that could not exist yet
@@ -978,8 +978,8 @@ def _buildAttributeCmdVars(cmdVars, name, attr):
978978
self._cmdVars[name + 'Value'] = attr.getValueStr(withQuotes=False)
979979

980980
if v:
981-
self._cmdVars[attr.attributeDesc.group] = \
982-
self._cmdVars.get(attr.attributeDesc.group, '') + ' ' + self._cmdVars[name]
981+
self._cmdVars[attr.desc.group] = \
982+
self._cmdVars.get(attr.desc.group, '') + ' ' + self._cmdVars[name]
983983

984984
@property
985985
def isParallelized(self):
@@ -1620,7 +1620,7 @@ def has3DOutputAttribute(self):
16201620
False otherwise.
16211621
"""
16221622

1623-
return next((attr for attr in self._attributes if attr.enabled and attr.isOutput and attr.is3D), None) is not None
1623+
return next((attr for attr in self._attributes if attr.enabled and attr.isOutput and attr.is3dDisplayable), None) is not None
16241624

16251625
name = Property(str, getName, constant=True)
16261626
defaultLabel = Property(str, getDefaultLabel, constant=True)
@@ -1760,9 +1760,9 @@ def upgradeInternalAttributeValues(self, values):
17601760
pass
17611761

17621762
def toDict(self):
1763-
inputs = {k: v.getExportValue() for k, v in self._attributes.objects.items() if v.isInput}
1764-
internalInputs = {k: v.getExportValue() for k, v in self._internalAttributes.objects.items()}
1765-
outputs = ({k: v.getExportValue() for k, v in self._attributes.objects.items()
1763+
inputs = {k: v.getSerializedValue() for k, v in self._attributes.objects.items() if v.isInput}
1764+
internalInputs = {k: v.getSerializedValue() for k, v in self._internalAttributes.objects.items()}
1765+
outputs = ({k: v.getSerializedValue() for k, v in self._attributes.objects.items()
17661766
if v.isOutput and not v.desc.isDynamicValue})
17671767

17681768
return {
@@ -2012,14 +2012,14 @@ def inputs(self):
20122012
# if node has not been added to a graph, return serialized node inputs
20132013
if not self.graph:
20142014
return self._inputs
2015-
return {k: v.getExportValue() for k, v in self._attributes.objects.items() if v.isInput}
2015+
return {k: v.getSerializedValue() for k, v in self._attributes.objects.items() if v.isInput}
20162016

20172017
@property
20182018
def internalInputs(self):
20192019
""" Get current node's internal attributes """
20202020
if not self.graph:
20212021
return self._internalInputs
2022-
return {k: v.getExportValue() for k, v in self._internalAttributes.objects.items()}
2022+
return {k: v.getSerializedValue() for k, v in self._internalAttributes.objects.items()}
20232023

20242024
def toDict(self):
20252025
"""

meshroom/ui/commands.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,10 @@ def undoImpl(self):
286286
class SetAttributeCommand(GraphCommand):
287287
def __init__(self, graph, attribute, value, parent=None):
288288
super().__init__(graph, parent)
289-
self.attrName = attribute.getFullNameToNode()
289+
self.attrName = attribute.fullName
290290
self.value = value
291-
self.oldValue = attribute.getExportValue()
292-
self.setText(f"Set Attribute '{attribute.getFullNameToNode()}'")
291+
self.oldValue = attribute.getSerializedValue()
292+
self.setText(f"Set Attribute '{attribute.fullName}'")
293293

294294
def redoImpl(self):
295295
if self.value == self.oldValue:
@@ -310,8 +310,8 @@ def undoImpl(self):
310310
class AddEdgeCommand(GraphCommand):
311311
def __init__(self, graph, src, dst, parent=None):
312312
super().__init__(graph, parent)
313-
self.srcAttr = src.getFullNameToNode()
314-
self.dstAttr = dst.getFullNameToNode()
313+
self.srcAttr = src.fullName
314+
self.dstAttr = dst.fullName
315315
self.setText(f"Connect '{self.srcAttr}'->'{self.dstAttr}'")
316316

317317
if src.baseType != dst.baseType:
@@ -328,8 +328,8 @@ def undoImpl(self):
328328
class RemoveEdgeCommand(GraphCommand):
329329
def __init__(self, graph, edge, parent=None):
330330
super().__init__(graph, parent)
331-
self.srcAttr = edge.src.getFullNameToNode()
332-
self.dstAttr = edge.dst.getFullNameToNode()
331+
self.srcAttr = edge.src.fullName
332+
self.dstAttr = edge.dst.fullName
333333
self.setText(f"Disconnect '{self.srcAttr}'->'{self.dstAttr}'")
334334

335335
def redoImpl(self):
@@ -345,7 +345,7 @@ class ListAttributeAppendCommand(GraphCommand):
345345
def __init__(self, graph, listAttribute, value, parent=None):
346346
super().__init__(graph, parent)
347347
assert isinstance(listAttribute, ListAttribute)
348-
self.attrName = listAttribute.getFullNameToNode()
348+
self.attrName = listAttribute.fullName
349349
self.index = None
350350
self.count = 1
351351
self.value = value if value else None
@@ -371,10 +371,10 @@ def __init__(self, graph, attribute, parent=None):
371371
super().__init__(graph, parent)
372372
listAttribute = attribute.root
373373
assert isinstance(listAttribute, ListAttribute)
374-
self.listAttrName = listAttribute.getFullNameToNode()
374+
self.listAttrName = listAttribute.fullName
375375
self.index = listAttribute.index(attribute)
376-
self.value = attribute.getExportValue()
377-
self.setText(f"Remove {attribute.getFullNameToNode()}")
376+
self.value = attribute.getSerializedValue()
377+
self.setText(f"Remove {attribute.fullName}")
378378

379379
def redoImpl(self):
380380
listAttribute = self.graph.attribute(self.listAttrName)
@@ -390,8 +390,8 @@ class RemoveImagesCommand(GraphCommand):
390390
def __init__(self, graph, cameraInitNodes, parent=None):
391391
super().__init__(graph, parent)
392392
self.cameraInits = cameraInitNodes
393-
self.viewpoints = { cameraInit.name: cameraInit.attribute("viewpoints").getExportValue() for cameraInit in self.cameraInits }
394-
self.intrinsics = { cameraInit.name: cameraInit.attribute("intrinsics").getExportValue() for cameraInit in self.cameraInits }
393+
self.viewpoints = { cameraInit.name: cameraInit.attribute("viewpoints").getSerializedValue() for cameraInit in self.cameraInits }
394+
self.intrinsics = { cameraInit.name: cameraInit.attribute("intrinsics").getSerializedValue() for cameraInit in self.cameraInits }
395395
self.title = f"Remove{' ' if len(self.cameraInits) == 1 else ' All '}Images"
396396
self.setText(self.title)
397397

0 commit comments

Comments
 (0)