Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c2e7b26
[core] attribute: Refactoring: Rename link expression constant variable
gregoire-dl Aug 27, 2025
47189df
[core] attribute: Refactoring; Remove `description` property
gregoire-dl Aug 27, 2025
315edbe
[core] attribute: Refactoring; Rename `desc` member
gregoire-dl Aug 27, 2025
e2ff3e1
[core] attribute: Refactoring; Remove `uidIgnoreValue` property
gregoire-dl Aug 27, 2025
99d690f
[core] attribute: Refactoring; Remove `node` &`root` python properties
gregoire-dl Aug 27, 2025
5656381
[core] attribute: Fix: rename `desc` member
gregoire-dl Aug 27, 2025
d1a9232
[core] attribute: Refactoring: Remove `_isReadOnly` method
gregoire-dl Aug 27, 2025
75dfbc3
[core] attribute: Refactoring: Rename get/set value methods
gregoire-dl Aug 27, 2025
09d7858
[core] attribute: Refactoring: Rename get/set enabled methods
gregoire-dl Aug 27, 2025
d1fb786
[core] attribute: Refactoring: Rename get/set linked attributes methods
gregoire-dl Aug 27, 2025
05614d0
[core] attribute: Refactoring: Remove `getType` & `getBaseType` methods
gregoire-dl Aug 27, 2025
e5e1a3f
[core] attribute: Refactoring: Rename `hasValidValue` property
gregoire-dl Aug 27, 2025
a004d8e
[core] attribute: Refactoring: Remove `valueStr` property
gregoire-dl Aug 27, 2025
d27d5d6
[core] attribute: Refactoring: Fix isInput/isOutput properties
gregoire-dl Aug 27, 2025
b716059
[core] attribute: Refactoring: Fix isLink property
gregoire-dl Aug 27, 2025
3bd52fd
[core] attribute: Refactoring: Fix hasOutputConnections property
gregoire-dl Aug 27, 2025
ea84ac8
[core] attribute: Refactoring: Fix isLinkNested property
gregoire-dl Aug 27, 2025
fc6a678
[core] attribute: Refactoring: Rename evalValue method
gregoire-dl Aug 27, 2025
2b370e8
[core] attribute: Refactoring: Remove unused label properties
gregoire-dl Aug 27, 2025
fcdc8e5
[core] attribute: Refactoring: Remove unused fullnameToGraph property
gregoire-dl Aug 27, 2025
e6f6ee1
[core] attribute: Refactoring: Rename names properties
gregoire-dl Aug 27, 2025
97a2330
[core] attribute: Refactoring: Use private attribute desc instead of …
gregoire-dl Aug 27, 2025
7e4e1f4
[core] attribute: Refactoring: Remove get/set label methods
gregoire-dl Aug 28, 2025
ff51b67
[test] attribute: Fix: get linked attributes
gregoire-dl Aug 28, 2025
8a61287
[core] attribute: Refactoring: Rename names properties
gregoire-dl Aug 28, 2025
379ee18
[core] attribute: Refactoring: input / output connections
gregoire-dl Aug 28, 2025
1e10375
[core] attribute: Refactoring: Rename `isLinkNested` property
gregoire-dl Aug 28, 2025
e7be179
[core] attribute: Refactoring: Change properties order
gregoire-dl Aug 28, 2025
50cf366
[core] attribute: Refactoring: Rename `hasValidValue` property
gregoire-dl Aug 28, 2025
37f404b
[core] attribute: Refactoring: Reorganize all attribute link/connections
gregoire-dl Aug 29, 2025
a2c9bbf
[core] attribute: Refactoring: Rename `is2D` and `is3D` properties
gregoire-dl Aug 29, 2025
affe459
[core] attribute: Refactoring: Change methods order
gregoire-dl Aug 29, 2025
6556ed3
[core] attribute: Refactoring: Rename `getDefaultValue` method
gregoire-dl Aug 29, 2025
4535f4b
[core] attribute: Refactoring: Rename `_initValue` method
gregoire-dl Aug 29, 2025
9b400e3
[core] attribute: Refactoring: Use lambda for `isDefault` properties
gregoire-dl Aug 29, 2025
7a00791
[core] attribute: Refactoring: Add doc for signals/properties
gregoire-dl Aug 29, 2025
4438c70
[core] attribute: Refactoring: Change methods order for all `Attribute`
gregoire-dl Sep 1, 2025
72b54fa
[core] attribute: Refactoring: Rename method `getSerializedValue`
gregoire-dl Sep 3, 2025
f24d7ae
[core] attribute: Refactoring: Add documentation for the methods
gregoire-dl Sep 2, 2025
0e6aef4
[core] attribute: Refactoring: Remove multiple spaces after operator
gregoire-dl Sep 2, 2025
f71621e
[core] attribute: Fix wrong edge side in `_hasAnyInputLinks`
gregoire-dl Sep 3, 2025
aafa2de
[core] attribute: Refactoring: Fix remaining `outputConnections`
gregoire-dl Sep 3, 2025
0f79721
[core] attribute: Refactoring: Fix doc for `rootName`
gregoire-dl Sep 3, 2025
dd3ed99
[core] attribute: Refactoring: Rename `inputRootLink`
gregoire-dl Sep 3, 2025
32d069b
[core] attribute: Refactoring: Rename `inputLink`
gregoire-dl Sep 3, 2025
3b9d296
[core] attribute: Refactoring: Rename `outputLink`
gregoire-dl Sep 3, 2025
aa88841
[core] attribute: Refactoring: Rename method `_getInputLink`
gregoire-dl Sep 3, 2025
c460c29
[core] attribute: Refactoring: Rename method `_getOutputLinks`
gregoire-dl Sep 3, 2025
9760d65
[core] attribute: Refactoring: Fix documentation
gregoire-dl Sep 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,095 changes: 542 additions & 553 deletions meshroom/core/attribute.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions meshroom/core/desc/computation.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def computeSize(self, node):
param = node.attribute(self._param)
# Link: use linked node's size
if param.isLink:
return param.getLinkParam().node.size
return param.inputLink.node.size
# ListAttribute: use list size
if isinstance(param.desc, ListAttribute):
return len(param)
Expand Down Expand Up @@ -120,7 +120,7 @@ def computeSize(self, node):
for param in self._params:
param = node.attribute(param)
if param.isLink:
size += param.getLinkParam().node.size
size += param.inputLink.node.size
elif isinstance(param.desc, ListAttribute):
size += len(param)
else:
Expand Down
42 changes: 21 additions & 21 deletions meshroom/core/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ def duplicateNodes(self, srcNodes):

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

