Skip to content

Commit 0dbbabe

Browse files
adamgerhantKeavonTrueDoctor
authored
Add layer node chains, import/export edge connectors, and refactor graph editing to go thru a NodeNetworkInterface (#1794)
* WIP: NodeNetworkInterface * Organize ModifyInputsContext to use network interface * Improve ClickTarget and Position state * Rework ClickTarget state * Continue fixing NodeGraphMessageHandler * Restructure network_metadata * Final(?) NodeNetworkInterface struct * Final(??) NodeNetworkInterface * Final(???) NodeNetworkInterface. Separated persistent and transient data * Final NodeNetworkInterface data structure. Implemented all basic getters * Continue migrating functionality to network interface * Migrate all NodeGraphMessage's to use network interface * Fix all helper functions in NodeGraphMessageHandler * Move document metadata to network interface, remove various cached fields * Move all editor only NodeNetwork implementations to NodeNetworkInterface * Fix all DocumentNodeDefinitions * Rework and migrate GraphOperationMessages to network interface * Continue migration to NodeNetworkInterface * Save point before merging master * Fix all errors in network_interface * 850 -> 160 errors * Fix all errors :D * Render default document * Visualize click targets * merge conflicts * Cache transient metadata separately, store entire interface in document history * Start migration to storing selected nodes for each network * Remove selected nodes from document message handler * Move outward wires and all nodes bounding box to transient metadata * Fix connecting/disconnecting nodes * Layer stack organization for disconnecting/connecting nodes * Basic chain locking * Improve chain positioning * Add copy/pasting * Move upstream nodes on shift+drag * merge conflict fixes * Improve Graph.svelte code quality * Final improvements to Graph.svelte * Fix layer panel * Performance optimizations * Bug fixes and derived PTZ * Chain organization improvement and bug fixes * Bug fixes, remove all warnings * Automatic file upgrade * Final code review * Fix editor tests * Fix compile errors * Remove select tool intersection check when panning * WIP: Import/Exports * Fix JS issues * Finish simplified import/export UI * Import/Export viewport edge UI * Remove minimum y bound on import/export ports * Improve performance while panning graph * cargo fmt * Fix CI code build * Format the demo artwork graph with chains * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: dennis@kobert.dev <dennis@kobert.dev>
1 parent ea44d14 commit 0dbbabe

File tree

77 files changed

+11230
-7880
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+11230
-7880
lines changed

demo-artwork/isometric-fountain.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/painted-dreams.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/procedural-string-lights.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/red-dress.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/valley-of-spires.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/consts.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Graph
2+
pub const GRID_SIZE: u32 = 24;
3+
14
// Viewport
25
pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.;
36
pub const VIEWPORT_ZOOM_MOUSE_RATE: f64 = 1. / 400.;

editor/src/dispatcher.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,10 @@ impl Dispatcher {
165165
self.message_handlers.preferences_message_handler.process_message(message, &mut queue, ());
166166
}
167167
Message::Tool(message) => {
168-
if let Some(document) = self.message_handlers.portfolio_message_handler.active_document() {
168+
let document_id = self.message_handlers.portfolio_message_handler.active_document_id().unwrap();
169+
if let Some(document) = self.message_handlers.portfolio_message_handler.documents.get_mut(&document_id) {
169170
let data = ToolMessageData {
170-
document_id: self.message_handlers.portfolio_message_handler.active_document_id().unwrap(),
171+
document_id,
171172
document,
172173
input: &self.message_handlers.input_preprocessor_message_handler,
173174
persistent_data: &self.message_handlers.portfolio_message_handler.persistent_data,
@@ -308,12 +309,12 @@ mod test {
308309
editor.handle_message(PortfolioMessage::PasteIntoFolder {
309310
clipboard: Clipboard::Internal,
310311
parent: LayerNodeIdentifier::ROOT_PARENT,
311-
insert_index: -1,
312+
insert_index: 0,
312313
});
313314
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
314315

315-
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
316-
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
316+
let layers_before_copy = document_before_copy.metadata().all_layers().collect::<Vec<_>>();
317+
let layers_after_copy = document_after_copy.metadata().all_layers().collect::<Vec<_>>();
317318

318319
assert_eq!(layers_before_copy.len(), 3);
319320
assert_eq!(layers_after_copy.len(), 4);
@@ -337,20 +338,20 @@ mod test {
337338
let mut editor = create_editor_with_three_layers();
338339

339340
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
340-
let shape_id = document_before_copy.metadata.all_layers().nth(1).unwrap();
341+
let shape_id = document_before_copy.metadata().all_layers().nth(1).unwrap();
341342

342343
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![shape_id.to_node()] });
343344
editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
344345
editor.handle_message(PortfolioMessage::PasteIntoFolder {
345346
clipboard: Clipboard::Internal,
346347
parent: LayerNodeIdentifier::ROOT_PARENT,
347-
insert_index: -1,
348+
insert_index: 0,
348349
});
349350

350351
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
351352

352-
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
353-
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
353+
let layers_before_copy = document_before_copy.metadata().all_layers().collect::<Vec<_>>();
354+
let layers_after_copy = document_after_copy.metadata().all_layers().collect::<Vec<_>>();
354355

355356
assert_eq!(layers_before_copy.len(), 3);
356357
assert_eq!(layers_after_copy.len(), 4);
@@ -376,7 +377,7 @@ mod test {
376377
let mut editor = create_editor_with_three_layers();
377378

378379
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
379-
let mut layers = document_before_copy.metadata.all_layers();
380+
let mut layers = document_before_copy.metadata().all_layers();
380381
let rect_id = layers.next().expect("rectangle");
381382
let shape_id = layers.next().expect("shape");
382383
let ellipse_id = layers.next().expect("ellipse");
@@ -385,23 +386,23 @@ mod test {
385386
nodes: vec![rect_id.to_node(), ellipse_id.to_node()],
386387
});
387388
editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
388-
editor.handle_message(DocumentMessage::DeleteSelectedLayers);
389+
editor.handle_message(NodeGraphMessage::DeleteSelectedNodes { reconnect: true });
389390
editor.draw_rect(0., 800., 12., 200.);
390391
editor.handle_message(PortfolioMessage::PasteIntoFolder {
391392
clipboard: Clipboard::Internal,
392393
parent: LayerNodeIdentifier::ROOT_PARENT,
393-
insert_index: -1,
394+
insert_index: 0,
394395
});
395396
editor.handle_message(PortfolioMessage::PasteIntoFolder {
396397
clipboard: Clipboard::Internal,
397398
parent: LayerNodeIdentifier::ROOT_PARENT,
398-
insert_index: -1,
399+
insert_index: 0,
399400
});
400401

401402
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone();
402403

403-
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
404-
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
404+
let layers_before_copy = document_before_copy.metadata().all_layers().collect::<Vec<_>>();
405+
let layers_after_copy = document_after_copy.metadata().all_layers().collect::<Vec<_>>();
405406

406407
assert_eq!(layers_before_copy.len(), 3);
407408
assert_eq!(layers_after_copy.len(), 6);

editor/src/messages/dialog/dialog_message_handler.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,25 @@ impl MessageHandler<DialogMessage, DialogMessageData<'_>> for DialogMessageHandl
7070
DialogMessage::RequestExportDialog => {
7171
if let Some(document) = portfolio.active_document() {
7272
let artboards = document
73-
.metadata
73+
.metadata()
7474
.all_layers()
75-
.filter(|&layer| document.metadata.is_artboard(layer))
75+
.filter(|&layer| document.network_interface.is_artboard(&layer.to_node(), &[]))
7676
.map(|layer| {
7777
let name = document
78-
.network
79-
.nodes
80-
.get(&layer.to_node())
81-
.and_then(|node| if node.alias.is_empty() { None } else { Some(node.alias.clone()) })
78+
.network_interface
79+
.node_metadata(&layer.to_node(), &[])
80+
.map(|node| node.persistent_metadata.display_name.clone())
81+
.and_then(|name| if name.is_empty() { None } else { Some(name) })
8282
.unwrap_or_else(|| "Artboard".to_string());
8383
(layer, name)
8484
})
8585
.collect();
8686

8787
self.export_dialog.artboards = artboards;
88-
self.export_dialog.has_selection = document.selected_nodes.selected_layers(document.metadata()).next().is_some();
88+
self.export_dialog.has_selection = document
89+
.network_interface
90+
.selected_nodes(&[])
91+
.is_some_and(|selected_nodes| selected_nodes.selected_layers(document.metadata()).next().is_some());
8992
self.export_dialog.send_dialog_to_frontend(responses);
9093
}
9194
}

editor/src/messages/frontend/frontend_message.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
22
use crate::messages::layout::utility_types::widget_prelude::*;
3-
use crate::messages::portfolio::document::node_graph::utility_types::{BoxSelection, ContextMenuInformation, FrontendNode, FrontendNodeType, FrontendNodeWire, Transform, WirePath};
3+
use crate::messages::portfolio::document::node_graph::utility_types::{
4+
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeType, FrontendNodeWire, Transform, WirePath,
5+
};
46
use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
57
use crate::messages::prelude::*;
68
use crate::messages::tool::utility_types::HintData;
@@ -121,6 +123,14 @@ pub enum FrontendMessage {
121123
#[serde(rename = "documentId")]
122124
document_id: DocumentId,
123125
},
126+
UpdateImportsExports {
127+
imports: Vec<(FrontendGraphOutput, i32, i32)>,
128+
exports: Vec<(FrontendGraphInput, i32, i32)>,
129+
},
130+
UpdateInSelectedNetwork {
131+
#[serde(rename = "inSelectedNetwork")]
132+
in_selected_network: bool,
133+
},
124134
UpdateBox {
125135
#[serde(rename = "box")]
126136
box_selection: Option<BoxSelection>,
@@ -129,9 +139,15 @@ pub enum FrontendMessage {
129139
#[serde(rename = "contextMenuInformation")]
130140
context_menu_information: Option<ContextMenuInformation>,
131141
},
142+
UpdateClickTargets {
143+
#[serde(rename = "clickTargets")]
144+
click_targets: Option<FrontendClickTargets>,
145+
},
132146
UpdateLayerWidths {
133147
#[serde(rename = "layerWidths")]
134148
layer_widths: HashMap<NodeId, u32>,
149+
#[serde(rename = "chainWidths")]
150+
chain_widths: HashMap<NodeId, u32>,
135151
},
136152
UpdateDialogButtons {
137153
#[serde(rename = "layoutTarget")]

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ pub fn input_mappings() -> Mapping {
6969
entry!(KeyDown(KeyX); modifiers=[Accel], action_dispatch=NodeGraphMessage::Cut),
7070
entry!(KeyDown(KeyC); modifiers=[Accel], action_dispatch=NodeGraphMessage::Copy),
7171
entry!(KeyDown(KeyD); modifiers=[Accel], action_dispatch=NodeGraphMessage::DuplicateSelectedNodes),
72-
entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=GraphOperationMessage::ToggleSelectedVisibility),
73-
entry!(KeyDown(KeyL); modifiers=[Accel], action_dispatch=GraphOperationMessage::ToggleSelectedLocked),
72+
entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedVisibility),
73+
entry!(KeyDown(KeyL); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedLocked),
7474
entry!(KeyDown(KeyL); modifiers=[Alt], action_dispatch=NodeGraphMessage::ToggleSelectedAsLayersOrNodes),
7575
entry!(KeyDown(KeyC); modifiers=[Shift], action_dispatch=NodeGraphMessage::PrintSelectedNodeCoordinates),
76+
entry!(KeyDown(KeyC); modifiers=[Alt], action_dispatch=NodeGraphMessage::SendClickTargets),
77+
entry!(KeyUp(KeyC); action_dispatch=NodeGraphMessage::EndSendClickTargets),
7678
//
7779
// TransformLayerMessage
7880
entry!(KeyDown(Enter); action_dispatch=TransformLayerMessage::ApplyTransformOperation),

0 commit comments

Comments
 (0)