@@ -57,6 +57,7 @@ pub struct NodeRuntime {
57
57
pub ( crate ) click_targets : HashMap < NodeId , Vec < ClickTarget > > ,
58
58
pub ( crate ) transforms : HashMap < NodeId , DAffine2 > ,
59
59
pub ( crate ) upstream_transforms : HashMap < NodeId , DAffine2 > ,
60
+ graph_hash : Option < u64 > ,
60
61
canvas_cache : HashMap < Vec < LayerId > , SurfaceId > ,
61
62
}
62
63
@@ -124,6 +125,7 @@ impl NodeRuntime {
124
125
canvas_cache : HashMap :: new ( ) ,
125
126
click_targets : HashMap :: new ( ) ,
126
127
transforms : HashMap :: new ( ) ,
128
+ graph_hash : None ,
127
129
upstream_transforms : HashMap :: new ( ) ,
128
130
}
129
131
}
@@ -151,8 +153,10 @@ impl NodeRuntime {
151
153
} ) => {
152
154
let ( result, monitor_nodes) = self . execute_network ( & path, graph, transform, viewport_resolution) . await ;
153
155
let mut responses = VecDeque :: new ( ) ;
154
- self . update_thumbnails ( & path, & monitor_nodes, & mut responses) ;
155
- self . update_upstream_transforms ( & monitor_nodes) ;
156
+ if let Some ( ref monitor_nodes) = monitor_nodes {
157
+ self . update_thumbnails ( & path, monitor_nodes, & mut responses) ;
158
+ self . update_upstream_transforms ( monitor_nodes) ;
159
+ }
156
160
let response = GenerationResponse {
157
161
generation_id,
158
162
result,
@@ -169,7 +173,7 @@ impl NodeRuntime {
169
173
}
170
174
}
171
175
172
- async fn execute_network < ' a > ( & ' a mut self , path : & [ LayerId ] , graph : NodeNetwork , transform : DAffine2 , viewport_resolution : UVec2 ) -> ( Result < TaggedValue , String > , MonitorNodes ) {
176
+ async fn execute_network < ' a > ( & ' a mut self , path : & [ LayerId ] , graph : NodeNetwork , transform : DAffine2 , viewport_resolution : UVec2 ) -> ( Result < TaggedValue , String > , Option < MonitorNodes > ) {
173
177
if self . wasm_io . is_none ( ) {
174
178
self . wasm_io = Some ( WasmApplicationIo :: new ( ) . await ) ;
175
179
}
@@ -198,27 +202,41 @@ impl NodeRuntime {
198
202
// Required to ensure that the appropriate protonodes are reinserted when the Editor API changes.
199
203
let mut graph_input_hash = DefaultHasher :: new ( ) ;
200
204
editor_api. font_cache . hash ( & mut graph_input_hash) ;
205
+ let font_hash_code = graph_input_hash. finish ( ) ;
206
+ graph. hash ( & mut graph_input_hash) ;
207
+ let hash_code = graph_input_hash. finish ( ) ;
208
+
209
+ if self . graph_hash != Some ( hash_code) {
210
+ self . graph_hash = None ;
211
+ }
201
212
202
- let scoped_network = wrap_network_in_scope ( graph , graph_input_hash . finish ( ) ) ;
213
+ let mut cached_monitor_nodes = None ;
203
214
204
- let monitor_nodes = scoped_network
205
- . recursive_nodes ( )
206
- . filter ( |( _, node) | node. implementation == DocumentNodeImplementation :: proto ( "graphene_core::memo::MonitorNode<_, _, _>" ) )
207
- . map ( |( _, node) | node. path . clone ( ) . unwrap_or_default ( ) )
208
- . collect :: < Vec < _ > > ( ) ;
215
+ if self . graph_hash . is_none ( ) {
216
+ let scoped_network = wrap_network_in_scope ( graph, font_hash_code) ;
209
217
210
- // We assume only one output
211
- assert_eq ! ( scoped_network. outputs. len( ) , 1 , "Graph with multiple outputs not yet handled" ) ;
212
- let c = Compiler { } ;
213
- let proto_network = match c. compile_single ( scoped_network) {
214
- Ok ( network) => network,
215
- Err ( e) => return ( Err ( e) , monitor_nodes) ,
216
- } ;
218
+ let monitor_nodes = scoped_network
219
+ . recursive_nodes ( )
220
+ . filter ( |( _, node) | node. implementation == DocumentNodeImplementation :: proto ( "graphene_core::memo::MonitorNode<_, _, _>" ) )
221
+ . map ( |( _, node) | node. path . clone ( ) . unwrap_or_default ( ) )
222
+ . collect :: < Vec < _ > > ( ) ;
223
+
224
+ // We assume only one output
225
+ assert_eq ! ( scoped_network. outputs. len( ) , 1 , "Graph with multiple outputs not yet handled" ) ;
226
+ let c = Compiler { } ;
227
+ let proto_network = match c. compile_single ( scoped_network) {
228
+ Ok ( network) => network,
229
+ Err ( e) => return ( Err ( e) , Some ( monitor_nodes) ) ,
230
+ } ;
231
+
232
+ assert_ne ! ( proto_network. nodes. len( ) , 0 , "No protonodes exist?" ) ;
233
+ if let Err ( e) = self . executor . update ( proto_network) . await {
234
+ error ! ( "Failed to update executor:\n {e}" ) ;
235
+ return ( Err ( e) , Some ( monitor_nodes) ) ;
236
+ }
217
237
218
- assert_ne ! ( proto_network. nodes. len( ) , 0 , "No protonodes exist?" ) ;
219
- if let Err ( e) = self . executor . update ( proto_network) . await {
220
- error ! ( "Failed to update executor:\n {e}" ) ;
221
- return ( Err ( e) , monitor_nodes) ;
238
+ cached_monitor_nodes = Some ( monitor_nodes) ;
239
+ self . graph_hash = Some ( hash_code) ;
222
240
}
223
241
224
242
use graph_craft:: graphene_compiler:: Executor ;
@@ -231,7 +249,7 @@ impl NodeRuntime {
231
249
} ;
232
250
let result = match result {
233
251
Ok ( value) => value,
234
- Err ( e) => return ( Err ( e) , monitor_nodes ) ,
252
+ Err ( e) => return ( Err ( e) , cached_monitor_nodes ) ,
235
253
} ;
236
254
237
255
if let TaggedValue :: SurfaceFrame ( SurfaceFrame { surface_id, transform : _ } ) = result {
@@ -244,7 +262,7 @@ impl NodeRuntime {
244
262
}
245
263
}
246
264
}
247
- ( Ok ( result) , monitor_nodes )
265
+ ( Ok ( result) , cached_monitor_nodes )
248
266
}
249
267
250
268
/// Recomputes the thumbnails for the layers in the graph, modifying the state and updating the UI.
0 commit comments