if isinstance(edge.dst.root, ListAttribute):
index = edge.dst.root.index(edge.dst)
outListAttributes[edge.dst.getFullNameToNode()] = (edge.dst.root.getFullNameToNode(),
index, edge.dst.value
if edge.dst.value else None)
outListAttributes[edge.dst.fullName] = (edge.dst.root.fullName,
index, edge.dst.value
if edge.dst.value else None)

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

for edge in self.nodeInEdges(node):
self.removeEdge(edge.dst)
inEdges[edge.dst.getFullNameToNode()] = edge.src.getFullNameToNode()
inEdges[edge.dst.fullName] = edge.src.fullName

node.alive = False
self._nodes.remove(node)
Expand Down Expand Up @@ -698,12 +698,12 @@ def upgradeNode(self, nodeName) -> Node:
Returns:
- the upgraded (newly created) node
- a dictionary containing the incoming edges removed by this operation:
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
{dstAttr.fullName, srcAttr.fullName}
- a dictionary containing the outgoing edges removed by this operation:
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
{dstAttr.fullName, srcAttr.fullName}
- a dictionary containing the values, indices and keys of attributes that were connected to a ListAttribute
prior to the removal of all edges:
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)}
{dstAttr.fullName, (dstAttr.root.fullName, dstAttr.index, dstAttr.value)}
"""
node = self.node(nodeName)
if not isinstance(node, CompatibilityNode):
Expand All @@ -730,10 +730,10 @@ def _restoreOutEdges(self, outEdges: dict[str, str], outListAttributes):

Args:
outEdges: a dictionary containing the outgoing edges removed by a call to "removeNode".
{dstAttr.getFullNameToNode(), srcAttr.getFullNameToNode()}
{dstAttr.fullName, srcAttr.fullName}
outListAttributes: a dictionary containing the values, indices and keys of attributes that were connected
to a ListAttribute prior to the removal of all edges.
{dstAttr.getFullNameToNode(), (dstAttr.root.getFullNameToNode(), dstAttr.index, dstAttr.value)}
{dstAttr.fullName, (dstAttr.root.fullName, dstAttr.index, dstAttr.value)}
"""
def _recreateTargetListAttributeChildren(listAttrName: str, index: int, value: Any):
listAttr = self.attribute(listAttrName)
Expand Down Expand Up @@ -899,13 +899,13 @@ def addEdge(self, srcAttr, dstAttr):
if srcAttr.node.graph != self or dstAttr.node.graph != self:
raise RuntimeError('The attributes of the edge should be part of a common graph.')
if dstAttr in self.edges.keys():
raise RuntimeError(f'Destination attribute "{dstAttr.getFullNameToNode()}" is already connected.')
raise RuntimeError(f'Destination attribute "{dstAttr.fullName}" is already connected.')
edge = Edge(srcAttr, dstAttr)
self.edges.add(edge)
self.markNodesDirty(dstAttr.node)
dstAttr.valueChanged.emit()
dstAttr.isLinkChanged.emit()
srcAttr.hasOutputConnectionsChanged.emit()
dstAttr.inputLinksChanged.emit()
srcAttr.outputLinksChanged.emit()
return edge

