Migrate node graph UI interaction from frontend to backend (#1768)

* Click node using click targets based

* Display graph transform based on state stored in Rust, fix zoom and pan.

* Migrate node selection logic

* Move click targets and transform to NodeNetwork

* Keep click targets in sync with changes to node shape

* Click targets for import/export, add dragging

* Basic wire dragging

* complete wire dragging

* Add node selection box when dragging

* Fix zoom operations and dragging nodes

* Remove click targets from serialized data, fix EnterNestedNetwork

* WIP: Auto connect node when dragged on wire

* Finish auto connect node when dragged on wire

* Add context menus

* Improve layer width calculations and state

* Improve context menu state, various other improvements

* Close menu on escape

* Cleanup Graph.svelte

* Fix lock/hide tool tip shortcuts

* Clean up editor_api.rs, fix lock/hide layers

* Start transferring network and node metadata from NodeNetwork to the editor

* Transfer click targets to NodeGraphMessageHandler

* Fix infinite canvas

* Fix undo/redo, scrollbars, and fix warnings

* Unicode-3.0 license and code cleanup

* License fix

* formatting issue

* Enable DomRect

* Fix layer move crash

* Remove tests

* Ignore test

* formatting

* remove white dot

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
adamgerhant 2024-06-15 08:55:33 -07:00 committed by GitHub
parent cf01f522a8
commit 02360c7bc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 2744 additions and 1257 deletions

View file

@ -551,87 +551,12 @@ impl EditorHandle {
self.dispatch(message);
}
/// Notifies the backend that the user connected a node's primary output to one of another node's inputs
#[wasm_bindgen(js_name = connectNodesByWire)]
pub fn connect_nodes_by_wire(&self, output_node: u64, output_node_connector_index: usize, input_node: u64, input_node_connector_index: usize) {
let output_node = NodeId(output_node);
let input_node = NodeId(input_node);
let message = NodeGraphMessage::ConnectNodesByWire {
output_node,
output_node_connector_index,
input_node,
input_node_connector_index,
};
self.dispatch(message);
}
/// Inserts node in-between two other nodes
#[wasm_bindgen(js_name = insertNodeBetween)]
pub fn insert_node_between(
&self,
post_node_id: u64,
post_node_input_index: usize,
insert_node_output_index: usize,
insert_node_id: u64,
insert_node_input_index: usize,
pre_node_output_index: usize,
pre_node_id: u64,
) {
let message = NodeGraphMessage::InsertNodeBetween {
post_node_id: NodeId(post_node_id),
post_node_input_index,
insert_node_output_index,
insert_node_id: NodeId(insert_node_id),
insert_node_input_index,
pre_node_output_index,
pre_node_id: NodeId(pre_node_id),
};
self.dispatch(message);
}
/// Shifts the node and its children to stop nodes going on top of each other
#[wasm_bindgen(js_name = shiftNode)]
pub fn shift_node(&self, node_id: u64) {
let node_id = NodeId(node_id);
let message = NodeGraphMessage::ShiftNode { node_id };
self.dispatch(message);
}
/// Notifies the backend that the user disconnected a node
#[wasm_bindgen(js_name = disconnectNodes)]
pub fn disconnect_nodes(&self, node_id: u64, input_index: usize) {
let node_id = NodeId(node_id);
let message = NodeGraphMessage::DisconnectInput { node_id, input_index };
self.dispatch(message);
}
/// Check for intersections between the curve and a rectangle defined by opposite corners
#[wasm_bindgen(js_name = rectangleIntersects)]
pub fn rectangle_intersects(&self, bezier_x: Vec<f64>, bezier_y: Vec<f64>, top: f64, left: f64, bottom: f64, right: f64) -> bool {
let bezier = bezier_rs::Bezier::from_cubic_dvec2(
(bezier_x[0], bezier_y[0]).into(),
(bezier_x[1], bezier_y[1]).into(),
(bezier_x[2], bezier_y[2]).into(),
(bezier_x[3], bezier_y[3]).into(),
);
!bezier.rectangle_intersections((left, top).into(), (right, bottom).into()).is_empty() || bezier.is_contained_within((left, top).into(), (right, bottom).into())
}
/// Creates a new document node in the node graph
#[wasm_bindgen(js_name = createNode)]
pub fn create_node(&self, node_type: String, x: i32, y: i32) -> u64 {
pub fn create_node(&self, node_type: String, x: i32, y: i32) {
let id = NodeId(generate_uuid());
let message = NodeGraphMessage::CreateNode { node_id: Some(id), node_type, x, y };
self.dispatch(message);
id.0
}
/// Notifies the backend that the user selected a node in the node graph
#[wasm_bindgen(js_name = selectNodes)]
pub fn select_nodes(&self, nodes: Vec<u64>) {
let nodes = nodes.into_iter().map(NodeId).collect::<Vec<_>>();
let message = NodeGraphMessage::SelectedNodesSet { nodes };
self.dispatch(message);
}
/// Pastes the nodes based on serialized data
@ -641,14 +566,6 @@ impl EditorHandle {
self.dispatch(message);
}
/// Notifies the backend that the user double clicked a node
#[wasm_bindgen(js_name = enterNestedNetwork)]
pub fn enter_nested_network(&self, node: u64) {
let node = NodeId(node);
let message = NodeGraphMessage::EnterNestedNetwork { node };
self.dispatch(message);
}
/// Go back a certain number of nested levels
#[wasm_bindgen(js_name = exitNestedNetwork)]
pub fn exit_nested_network(&self, steps_back: usize) {
@ -656,24 +573,6 @@ impl EditorHandle {
self.dispatch(message);
}
/// Notifies the backend that the selected nodes have been moved
#[wasm_bindgen(js_name = moveSelectedNodes)]
pub fn move_selected_nodes(&self, displacement_x: i32, displacement_y: i32) {
let message = DocumentMessage::StartTransaction;
self.dispatch(message);
let message = NodeGraphMessage::MoveSelectedNodes { displacement_x, displacement_y };
self.dispatch(message);
}
/// Toggle preview on node
#[wasm_bindgen(js_name = togglePreview)]
pub fn toggle_preview(&self, node_id: u64) {
let node_id = NodeId(node_id);
let message = NodeGraphMessage::TogglePreview { node_id };
self.dispatch(message);
}
/// Pastes an image
#[wasm_bindgen(js_name = pasteImage)]
pub fn paste_image(&self, image_data: Vec<u8>, width: u32, height: u32, mouse_x: Option<f64>, mouse_y: Option<f64>) {
@ -698,14 +597,6 @@ impl EditorHandle {
self.dispatch(message);
}
/// Toggle visibility of a layer or node given its node ID
#[wasm_bindgen(js_name = toggleNodeVisibilityGraph)]
pub fn toggle_node_visibility_graph(&self, id: u64) {
let node_id = NodeId(id);
let message = NodeGraphMessage::ToggleVisibility { node_id };
self.dispatch(message);
}
/// Delete a layer or node given its node ID
#[wasm_bindgen(js_name = deleteNode)]
pub fn delete_node(&self, id: u64) {