diff --git a/meshroom/core/graph.py b/meshroom/core/graph.py index cad9e4d8..0eb7bf43 100644 --- a/meshroom/core/graph.py +++ b/meshroom/core/graph.py @@ -899,6 +899,7 @@ class Graph(BaseObject): dstAttr.valueChanged.emit() dstAttr.isLinkChanged.emit() srcAttr.hasOutputConnectionsChanged.emit() + dstAttr.node.countForLoopChanged.emit() return edge def addEdges(self, *edges): @@ -915,6 +916,7 @@ class Graph(BaseObject): dstAttr.valueChanged.emit() dstAttr.isLinkChanged.emit() edge.src.hasOutputConnectionsChanged.emit() + dstAttr.node.countForLoopChanged.emit() def getDepth(self, node, minimal=False): """ Return node's depth in this Graph. @@ -1485,6 +1487,7 @@ class Graph(BaseObject): nodes, edges = self.dfsOnDiscover(startNodes=[fromNode], reverse=True) for node in nodes: node.dirty = True + node.countForLoopChanged.emit() def stopExecution(self): """ Request graph execution to be stopped by terminating running chunks""" diff --git a/meshroom/core/node.py b/meshroom/core/node.py index 79d70f1f..89cf763a 100644 --- a/meshroom/core/node.py +++ b/meshroom/core/node.py @@ -1320,6 +1320,25 @@ class BaseNode(BaseObject): if attr.enabled and attr.isOutput and hasSupportedExt: return True return False + + def _countForLoop(self): + """ + Return in how many ForLoop nodes this node is. + """ + count = 0 + # Access to the input attributes of the node + for attr in self._attributes: + if attr.isInput and attr.isLink: + # Access to the attribute connected to the input attribute + srcAttr = attr.getLinkParam() + # If the srcAttr is a ListAttribute, it means that the node is in a ForLoop + if isinstance(srcAttr.root, ListAttribute) and srcAttr.type == attr.type: + # Access the countForLoop of the node of the ListAttribute + count = srcAttr.root.node.countForLoop + 1 + if srcAttr.root.isInput: + count = count - 1 if count > 1 else 1 + return count + name = Property(str, getName, constant=True) @@ -1373,6 +1392,9 @@ class BaseNode(BaseObject): hasSequenceOutput = Property(bool, hasSequenceOutputAttribute, notify=outputAttrEnabledChanged) has3DOutput = Property(bool, has3DOutputAttribute, notify=outputAttrEnabledChanged) + countForLoopChanged = Signal() + countForLoop = Property(int, _countForLoop, notify=countForLoopChanged) + class Node(BaseNode): """ A standard Graph node based on a node type. diff --git a/meshroom/ui/graph.py b/meshroom/ui/graph.py index 448f2548..caac4e8e 100644 --- a/meshroom/ui/graph.py +++ b/meshroom/ui/graph.py @@ -776,6 +776,7 @@ class UIGraph(QObject): newNode = duplicates[0] previousEdge = self.graph.edge(newNode.attribute(dst.name)) self.replaceEdge(previousEdge, listAttribute.at(i), previousEdge.dst) + newNode.countForLoopChanged.emit() # Last, replace the edge with the first element of the list return self.replaceEdge(currentEdge, listAttribute.at(0), dst) diff --git a/meshroom/ui/qml/GraphEditor/Node.qml b/meshroom/ui/qml/GraphEditor/Node.qml index 47ecdfaf..b343cf79 100755 --- a/meshroom/ui/qml/GraphEditor/Node.qml +++ b/meshroom/ui/qml/GraphEditor/Node.qml @@ -276,6 +276,16 @@ Item { } } + // Is in for loop indicator + MaterialLabel { + visible: node.countForLoop > 0 + text: MaterialIcons.loop + padding: 2 + font.pointSize: 7 + palette.text: Colors.sysPalette.text + ToolTip.text: "Is in " + node.countForLoop + " for loop(s)" + } + // Submitted externally indicator MaterialLabel { visible: ["SUBMITTED", "RUNNING"].includes(node.globalStatus) && node.chunks.count > 0 && node.isExternal