def addEdges(self, *edges):
Expand All @@ -916,12 +916,12 @@ def addEdges(self, *edges):
@changeTopology
def removeEdge(self, dstAttr):
if dstAttr not in self.edges.keys():
raise RuntimeError(f'Attribute "{dstAttr.getFullNameToNode()}" is not connected')
raise RuntimeError(f'Attribute "{dstAttr.fullName}" is not connected')
edge = self.edges.pop(dstAttr)
self.markNodesDirty(dstAttr.node)
dstAttr.valueChanged.emit()
dstAttr.isLinkChanged.emit()
edge.src.hasOutputConnectionsChanged.emit()
dstAttr.inputLinksChanged.emit()
edge.src.outputLinksChanged.emit()

def getDepth(self, node, minimal=False):
""" Return node's depth in this Graph.
Expand Down Expand Up @@ -1242,7 +1242,7 @@ def getEdges(self, dependenciesOnly=False):
attr = e.src
if dependenciesOnly:
if attr.isLink:
attr = attr.getLinkParam(recursive=True)
attr = attr.inputRootLink
if not attr.isOutput:
continue
newE = Edge(attr, e.dst)
Expand Down
12 changes: 6 additions & 6 deletions meshroom/core/graphIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,18 @@ def _serializeAttribute(self, attribute: Attribute) -> Any:
Serialize `attribute` (recursively for list/groups) and deal with attributes being connected
to nodes that are not part of the partial list of nodes to serialize.
"""
linkParam = attribute.getLinkParam()
linkAttribute = attribute.inputLink

if linkParam is not None:
if linkAttribute is not None:
# Use standard link serialization if upstream node is part of the serialization.
if linkParam.node in self.nodes:
return attribute.getExportValue()
if linkAttribute.node in self.nodes:
return attribute.getSerializedValue()
# Skip link serialization otherwise.
# If part of a list, this entry can be discarded.
if isinstance(attribute.root, ListAttribute):
return None
# Otherwise, return the default value for this attribute.
return attribute.defaultValue()
return attribute.getDefaultValue()

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

