@@ -57,6 +57,7 @@ pub struct NodeRuntime {
5757 pub ( crate ) click_targets : HashMap < NodeId , Vec < ClickTarget > > ,
5858 pub ( crate ) transforms : HashMap < NodeId , DAffine2 > ,
5959 pub ( crate ) upstream_transforms : HashMap < NodeId , DAffine2 > ,
60+ graph_hash : Option < u64 > ,
6061 canvas_cache : HashMap < Vec < LayerId > , SurfaceId > ,
6162}
6263
@@ -124,6 +125,7 @@ impl NodeRuntime {
124125 canvas_cache : HashMap :: new ( ) ,
125126 click_targets : HashMap :: new ( ) ,
126127 transforms : HashMap :: new ( ) ,
128+ graph_hash : None ,
127129 upstream_transforms : HashMap :: new ( ) ,
128130 }
129131 }
@@ -151,8 +153,10 @@ impl NodeRuntime {
151153 } ) => {
152154 let ( result, monitor_nodes) = self . execute_network ( & path, graph, transform, viewport_resolution) . await ;
153155 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+ }
156160 let response = GenerationResponse {
157161 generation_id,
158162 result,
@@ -169,7 +173,7 @@ impl NodeRuntime {
169173 }
170174 }
171175
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 > ) {
173177 if self . wasm_io . is_none ( ) {
174178 self . wasm_io = Some ( WasmApplicationIo :: new ( ) . await ) ;
175179 }
@@ -198,27 +202,41 @@ impl NodeRuntime {
198202 // Required to ensure that the appropriate protonodes are reinserted when the Editor API changes.
199203 let mut graph_input_hash = DefaultHasher :: new ( ) ;
200204 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+ }
201212
202- let scoped_network = wrap_network_in_scope ( graph , graph_input_hash . finish ( ) ) ;
213+ let mut cached_monitor_nodes = None ;
203214
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) ;
209217
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+ }
217237
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) ;
222240 }
223241
224242 use graph_craft:: graphene_compiler:: Executor ;
@@ -231,7 +249,7 @@ impl NodeRuntime {
231249 } ;
232250 let result = match result {
233251 Ok ( value) => value,
234- Err ( e) => return ( Err ( e) , monitor_nodes ) ,
252+ Err ( e) => return ( Err ( e) , cached_monitor_nodes ) ,
235253 } ;
236254
237255 if let TaggedValue :: SurfaceFrame ( SurfaceFrame { surface_id, transform : _ } ) = result {
@@ -244,7 +262,7 @@ impl NodeRuntime {
244262 }
245263 }
246264 }
247- ( Ok ( result) , monitor_nodes )
265+ ( Ok ( result) , cached_monitor_nodes )
248266 }
249267
250268 /// Recomputes the thumbnails for the layers in the graph, modifying the state and updating the UI.
0 commit comments