Skip to content

Commit eee27a2

Browse files
committed
Node positions backend
1 parent cf69f45 commit eee27a2

File tree

7 files changed

+82
-8
lines changed

7 files changed

+82
-8
lines changed

editor/src/messages/portfolio/document/node_graph/node_graph_message.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ pub enum NodeGraphMessage {
2121
DeleteNode {
2222
node_id: NodeId,
2323
},
24+
MoveSelectedNodes {
25+
displacement_x: i32,
26+
displacement_y: i32,
27+
},
2428
OpenNodeGraph {
2529
layer_path: Vec<graphene::LayerId>,
2630
},

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
use crate::messages::layout::utility_types::layout_widget::LayoutGroup;
22
use crate::messages::prelude::*;
3-
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork};
3+
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, DocumentNodeMetadata, NodeInput, NodeNetwork};
44
use graphene::document::Document;
55
use graphene::layers::layer_info::LayerDataType;
66
use graphene::layers::nodegraph_layer::NodeGraphFrameLayer;
77

88
mod document_node_types;
99
mod node_properties;
1010

11+
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
12+
pub enum DataType {
13+
Raster,
14+
}
15+
1116
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
1217
pub struct FrontendNode {
1318
pub id: graph_craft::document::NodeId,
1419
#[serde(rename = "displayName")]
1520
pub display_name: String,
21+
#[serde(rename = "exposedInputs")]
22+
pub exposed_inputs: Vec<DataType>,
23+
pub outputs: Vec<DataType>,
24+
pub position: (i32, i32),
1625
}
1726