return attribute.getExportValue()
return attribute.getSerializedValue()
30 changes: 15 additions & 15 deletions meshroom/core/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -875,14 +875,14 @@ def _computeUid(self):
for attr in self.invalidatingAttributes:
if not attr.enabled:
continue # Disabled params do not contribute to the uid
dynamicOutputAttr = attr.isLink and attr.getLinkParam(recursive=True).desc.isDynamicValue
dynamicOutputAttr = attr.isLink and attr.inputRootLink.desc.isDynamicValue
# For dynamic output attributes, the UID does not depend on the attribute value.
# In particular, when loading a project file, the UIDs are updated first,
# and the node status and the dynamic output values are not yet loaded,
# so we should not read the attribute value.
if not dynamicOutputAttr and attr.value == attr.uidIgnoreValue:
if not dynamicOutputAttr and attr.value == attr.desc.uidIgnoreValue:
continue # For non-dynamic attributes, check if the value should be ignored
uidAttributes.append((attr.getName(), attr.uid()))
uidAttributes.append((attr.name, attr.uid()))
uidAttributes.sort()

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

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

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

@property
def isParallelized(self):
Expand Down Expand Up @@ -1620,7 +1620,7 @@ def has3DOutputAttribute(self):
False otherwise.
"""

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

name = Property(str, getName, constant=True)
defaultLabel = Property(str, getDefaultLabel, constant=True)
Expand Down Expand Up @@ -1760,9 +1760,9 @@ def upgradeInternalAttributeValues(self, values):
pass

def toDict(self):
inputs = {k: v.getExportValue() for k, v in self._attributes.objects.items() if v.isInput}
internalInputs = {k: v.getExportValue() for k, v in self._internalAttributes.objects.items()}
outputs = ({k: v.getExportValue() for k, v in self._attributes.objects.items()
inputs = {k: v.getSerializedValue() for k, v in self._attributes.objects.items() if v.isInput}
internalInputs = {k: v.getSerializedValue() for k, v in self._internalAttributes.objects.items()}
outputs = ({k: v.getSerializedValue() for k, v in self._attributes.objects.items()
if v.isOutput and not v.desc.isDynamicValue})

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

@property
def internalInputs(self):
""" Get current node's internal attributes """
if not self.graph:
return self._internalInputs
return {k: v.getExportValue() for k, v in self._internalAttributes.objects.items()}
return {k: v.getSerializedValue() for k, v in self._internalAttributes.objects.items()}

def toDict(self):
"""
Expand Down
26 changes: 13 additions & 13 deletions meshroom/ui/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ def undoImpl(self):
class SetAttributeCommand(GraphCommand):
def __init__(self, graph, attribute, value, parent=None):
super().__init__(graph, parent)
self.attrName = attribute.getFullNameToNode()
self.attrName = attribute.fullName
self.value = value
self.oldValue = attribute.getExportValue()
self.setText(f"Set Attribute '{attribute.getFullNameToNode()}'")
self.oldValue = attribute.getSerializedValue()
self.setText(f"Set Attribute '{attribute.fullName}'")

def redoImpl(self):
if self.value == self.oldValue:
Expand All @@ -310,8 +310,8 @@ def undoImpl(self):
class AddEdgeCommand(GraphCommand):
def __init__(self, graph, src, dst, parent=None):
super().__init__(graph, parent)
self.srcAttr = src.getFullNameToNode()
self.dstAttr = dst.getFullNameToNode()
self.srcAttr = src.fullName
self.dstAttr = dst.fullName
self.setText(f"Connect '{self.srcAttr}'->'{self.dstAttr}'")

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

def redoImpl(self):
Expand All @@ -345,7 +345,7 @@ class ListAttributeAppendCommand(GraphCommand):
def __init__(self, graph, listAttribute, value, parent=None):
super().__init__(graph, parent)
assert isinstance(listAttribute, ListAttribute)
self.attrName = listAttribute.getFullNameToNode()
self.attrName = listAttribute.fullName
self.index = None
self.count = 1
self.value = value if value else None
Expand All @@ -371,10 +371,10 @@ def __init__(self, graph, attribute, parent=None):
super().__init__(graph, parent)
listAttribute = attribute.root
assert isinstance(listAttribute, ListAttribute)
self.listAttrName = listAttribute.getFullNameToNode()
self.listAttrName = listAttribute.fullName
self.index = listAttribute.index(attribute)
self.value = attribute.getExportValue()
self.setText(f"Remove {attribute.getFullNameToNode()}")
self.value = attribute.getSerializedValue()
self.setText(f"Remove {attribute.fullName}")

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

Expand Down
Loading
Loading