Skip to content

Migrate node graph UI interaction from frontend to backend #1768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jun 15, 2024
Merged
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d435ec6
Click node using click targets based
adamgerhant Jun 3, 2024
4748778
Display graph transform based on state stored in Rust, fix zoom and pan.
adamgerhant Jun 4, 2024
1072676
Migrate node selection logic
adamgerhant Jun 4, 2024
8306115
Move click targets and transform to NodeNetwork
adamgerhant Jun 5, 2024
f7b7da8
Keep click targets in sync with changes to node shape
adamgerhant Jun 6, 2024
115b6eb
Click targets for import/export, add dragging
adamgerhant Jun 7, 2024
ba1c26f
Basic wire dragging
adamgerhant Jun 7, 2024
06ff4a1
complete wire dragging
adamgerhant Jun 8, 2024
6501ef6
Add node selection box when dragging
adamgerhant Jun 8, 2024
8f2b0e7
Fix zoom operations and dragging nodes
adamgerhant Jun 9, 2024
d6f1489
Remove click targets from serialized data, fix EnterNestedNetwork
adamgerhant Jun 11, 2024
a8f1835
WIP: Auto connect node when dragged on wire
adamgerhant Jun 11, 2024
d1a0781
Finish auto connect node when dragged on wire
adamgerhant Jun 11, 2024
14280bf
Add context menus
adamgerhant Jun 12, 2024
27e1b5c
Improve layer width calculations and state
adamgerhant Jun 12, 2024
b23c97b
Improve context menu state, various other improvements
adamgerhant Jun 13, 2024
64193c4
Close menu on escape
adamgerhant Jun 13, 2024
0d71c48
Cleanup Graph.svelte
adamgerhant Jun 13, 2024
ae9e15f
Fix lock/hide tool tip shortcuts
adamgerhant Jun 13, 2024
66ad713
Clean up editor_api.rs, fix lock/hide layers
adamgerhant Jun 13, 2024
1cacd4a
Start transferring network and node metadata from NodeNetwork to the …
adamgerhant Jun 13, 2024
d4ac501
Transfer click targets to NodeGraphMessageHandler
adamgerhant Jun 14, 2024
eb8d98c
Fix infinite canvas
adamgerhant Jun 14, 2024
eb82961
Fix undo/redo, scrollbars, and fix warnings
adamgerhant Jun 14, 2024
eed7592
Unicode-3.0 license and code cleanup
adamgerhant Jun 14, 2024
15cdeb2
License fix
adamgerhant Jun 14, 2024
0f6d72b
formatting issue
adamgerhant Jun 14, 2024
09b7064
Enable DomRect
adamgerhant Jun 14, 2024
c4bda8c
Fix layer move crash
adamgerhant Jun 15, 2024
facec9d
Remove tests
adamgerhant Jun 15, 2024
694b2fa
Ignore test
adamgerhant Jun 15, 2024
f27f83e
formatting
adamgerhant Jun 15, 2024
e1985d7
remove white dot
adamgerhant Jun 15, 2024
59c56fd
Merge branch 'master' into node-graph-transfer
Keavon Jun 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Finish auto connect node when dragged on wire
  • Loading branch information
adamgerhant committed Jun 11, 2024
commit d1a07815624e156dd975a9ccd861ef65c7fe469e
Original file line number Diff line number Diff line change
Expand Up @@ -859,12 +859,12 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if selected_nodes.selected_nodes_ref().len() == 1 {
let selected_node_id = selected_nodes.selected_nodes_ref()[0];
// Check that neither the primary input or output of the selected node are already connected.
let Some(node) = network.nodes.get(&selected_node_id) else {
let Some(selected_node) = network.nodes.get(&selected_node_id) else {
log::error!("Could not get selected node from network");
return;
};
// Check if primary input is disconnected
if node.inputs.get(0).is_some_and(|first_input| first_input.as_value().is_some()) {
if selected_node.inputs.get(0).is_some_and(|first_input| first_input.as_value().is_some()) {
let has_primary_output_connection = network.nodes.iter().flat_map(|(_, node)| node.inputs.iter()).any(|input| {
if let NodeInput::Node { node_id, output_index, .. } = input {
if *node_id == selected_node_id && *output_index == 0 {
Expand All @@ -879,15 +879,56 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
// Check if primary output is disconnected
if !has_primary_output_connection {
// TODO: Cache all wire locations. This will be difficult since there are many ways for an input to changes, and each change will have to update the cache
for frontend_wire in Self::collect_wires(network) {
let Some(bounding_box) = network.node_click_targets.get(&selected_node_id).and_then(|click_target| click_target.subpath.bounding_box()) else {
log::error!("Could not get bounding box for node: {selected_node_id}");
return;
};
let overlapping_wire = Self::collect_wires(network).into_iter().find(|frontend_wire| {
// Get positions in order to build wire positions and then use rectangleIntersects
let Some(node_position) = network
.nodes
.get(&frontend_wire.wire_end)
.map(|node| DVec2::new(node.metadata.position.x as f64 * 24., node.metadata.position.y as f64 * 24.))
else {
continue;
let (end_node_position, end_node_is_layer) = network.nodes.get(&frontend_wire.wire_end).map_or(
(DVec2::new(network.exports_metadata.1.x as f64 * 24., network.exports_metadata.1.y as f64 * 24. + 24.), false),
|node| (DVec2::new(node.metadata.position.x as f64 * 24., node.metadata.position.y as f64 * 24.), node.is_layer),
);
let (start_node_position, start_node_is_layer) = network.nodes.get(&frontend_wire.wire_start).map_or(
(DVec2::new(network.imports_metadata.1.x as f64 * 24., network.imports_metadata.1.y as f64 * 24. + 24.), false),
|node| (DVec2::new(node.metadata.position.x as f64 * 24., node.metadata.position.y as f64 * 24.), node.is_layer),
);

let input_position = if end_node_is_layer {
DVec2::new(end_node_position.x + 3. * 24., end_node_position.y + 2. * 24. + 12.)
} else {
DVec2::new(end_node_position.x, end_node_position.y + 24. + 24. * frontend_wire.wire_end_input_index as f64)
};

let output_position = if start_node_is_layer {
DVec2::new(start_node_position.x + 3. * 24., start_node_position.y - 12.)
} else {
DVec2::new(start_node_position.x + 5. * 24., start_node_position.y + 24. + 24. * frontend_wire.wire_start_output_index as f64)
};

let locations = Self::build_wire_path_locations(output_position, input_position, start_node_is_layer, end_node_is_layer);
let bezier = bezier_rs::Bezier::from_cubic_dvec2(
(locations[0].x, locations[0].y).into(),
(locations[1].x, locations[1].y).into(),
(locations[2].x, locations[2].y).into(),
(locations[3].x, locations[3].y).into(),
);

!bezier.rectangle_intersections(bounding_box[0], bounding_box[1]).is_empty() || bezier.is_contained_within(bounding_box[0], bounding_box[1])
});
if let Some(overlapping_wire) = overlapping_wire {
responses.add(NodeGraphMessage::InsertNodeBetween {
post_node_id: overlapping_wire.wire_end,
post_node_input_index: overlapping_wire.wire_end_input_index,
insert_node_output_index: 0,
insert_node_id: selected_node_id,
insert_node_input_index: 0,
pre_node_output_index: overlapping_wire.wire_start_output_index,
pre_node_id: overlapping_wire.wire_start,
});
if !selected_node.is_layer {
responses.add(NodeGraphMessage::ShiftNode { node_id: selected_node_id });
}
}
}
}
Expand Down