@@ -58,6 +58,55 @@ class ExecMode(Enum):
5858 LOCAL = 1
5959 EXTERN = 2
6060
61+ class ForLoopData (BaseObject ):
62+ """
63+ """
64+
65+ def __init__ (self , parentNode = None , connectedAttribute = None , parent = None ):
66+ super (ForLoopData , self ).__init__ (parent )
67+ self ._countForLoop = 0
68+ self ._iterations = ListModel (parent = self ) # list of nodes for each iteration
69+ self ._parentNode = parentNode # parent node
70+ self .connectedAttribute = connectedAttribute # attribute connected to the ForLoop node from parent node
71+
72+ def update (self , currentNode = None ):
73+ # set the connectedAttribute
74+ if currentNode is not None :
75+ for attr in currentNode ._attributes :
76+ if attr .isInput and attr .isLink :
77+ srcAttr = attr .getLinkParam ()
78+ # If the srcAttr is a ListAttribute, it means that the node is in a ForLoop
79+ if isinstance (srcAttr .root , ListAttribute ) and srcAttr .type == attr .type :
80+ self .connectedAttribute = srcAttr .root
81+ self ._parentNode = srcAttr .root .node
82+ break
83+
84+ # set the countForLoop
85+ if self .connectedAttribute is not None :
86+ self ._countForLoop = self ._parentNode ._forLoopData ._countForLoop + 1
87+ if self .connectedAttribute .isInput :
88+ self ._countForLoop -= 1 if self ._countForLoop > 1 else 1
89+
90+ # set the iterations by creating iteration nodes for each connected attribute value and will add them to the core graph and not the ui one
91+ for i in range (len (self .connectedAttribute .value )):
92+ iterationNode = IterationNode (currentNode , i )
93+ # check if node already exists
94+ if iterationNode .name not in [n .name for n in self ._parentNode .graph .nodes ]:
95+ self ._parentNode .graph .addNode (iterationNode , iterationNode .name )
96+ self ._iterations .append (iterationNode )
97+
98+ self .parentNodeChanged .emit ()
99+ self .iterationsChanged .emit ()
100+ self .countForLoopChanged .emit ()
101+
102+ countForLoopChanged = Signal ()
103+ countForLoop = Property (int , lambda self : self ._countForLoop , notify = countForLoopChanged )
104+ iterationsChanged = Signal ()
105+ iterations = Property (Variant , lambda self : self ._iterations , notify = iterationsChanged )
106+ parentNodeChanged = Signal ()
107+ parentNode = Property (Variant , lambda self : self ._parentNode , notify = parentNodeChanged )
108+
109+
61110
62111class StatusData (BaseObject ):
63112 """
@@ -513,6 +562,7 @@ def __init__(self, nodeType, position=None, parent=None, uids=None, **kwargs):
513562 self ._locked = False
514563 self ._duplicates = ListModel (parent = self ) # list of nodes with the same uid
515564 self ._hasDuplicates = False
565+ self ._forLoopData = ForLoopData ()
516566
517567 self .globalStatusChanged .connect (self .updateDuplicatesStatusAndLocked )
518568
@@ -967,6 +1017,10 @@ def updateInternals(self, cacheDir=None):
9671017
9681018 # Update chunks splitting
9691019 self ._updateChunks ()
1020+
1021+ # try to update for loopdata as node is created
1022+ self ._forLoopData .update (self )
1023+
9701024 # Retrieve current internal folder (if possible)
9711025 try :
9721026 folder = self .internalFolder
@@ -1321,23 +1375,11 @@ def has3DOutputAttribute(self):
13211375 return True
13221376 return False
13231377
1324- def _countForLoop (self ):
1378+ def getForLoopData (self ):
13251379 """
1326- Return in how many ForLoop nodes this node is .
1380+ Return the ForLoopData of the node.
13271381 """
1328- count = 0
1329- # Access to the input attributes of the node
1330- for attr in self ._attributes :
1331- if attr .isInput and attr .isLink :
1332- # Access to the attribute connected to the input attribute
1333- srcAttr = attr .getLinkParam ()
1334- # If the srcAttr is a ListAttribute, it means that the node is in a ForLoop
1335- if isinstance (srcAttr .root , ListAttribute ) and srcAttr .type == attr .type :
1336- # Access the countForLoop of the node of the ListAttribute
1337- count = srcAttr .root .node .countForLoop + 1
1338- if srcAttr .root .isInput :
1339- count = count - 1 if count > 1 else 1
1340- return count
1382+ return self ._forLoopData
13411383
13421384
13431385
@@ -1392,8 +1434,8 @@ def _countForLoop(self):
13921434 hasSequenceOutput = Property (bool , hasSequenceOutputAttribute , notify = outputAttrEnabledChanged )
13931435 has3DOutput = Property (bool , has3DOutputAttribute , notify = outputAttrEnabledChanged )
13941436
1395- countForLoopChanged = Signal ()
1396- countForLoop = Property (int , _countForLoop , notify = countForLoopChanged )
1437+ forLoopDataChanged = Signal ()
1438+ forLoopData = Property (Variant , getForLoopData , notify = forLoopDataChanged )
13971439
13981440class Node (BaseNode ):
13991441 """
@@ -1553,6 +1595,22 @@ def _updateChunks(self):
15531595 self ._chunks [0 ].range = desc .Range ()
15541596
15551597
1598+ class IterationNode (BaseNode ):
1599+ """
1600+ A node that is not added to the graph but used to process a specific iteration of a ForLoop node.
1601+ """
1602+ def __init__ (self , node , iteration ):
1603+ super (IterationNode , self ).__init__ (node .nodeType , parent = node .graph , uids = node ._uids )
1604+ self ._name = f"{ node .name } _{ iteration } "
1605+
1606+ self ._chunks .setObjectList ([NodeChunk (self , desc .Range (iteration , iteration ))])
1607+
1608+ # if iteration is 3 set status to success
1609+ if iteration == 3 or iteration == 12 :
1610+ self ._chunks .at (0 ).status .status = Status .SUCCESS
1611+
1612+ # print(self._attributes.at(0))
1613+
15561614class CompatibilityIssue (Enum ):
15571615 """
15581616 Enum describing compatibility issues when deserializing a Node.
0 commit comments