1827
// (link_start, link_end, link_end_input_index)
@@ -92,6 +101,9 @@ impl NodeGraphMessageHandler {
92101
nodes.push(FrontendNode {
93102
id: *id,
94103
display_name: node.name.clone(),
104+
exposed_inputs: node.inputs.iter().filter(|input| input.is_exposed()).map(|_| DataType::Raster).collect(),
105+
outputs: vec![DataType::Raster],
106+
position: node.metadata.position,
95107
})
96108
}
97109
log::debug!("Nodes:\n{:#?}\n\nFrontend Nodes:\n{:#?}\n\nLinks:\n{:#?}", network.nodes, nodes, links);
@@ -159,6 +171,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
159171
// TODO: Allow inserting nodes that contain other nodes.
160172
implementation: DocumentNodeImplementation::Unresolved(document_node_type.identifier.clone()),
161173
inputs: (0..num_inputs).map(|_| NodeInput::Network).collect(),
174+
metadata: DocumentNodeMetadata::default(),
162175
},
163176
)]
164177
.into_iter()
@@ -171,6 +184,10 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
171184
inputs: document_node_type.default_inputs.to_vec(),
172185
// TODO: Allow inserting nodes that contain other nodes.
173186
implementation: DocumentNodeImplementation::Network(inner_network),
187+
metadata: graph_craft::document::DocumentNodeMetadata {
188+
// TODO: Better position default
189+
position: (node_id as i32 * 7 - 41, node_id as i32 * 2 - 10),
190+
},
174191
},
175192
);
176193
Self::send_graph(network, responses);
@@ -181,6 +198,19 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
181198
Self::send_graph(network, responses);
182199
}
183200
}
201+
NodeGraphMessage::MoveSelectedNodes { displacement_x, displacement_y } => {
202+
let Some(network) = self.get_active_network_mut(document) else{
203+
warn!("No network");
204+
return;
205+
};
206+
207+
for node_id in &self.selected_nodes {
208+
if let Some(node) = network.nodes.get_mut(node_id) {
209+
node.metadata.position.0 += displacement_x;
210+
node.metadata.position.1 += displacement_y;
211+
}
212+
}
213+
}
184214
NodeGraphMessage::OpenNodeGraph { layer_path } => {
185215
if let Some(_old_layer_path) = self.layer_path.replace(layer_path) {
186216
// TODO: Necessary cleanup of old node graph

frontend/src/components/panels/NodeGraph.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
class="node"
3636
:class="{ selected: selected.includes(node.id) }"
3737
:style="{
38-
'--offset-left': 8 + Number(node.id < 9n ? node.id : node.id - 7n) * 7,
39-
'--offset-top': 4 + Number(node.id < 9n ? node.id : node.id - 7n) * 2,
38+
'--offset-left': node.position?.x || 0,
39+
'--offset-top': node.position?.y || 0,
4040
'--data-color': 'var(--color-data-raster)',
4141
'--data-color-dim': 'var(--color-data-raster-dim)',
4242
}"

frontend/src/wasm-communication/messages.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ export class JsMessage {
1212
static readonly jsMessageMarker = true;
1313
}
1414

15+
const TupleToVec2 = Transform(({ value }: { value: [number, number] | undefined }) => (value === undefined ? undefined : { x: value[0], y: value[1] }));
16+
const BigIntTupleToVec2 = Transform(({ value }: { value: [bigint, bigint] | undefined }) => (value === undefined ? undefined : { x: Number(value[0]), y: Number(value[1]) }));
17+
18+
export type XY = { x: number; y: number };
19+
1520
// ============================================================================
1621
// Add additional classes below to replicate Rust's `FrontendMessage`s and data structures.
1722
//
@@ -64,10 +69,19 @@ export class FrontendDocumentDetails extends DocumentDetails {
6469
readonly id!: bigint;
6570
}
6671

72+
export type DataType = "Raster" | "Color" | "Image" | "F32";
73+
6774
export class FrontendNode {
6875
readonly id!: bigint;
6976

7077
readonly displayName!: string;
78+
79+
readonly exposedInputs!: DataType[];
80+
81+
readonly outputs!: DataType[];
82+
83+
@TupleToVec2
84+
readonly position!: XY | undefined;
7185
}
7286

7387
export class FrontendNodeLink {
@@ -403,11 +417,6 @@ export class UpdateDocumentArtboards extends JsMessage {
403417
readonly svg!: string;
404418
}
405419

406-
const TupleToVec2 = Transform(({ value }: { value: [number, number] | undefined }) => (value === undefined ? undefined : { x: value[0], y: value[1] }));
407-
const BigIntTupleToVec2 = Transform(({ value }: { value: [bigint, bigint] | undefined }) => (value === undefined ? undefined : { x: Number(value[0]), y: Number(value[1]) }));
408-
409-
export type XY = { x: number; y: number };
410-
411420
export class UpdateDocumentScrollbars extends JsMessage {
412421
@TupleToVec2
413422
readonly position!: XY;

frontend/wasm/src/editor_api.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,13 @@ impl JsEditorHandle {
575575
self.dispatch(message);
576576
}
577577

578+
/// Notifies the backend that the selected nodes have been moved
579+
#[wasm_bindgen(js_name = moveSelectedNodes)]
580+
pub fn move_selected_nodes(&self, displacement_x: i32, displacement_y: i32) {
581+
let message = NodeGraphMessage::MoveSelectedNodes { displacement_x, displacement_y };
582+
self.dispatch(message);
583+
}
584+
578585
/// Pastes an image
579586
#[wasm_bindgen(js_name = pasteImage)]
580587
pub fn paste_image(&self, mime: String, image_data: Vec<u8>, mouse_x: Option<f64>, mouse_y: Option<f64>) {

graphene/src/layers/nodegraph_layer.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ impl Default for NodeGraphFrameLayer {
131131
"graphene_std::raster::BrightenImageNode",
132132
&[graph_craft::proto::Type::Concrete(std::borrow::Cow::Borrowed("&TypeErasedNode"))],
133133
)),
134+
metadata: DocumentNodeMetadata::default(),
134135
},
135136
)]
136137
.into_iter()
@@ -149,6 +150,7 @@ impl Default for NodeGraphFrameLayer {
149150
"graphene_std::raster::HueShiftImage",
150151
&[graph_craft::proto::Type::Concrete(std::borrow::Cow::Borrowed("&TypeErasedNode"))],
151152
)),
153+
metadata: DocumentNodeMetadata::default(),
152154
},
153155
)]
154156
.into_iter()
@@ -167,6 +169,7 @@ impl Default for NodeGraphFrameLayer {
167169
name: "Input".into(),
168170
inputs: vec![NodeInput::Network],
169171
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode", &[Type::Generic])),
172+
metadata: DocumentNodeMetadata { position: (8, 4) },
170173
},
171174
),
172175
(
@@ -181,6 +184,7 @@ impl Default for NodeGraphFrameLayer {
181184
},
182185
],
183186
implementation: DocumentNodeImplementation::Network(hue_shift_network),
187+
metadata: DocumentNodeMetadata { position: (8 + 7, 4 + 2) },
184188
},
185189
),
186190
(
@@ -195,6 +199,7 @@ impl Default for NodeGraphFrameLayer {
195199
},
196200
],
197201
implementation: DocumentNodeImplementation::Network(brighten_network),
202+
metadata: DocumentNodeMetadata { position: (8 + 7 * 2, 4 + 2 * 2) },
198203
},
199204
),
200205
(
@@ -203,6 +208,7 @@ impl Default for NodeGraphFrameLayer {
203208
name: "Output".into(),
204209
inputs: vec![NodeInput::Node(2)],
205210
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode", &[Type::Generic])),
211+
metadata: DocumentNodeMetadata { position: (8 + 7 * 3, 4) },
206212
},
207213
),
208214
]

