Skip to content

Commit 596191b

Browse files
authored
Render thumbnails from each layer's observed context (#4802)
1 parent 6c158c6 commit 596191b

9 files changed

Lines changed: 371 additions & 112 deletions

File tree

‎editor/src/messages/portfolio/document/utility_types/layers_in_view.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,23 @@ impl LayersInView {
2121
&self.layers_panel
2222
}
2323

24+
/// The layers in view in either the Layers panel or the node graph.
25+
pub fn all_in_view(&self) -> HashSet<NodeId> {
26+
self.layers_panel.union(&self.node_graph).copied().collect()
27+
}
28+
2429
/// Sets the layers with a row in view in the Layers panel, sending the thumbnails it lacks for them.
2530
pub fn set_layers_panel(&mut self, layers: HashSet<NodeId>, responses: &mut VecDeque<Message>) {
2631
self.layers_panel = layers;
2732
self.send_thumbnails_in_view(responses);
33+
responses.add(PortfolioMessage::SubmitThumbnailsInView);
2834
}
2935

3036
/// Sets the nodes in view in the node graph, sending the thumbnails it lacks for those that are layers.
3137
pub fn set_node_graph(&mut self, nodes: HashSet<NodeId>, responses: &mut VecDeque<Message>) {
3238
self.node_graph = nodes;
3339
self.send_thumbnails_in_view(responses);
40+
responses.add(PortfolioMessage::SubmitThumbnailsInView);
3441
}
3542

3643
/// Keeps a layer's newly rendered thumbnail, sending it to the frontend only if the layer is in view.

‎editor/src/messages/portfolio/portfolio_message.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ pub enum PortfolioMessage {
150150
},
151151
SubmitEyedropperPreviewRender,
152152
PollNodeGraphEvaluation,
153+
SubmitThumbnailsInView,
153154
ToggleResetNodesToDefinitionsOnOpen,
154155
ToggleRulers,
155156
UpdateDocumentWidgets,

