@@ -43,10 +43,31 @@ public override void UpdateComputeOrder()
43
43
44
44
public override void Run ( )
45
45
{
46
- // Execute the whole graph:
47
- var enumerator = RunConditionalGraph ( ) ;
46
+ IEnumerator < BaseNode > enumerator ;
48
47
49
- while ( enumerator . MoveNext ( ) )
48
+ if ( startNodeList . Count == 0 )
49
+ {
50
+ enumerator = RunTheGraph ( ) ;
51
+ }
52
+ else
53
+ {
54
+ Stack < BaseNode > nodeToExecute = new Stack < BaseNode > ( ) ;
55
+ // Add all the start nodes to the execution stack
56
+ startNodeList . ForEach ( s => nodeToExecute . Push ( s ) ) ;
57
+ // Execute the whole graph:
58
+ enumerator = RunTheGraph ( nodeToExecute ) ;
59
+ }
60
+
61
+ while ( enumerator . MoveNext ( ) )
62
+ ;
63
+ }
64
+
65
+ private void WaitedRun ( Stack < BaseNode > nodesToRun )
66
+ {
67
+ // Execute the waitable node:
68
+ var enumerator = RunTheGraph ( nodesToRun ) ;
69
+
70
+ while ( enumerator . MoveNext ( ) )
50
71
;
51
72
}
52
73
@@ -67,96 +88,110 @@ IEnumerable<BaseNode> GatherNonConditionalDependencies(BaseNode node)
67
88
yield return dependency ;
68
89
}
69
90
}
70
-
71
- public IEnumerator < BaseNode > RunConditionalGraph ( )
91
+
92
+ private IEnumerator < BaseNode > RunTheGraph ( )
72
93
{
73
- if ( startNodeList . Count == 0 )
74
- {
75
- int count = processList . Count ;
94
+ int count = processList . Count ;
76
95
77
- for ( int i = 0 ; i < count ; i ++ )
78
- {
79
- processList [ i ] . OnProcess ( ) ;
80
- yield return processList [ i ] ;
81
- }
82
- }
83
- else // Conditional graph execution:
96
+ for ( int i = 0 ; i < count ; i ++ )
84
97
{
85
- Stack < BaseNode > nodeToExecute = new Stack < BaseNode > ( ) ;
86
- HashSet < BaseNode > nodeDependenciesGathered = new HashSet < BaseNode > ( ) ;
87
- HashSet < BaseNode > skipConditionalHandling = new HashSet < BaseNode > ( ) ;
88
-
89
- // Add all the start nodes to the execution stack
90
- startNodeList . ForEach ( s => nodeToExecute . Push ( s ) ) ;
91
-
92
- while ( nodeToExecute . Count > 0 )
93
- {
94
- var node = nodeToExecute . Pop ( ) ;
95
- // TODO: maxExecutionTimeMS
96
-
97
- // In case the node is conditional, then we need to execute it's non-conditional dependencies first
98
- if ( node is IConditionalNode && ! skipConditionalHandling . Contains ( node ) )
99
- {
100
- // Gather non-conditional deps: TODO, move to the cache:
101
- if ( nodeDependenciesGathered . Contains ( node ) )
102
- {
103
- // Execute the conditional node:
104
- node . OnProcess ( ) ;
105
- yield return node ;
106
-
107
- // And select the next nodes to execute:
108
- switch ( node )
109
- {
110
- // special code path for the loop node as it will execute multiple times the same nodes
111
- case ForLoopNode forLoopNode :
112
- forLoopNode . index = forLoopNode . start - 1 ; // Initialize the start index
113
- foreach ( var n in forLoopNode . GetExecutedNodesLoopCompleted ( ) )
114
- nodeToExecute . Push ( n ) ;
115
- for ( int i = forLoopNode . start ; i < forLoopNode . end ; i ++ )
116
- {
117
- foreach ( var n in forLoopNode . GetExecutedNodesLoopBody ( ) )
118
- nodeToExecute . Push ( n ) ;
119
-
120
- nodeToExecute . Push ( node ) ; // Increment the counter
121
- }
122
- skipConditionalHandling . Add ( node ) ;
123
- break ;
124
- case IConditionalNode cNode :
125
- foreach ( var n in cNode . GetExecutedNodes ( ) )
126
- nodeToExecute . Push ( n ) ;
127
- break ;
128
- default :
129
- Debug . LogError ( $ "Conditional node { node } not handled") ;
130
- break ;
131
- }
132
- nodeDependenciesGathered . Remove ( node ) ;
133
- }
134
- else
135
- {
136
- nodeToExecute . Push ( node ) ;
137
- nodeDependenciesGathered . Add ( node ) ;
138
- foreach ( var nonConditionalNode in GatherNonConditionalDependencies ( node ) )
139
- {
140
- nodeToExecute . Push ( nonConditionalNode ) ;
141
- }
142
- }
143
- }
144
- else
145
- {
146
- node . OnProcess ( ) ;
147
- yield return node ;
148
- }
149
- }
98
+ processList [ i ] . OnProcess ( ) ;
99
+ yield return processList [ i ] ;
150
100
}
151
101
}
152
-
153
- // Advance the execution of the graph of one node, mostly for debug
102
+
103
+ private IEnumerator < BaseNode > RunTheGraph ( Stack < BaseNode > nodeToExecute )
104
+ {
105
+ HashSet < BaseNode > nodeDependenciesGathered = new HashSet < BaseNode > ( ) ;
106
+ HashSet < BaseNode > skipConditionalHandling = new HashSet < BaseNode > ( ) ;
107
+
108
+ while ( nodeToExecute . Count > 0 )
109
+ {
110
+ var node = nodeToExecute . Pop ( ) ;
111
+ // TODO: maxExecutionTimeMS
112
+
113
+ // In case the node is conditional, then we need to execute it's non-conditional dependencies first
114
+ if ( node is IConditionalNode && ! skipConditionalHandling . Contains ( node ) )
115
+ {
116
+ // Gather non-conditional deps: TODO, move to the cache:
117
+ if ( nodeDependenciesGathered . Contains ( node ) )
118
+ {
119
+ // Execute the conditional node:
120
+ node . OnProcess ( ) ;
121
+ yield return node ;
122
+
123
+ // And select the next nodes to execute:
124
+ switch ( node )
125
+ {
126
+ // special code path for the loop node as it will execute multiple times the same nodes
127
+ case ForLoopNode forLoopNode :
128
+ forLoopNode . index = forLoopNode . start - 1 ; // Initialize the start index
129
+ foreach ( var n in forLoopNode . GetExecutedNodesLoopCompleted ( ) )
130
+ nodeToExecute . Push ( n ) ;
131
+ for ( int i = forLoopNode . start ; i < forLoopNode . end ; i ++ )
132
+ {
133
+ foreach ( var n in forLoopNode . GetExecutedNodesLoopBody ( ) )
134
+ nodeToExecute . Push ( n ) ;
135
+
136
+ nodeToExecute . Push ( node ) ; // Increment the counter
137
+ }
138
+
139
+ skipConditionalHandling . Add ( node ) ;
140
+ break ;
141
+ // another special case for waitable nodes, like "wait for a coroutine", wait x seconds", etc.
142
+ case WaitableNode waitableNode :
143
+ foreach ( var n in waitableNode . GetExecutedNodes ( ) )
144
+ nodeToExecute . Push ( n ) ;
145
+
146
+ waitableNode . onProcessFinished += ( waitedNode ) =>
147
+ {
148
+ Stack < BaseNode > waitedNodes = new Stack < BaseNode > ( ) ;
149
+ foreach ( var n in waitedNode . GetExecuteAfterNodes ( ) )
150
+ waitedNodes . Push ( n ) ;
151
+ WaitedRun ( waitedNodes ) ;
152
+ waitableNode . onProcessFinished = null ;
153
+ } ;
154
+ break ;
155
+ case IConditionalNode cNode :
156
+ foreach ( var n in cNode . GetExecutedNodes ( ) )
157
+ nodeToExecute . Push ( n ) ;
158
+ break ;
159
+ default :
160
+ Debug . LogError ( $ "Conditional node { node } not handled") ;
161
+ break ;
162
+ }
163
+
164
+ nodeDependenciesGathered . Remove ( node ) ;
165
+ }
166
+ else
167
+ {
168
+ nodeToExecute . Push ( node ) ;
169
+ nodeDependenciesGathered . Add ( node ) ;
170
+ foreach ( var nonConditionalNode in GatherNonConditionalDependencies ( node ) )
171
+ {
172
+ nodeToExecute . Push ( nonConditionalNode ) ;
173
+ }
174
+ }
175
+ }
176
+ else
177
+ {
178
+ node . OnProcess ( ) ;
179
+ yield return node ;
180
+ }
181
+ }
182
+ }
183
+
184
+ // Advance the execution of the graph of one node, mostly for debug. Doesn't work for WaitableNode's executeAfter port.
154
185
public void Step ( )
155
186
{
156
187
if ( currentGraphExecution == null )
157
188
{
158
- currentGraphExecution = RunConditionalGraph ( ) ;
159
- currentGraphExecution . MoveNext ( ) ; // Advance to the first node
189
+ Stack < BaseNode > nodeToExecute = new Stack < BaseNode > ( ) ;
190
+ if ( startNodeList . Count > 0 )
191
+ startNodeList . ForEach ( s => nodeToExecute . Push ( s ) ) ;
192
+
193
+ currentGraphExecution = startNodeList . Count == 0 ? RunTheGraph ( ) : RunTheGraph ( nodeToExecute ) ;
194
+ currentGraphExecution . MoveNext ( ) ; // Advance to the first node
160
195
}
161
196
else
162
197
if ( ! currentGraphExecution . MoveNext ( ) )
0 commit comments