node-graph/graph-craft/src/document.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@ fn merge_ids(a: u64, b: u64) -> u64 {
2828
hasher.finish()
2929
}
3030

31+
#[derive(Clone, Debug, PartialEq, Default)]
32+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33+
pub struct DocumentNodeMetadata {
34+
pub position: (i32, i32),
35+
}
36+
3137
#[derive(Clone, Debug, PartialEq)]
3238
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3339
pub struct DocumentNode {
3440
pub name: String,
3541
pub inputs: Vec<NodeInput>,
3642
pub implementation: DocumentNodeImplementation,
43+
pub metadata: DocumentNodeMetadata,
3744
}
3845

3946
impl DocumentNode {
@@ -183,6 +190,7 @@ impl NodeNetwork {
183190
name: name.clone(),
184191
inputs: vec![NodeInput::Value { tagged_value, exposed }],
185192
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::value::ValueNode", &[Type::Generic])),
193+
metadata: DocumentNodeMetadata::default(),
186194
};
187195
assert!(!self.nodes.contains_key(&new_id));
188196
self.nodes.insert(new_id, value_node);
@@ -245,6 +253,7 @@ mod test {
245253
name: "Cons".into(),
246254
inputs: vec![NodeInput::Network, NodeInput::Network],
247255
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::structural::ConsNode", &[Type::Generic, Type::Generic])),
256+
metadata: DocumentNodeMetadata::default(),
248257
},
249258
),
250259
(
@@ -253,6 +262,7 @@ mod test {
253262
name: "Add".into(),
254263
inputs: vec![NodeInput::Node(0)],
255264
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::AddNode", &[Type::Generic, Type::Generic])),
265+
metadata: DocumentNodeMetadata::default(),
256266
},
257267
),
258268
]
@@ -275,6 +285,7 @@ mod test {
275285
name: "Cons".into(),
276286
inputs: vec![NodeInput::Network, NodeInput::Network],
277287
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::structural::ConsNode", &[Type::Generic, Type::Generic])),
288+
metadata: DocumentNodeMetadata::default(),
278289
},
279290
),
280291
(
@@ -283,6 +294,7 @@ mod test {
283294
name: "Add".into(),
284295
inputs: vec![NodeInput::Node(1)],
285296
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::AddNode", &[Type::Generic, Type::Generic])),
297+
metadata: DocumentNodeMetadata::default(),
286298
},
287299
),
288300
]
@@ -309,6 +321,7 @@ mod test {
309321
},
310322
],
311323
implementation: DocumentNodeImplementation::Network(add_network()),
324+
metadata: DocumentNodeMetadata::default(),
312325
},
313326
)]
314327
.into_iter()
@@ -328,6 +341,7 @@ mod test {
328341
name: "Cons".into(),
329342
inputs: vec![NodeInput::Network, NodeInput::Node(0)],
330343
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::structural::ConsNode", &[Type::Generic, Type::Generic])),
344+
metadata: DocumentNodeMetadata::default(),
331345
};
332346

333347
let proto_node = document_node.resolve_proto_node();
@@ -393,6 +407,7 @@ mod test {
393407
name: "Inc".into(),
394408
inputs: vec![NodeInput::Node(11)],
395409
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode", &[Type::Generic])),
410+
metadata: DocumentNodeMetadata::default(),
396411
},
397412
),
398413
(
@@ -401,6 +416,7 @@ mod test {
401416
name: "Cons".into(),
402417
inputs: vec![NodeInput::Network, NodeInput::Node(14)],
403418
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::structural::ConsNode", &[Type::Generic, Type::Generic])),
419+
metadata: DocumentNodeMetadata::default(),
404420
},
405421
),
406422
(
@@ -412,6 +428,7 @@ mod test {
412428
exposed: false,
413429
}],
414430
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::value::ValueNode", &[Type::Generic])),
431+
metadata: DocumentNodeMetadata::default(),
415432
},
416433
),
417434
(
@@ -420,6 +437,7 @@ mod test {
420437
name: "Add".into(),
421438
inputs: vec![NodeInput::Node(10)],
422439
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::AddNode", &[Type::Generic, Type::Generic])),
440+
metadata: DocumentNodeMetadata::default(),
423441
},
424442
),
425443
]

0 commit comments

Comments
 (0)