‎editor/src/messages/portfolio/portfolio_message_handler.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
10181018
}
10191019
}
10201020
}
1021+
PortfolioMessage::SubmitThumbnailsInView => {
1022+
if let Some(document_id) = self.active_document_id
1023+
&& let Some(document) = self.documents.get(&document_id)
1024+
{
1025+
self.executor.submit_thumbnails_in_view(document, document_id);
1026+
}
1027+
}
10211028
PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen => {
10221029
self.reset_node_definitions_on_open = !self.reset_node_definitions_on_open;
10231030
responses.add(MenuBarMessage::SendLayout);

‎editor/src/node_graph_executor.rs‎

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ pub enum NodeGraphUpdate {
6666
ExecutionResponse(Box<ExecutionResponse>),
6767
CompilationResponse(CompilationResponse),
6868
EyedropperPreview(Raster<CPU>),
69+
/// Thumbnails rendered for layers that came into view, from the network of the given document.
70+
Thumbnails {
71+
responses: VecDeque<FrontendMessage>,
72+
document_id: DocumentId,
73+
},
6974
}
7075

7176
#[derive(Debug)]
@@ -76,6 +81,8 @@ pub struct NodeGraphExecutor {
7681
futures: VecDeque<(u64, ExecutionContext)>,
7782
pending: Option<(u64, ExecutionContext)>,
7883
node_graph_hash: u64,
84+
/// The document whose network the graph runtime was last sent.
85+
node_graph_document: Option<DocumentId>,
7986
/// Full path from the root document network to the node currently being inspected by the Data panel, or empty if nothing is selected.
8087
/// The last element is the inspect target itself; preceding elements identify the nested subnetwork the node lives in,
8188
/// so the runtime can splice its monitor node alongside the target rather than only at the top level.
@@ -126,6 +133,7 @@ impl NodeGraphExecutor {
126133
sender: request_sender,
127134
receiver: response_receiver,
128135
node_graph_hash: 0,
136+
node_graph_document: None,
129137
current_execution_id: 0,
130138
previous_node_to_inspect: Vec::new(),
131139
gradient_migration: None,
@@ -151,6 +159,19 @@ impl NodeGraphExecutor {
151159
execution_id
152160
}
153161

162+
/// Tells the graph runtime which of the document's layers have their thumbnails in view, so it renders only those.
163+
pub fn submit_thumbnails_in_view(&self, document: &DocumentMessageHandler, document_id: DocumentId) {
164+
// The runtime renders thumbnails from the network it has, which may still be another document's
165+
if self.node_graph_document != Some(document_id) {
166+
return;
167+
}
168+
169+
let layers = document.layers_in_view.all_in_view();
170+
self.sender
171+
.send(GraphRuntimeRequest::ThumbnailsInView { layers, document_id })
172+
.expect("Failed to send the thumbnails in view");
173+
}
174+
154175
pub fn update_editor_preferences(&self, editor_preferences: EditorPreferences) {
155176
self.sender
156177
.send(GraphRuntimeRequest::EditorPreferencesUpdate(editor_preferences))
@@ -178,13 +199,14 @@ impl NodeGraphExecutor {
178199
}
179200

180201
/// Update the cached network if necessary.
181-
fn update_node_graph(&mut self, document: &mut DocumentMessageHandler, node_to_inspect: Vec<NodeId>, ignore_hash: bool) -> Result<(), String> {
202+
fn update_node_graph(&mut self, document: &mut DocumentMessageHandler, document_id: DocumentId, node_to_inspect: Vec<NodeId>, ignore_hash: bool) -> Result<(), String> {
182203
let network_hash = document.network_interface.network_hash();
183204
// Refresh the graph when it changes or the inspect node changes
184-
if network_hash != self.node_graph_hash || self.previous_node_to_inspect != node_to_inspect || ignore_hash {
205+
if network_hash != self.node_graph_hash || self.node_graph_document != Some(document_id) || self.previous_node_to_inspect != node_to_inspect || ignore_hash {
185206
let network = document.network_interface.document_network().clone();
186207
self.previous_node_to_inspect.clone_from(&node_to_inspect);
187208
self.node_graph_hash = network_hash;
209+
self.node_graph_document = Some(document_id);
188210

189211
let resources = document.resources.registry.clone();
190212

@@ -251,7 +273,7 @@ impl NodeGraphExecutor {
251273
ignore_hash: bool,
252274
pointer: DVec2,
253275
) -> Result<Message, String> {
254-
self.update_node_graph(document, node_to_inspect, ignore_hash)?;
276+
self.update_node_graph(document, document_id, node_to_inspect, ignore_hash)?;
255277
self.submit_current_node_graph_evaluation(document, document_id, viewport_resolution, viewport_scale, time, pointer)
256278
}
257279

@@ -554,22 +576,47 @@ impl NodeGraphExecutor {
554576
let (data, width, height) = raster.to_flat_u8();
555577
responses.add(EyedropperToolMessage::PreviewImage { data, width, height });
556578
}
579+
NodeGraphUpdate::Thumbnails {
580+
responses: thumbnails,
581+
document_id: thumbnails_document,
582+
} => {
583+
if thumbnails_document == document_id {
584+
Self::receive_thumbnails(document, thumbnails, responses);
585+
}
586+
}
557587
}
558588
}
559589

560-
// An error leaves the later responses unapplied, but the runtime still dropped their thumbnails
590+
// An error leaves the later responses unapplied, but the runtime still dropped and rendered their thumbnails
561591
for response in results {
562-
if let NodeGraphUpdate::ExecutionResponse(execution_response) = response {
563-
if self.document_of_execution(execution_response.execution_id) == Some(document_id) {
564-
document.layers_in_view.forget_thumbnails(&execution_response.dropped_thumbnails, responses);
592+
match response {
593+
NodeGraphUpdate::ExecutionResponse(execution_response) => {
594+
if self.document_of_execution(execution_response.execution_id) == Some(document_id) {
595+
document.layers_in_view.forget_thumbnails(&execution_response.dropped_thumbnails, responses);
596+
}
597+
all_dropped_thumbnails.extend(execution_response.dropped_thumbnails);
598+
}
599+
NodeGraphUpdate::Thumbnails {
600+
responses: thumbnails,
601+
document_id: thumbnails_document,
602+
} if thumbnails_document == document_id => {
603+
Self::receive_thumbnails(document, thumbnails, responses);
565604
}
566-
all_dropped_thumbnails.extend(execution_response.dropped_thumbnails);
605+
_ => {}
567606
}
568607
}
569608

570609
all_dropped_thumbnails
571610
}
572611

612+
fn receive_thumbnails(document: &mut DocumentMessageHandler, thumbnails: VecDeque<FrontendMessage>, responses: &mut VecDeque<Message>) {
613+
for thumbnail in thumbnails {
614+
if let FrontendMessage::UpdateNodeThumbnail { id, value } = thumbnail {
615+
document.layers_in_view.receive_thumbnail(id, value, responses);
616+
}
617+
}
618+
}
619+
573620
/// The document an execution was submitted for, while it's still queued or pending.
574621
fn document_of_execution(&self, execution_id: u64) -> Option<DocumentId> {
575622
self.futures

0 commit comments

Comments
 (0)