Skip to content

Commit 5a306a3

Browse files
committed
target initial mouse click instead of node center
1 parent ebe0422 commit 5a306a3

2 files changed

Lines changed: 49 additions & 48 deletions

File tree

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

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ pub struct NodeGraphMessageHandler {
5858
/// Used to add a transaction for the first node move when dragging.
5959
/// Used to prevent entering a nested network if the node is dragged after double clicking
6060
node_has_moved_in_drag: bool,
61-
/// If dragging the selected nodes, this stores the current position of the node,
62-
/// plus a flag indicating if it has been dragged since the mousedown began.
61+
/// See DragStart for notes
6362
pub drag_start: Option<DragStart>,
6463
// Store the selected chain nodes on drag start so they can be reconnected if shaken
6564
pub drag_start_chain_nodes: Vec<NodeId>,
@@ -962,9 +961,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
962961

963962
// If this node is selected (whether from before or just now), prepare it for dragging
964963
if updated_selected.contains(&clicked_id) {
965-
let drag_start_position = IVec2::new((node_graph_point.x / 24.).round() as i32, (node_graph_point.y / 24.).round() as i32);
966-
967-
self.drag_start = Some(DragStart::No(drag_start_position));
964+
let Some(selected_top_left) = network_interface.selected_nodes_bounding_box(breadcrumb_network_path) else {
965+
log::error!("Could not get bbox in PointerDown");
966+
return;
967+
};
968+
self.drag_start = Some(DragStart::new(node_graph_point - selected_top_left[0]));
968969
let selected_chain_nodes = updated_selected
969970
.iter()
970971
.filter(|node_id| network_interface.is_chain(node_id, selection_network_path))
@@ -1097,28 +1098,19 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
10971098
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: Some(wire_path) });
10981099
}
10991100
} else if let Some(drag_start) = &mut self.drag_start {
1100-
match drag_start {
1101-
DragStart::Yes => {
1102-
sync_selected_node_position_with_mouse(network_interface, breadcrumb_network_path, point, responses);
1103-
}
1104-
DragStart::No(start) => {
1105-
let mouse_position_grid_space = IVec2::new((point.x / 24.).round() as i32, (point.y / 24.).round() as i32);
1106-
if *start != mouse_position_grid_space {
1107-
*drag_start = DragStart::Yes;
1108-
if ipp.keyboard.get(Key::Alt as usize) {
1109-
responses.add(NodeGraphMessage::DuplicateSelectedNodes);
1110-
// Duplicating sets a 2x2 offset, so shift the nodes back to the original position
1111-
responses.add(NodeGraphMessage::ShiftSelectedNodesByAmount {
1112-
graph_delta: IVec2::new(-2, -2),
1113-
rubber_band: false,
1114-
});
1115-
self.preview_on_mouse_up = None;
1116-
}
1117-
sync_selected_node_position_with_mouse(network_interface, breadcrumb_network_path, point, responses);
1118-
}
1101+
let moved = sync_selected_node_position_with_mouse(network_interface, breadcrumb_network_path, drag_start, point, responses);
1102+
if !drag_start.dragged && moved {
1103+
drag_start.dragged = true;
1104+
if ipp.keyboard.get(Key::Alt as usize) {
1105+
responses.add(NodeGraphMessage::DuplicateSelectedNodes);
1106+
// Duplicating sets a 2x2 offset, so shift the nodes back to the original position
1107+
responses.add(NodeGraphMessage::ShiftSelectedNodesByAmount {
1108+
graph_delta: IVec2::new(-2, -2),
1109+
rubber_band: false,
1110+
});
1111+
self.preview_on_mouse_up = None;
11191112
}
1120-
};
1121-
1113+
}
11221114
self.update_node_graph_hints(responses);
11231115
} else if let Some((_, box_selection_dragged)) = &mut self.box_selection_start {
11241116
*box_selection_dragged = true;
@@ -1187,7 +1179,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
11871179
self.preview_on_mouse_up = None;
11881180
}
11891181
if let Some(node_to_deselect) = self.deselect_on_pointer_up.take()
1190-
&& self.drag_start.as_ref().is_some_and(|start| !start.dragged())
1182+
&& self.drag_start.as_ref().is_some_and(|start| !start.dragged)
11911183
{
11921184
let mut new_selected_nodes = selected_nodes.selected_nodes_ref().clone();
11931185
new_selected_nodes.remove(node_to_deselect);
@@ -1263,7 +1255,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
12631255

12641256
// Only select clicked node if multiple are selected and they were not dragged
12651257
if let Some(select_if_not_dragged) = self.select_if_not_dragged {
1266-
if !drag_start.dragged()
1258+
if !drag_start.dragged
12671259
&& (selected_nodes.selected_nodes_ref().len() != 1
12681260
|| selected_nodes
12691261
.selected_nodes_ref()
@@ -1292,7 +1284,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
12921284
return;
12931285
};
12941286
// Check if a single node was dragged onto a wire and that the node was dragged onto the wire
1295-
if selected_nodes.selected_nodes_ref().len() == 1 && self.drag_start.as_ref().is_some_and(|drag_start| drag_start.dragged()) {
1287+
if selected_nodes.selected_nodes_ref().len() == 1 && self.drag_start.as_ref().is_some_and(|drag_start| drag_start.dragged) {
12961288
let selected_node_id = selected_nodes.selected_nodes_ref()[0];
12971289
let has_primary_output_connection = network_interface
12981290
.outward_wires(selection_network_path)
@@ -1546,7 +1538,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
15461538
}
15471539
}
15481540
}
1549-
sync_selected_node_position_with_mouse(network_interface, breadcrumb_network_path, point, responses);
1541+
if let Some(drag_start) = self.drag_start.as_ref() {
1542+
sync_selected_node_position_with_mouse(network_interface, breadcrumb_network_path, drag_start, point, responses);
1543+
}
15501544
responses.add(NodeGraphMessage::RunDocumentGraph);
15511545
responses.add(NodeGraphMessage::SendGraph);
15521546
}
@@ -2725,7 +2719,7 @@ impl NodeGraphMessageHandler {
27252719
let wiring = self.wire_in_progress_from_connector.is_some();
27262720

27272721
// Node dragging is in progress (having already moved at least one pixel from the mouse down position)
2728-
let dragging_nodes = self.drag_start.as_ref().is_some_and(|drag_start| drag_start.dragged());
2722+
let dragging_nodes = self.drag_start.as_ref().is_some_and(|drag_start| drag_start.dragged);
27292723

27302724
// A box selection is in progress
27312725
let dragging_box_selection = self.box_selection_start.is_some_and(|(_, box_selection_dragged)| box_selection_dragged);
@@ -2811,19 +2805,23 @@ impl PartialEq for NodeGraphMessageHandler {
28112805
}
28122806
}
28132807

2814-
fn sync_selected_node_position_with_mouse(network_interface: &mut NodeNetworkInterface, breadcrumb_network_path: &[NodeId], mouse_position_node_graph_space: DVec2, responses: &mut VecDeque<Message>) {
2815-
let mouse_position_grid_space = IVec2::new((mouse_position_node_graph_space.x / 24.).round() as i32, (mouse_position_node_graph_space.y / 24.).round() as i32);
2816-
2808+
/// Returns whether the nodes have been moved
2809+
fn sync_selected_node_position_with_mouse(
2810+
network_interface: &mut NodeNetworkInterface,
2811+
breadcrumb_network_path: &[NodeId],
2812+
drag_start: &DragStart,
2813+
mouse_position_node_graph_space: DVec2,
2814+
responses: &mut VecDeque<Message>,
2815+
) -> bool {
28172816
let Some(selected_nodes_bbox) = network_interface.selected_nodes_bounding_box(breadcrumb_network_path) else {
28182817
log::error!("Could not get selected_nodes_bounding_box when dragging");
2819-
return;
2818+
return false;
28202819
};
2821-
let mut selected_nodes_center = (selected_nodes_bbox[0] + selected_nodes_bbox[1]) / 2.;
2822-
// Add 1 to correct for floating point errors
2823-
selected_nodes_center += DVec2::ONE;
2824-
let selected_nodes_center_grid_space = IVec2::new((selected_nodes_center.x / 24.).round() as i32, (selected_nodes_center.y / 24.).round() as i32);
2825-
let graph_delta = mouse_position_grid_space - selected_nodes_center_grid_space;
2820+
let mut target_center = selected_nodes_bbox[0] + drag_start.drag_start_offset;
2821+
let offset = mouse_position_node_graph_space - target_center;
2822+
let graph_delta = IVec2::new((offset.x / 24.).round() as i32, (offset.y / 24.).round() as i32);
28262823
if graph_delta != IVec2::ZERO {
28272824
responses.add(NodeGraphMessage::ShiftSelectedNodesByAmount { graph_delta, rubber_band: true });
2828-
}
2825+
};
2826+
graph_delta != IVec2::ZERO
28292827
}

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,20 @@ pub struct FrontendNodeType {
110110
pub input_types: Vec<String>,
111111
}
112112

113-
/// State to represent the grid space coordinate from which the pointer started the drag
114-
/// Once the nodes have been dragged, it is toggled to the Yes variant
113+
/// If dragging the selected nodes, this stores the coordinate of the click relative to the top left selected node.
114+
/// Once the nodes have been dragged, it is toggled to the Yes variant.
115115
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
116-
pub enum DragStart {
117-
Yes,
118-
No(IVec2),
116+
pub struct DragStart {
117+
pub drag_start_offset: DVec2,
118+
pub dragged: bool,
119119
}
120120

121121
impl DragStart {
122-
pub fn dragged(&self) -> bool {
123-
matches!(self, DragStart::Yes)
122+
pub fn new(drag_start: DVec2) -> Self {
123+
DragStart {
124+
drag_start_offset: drag_start,
125+
dragged: false,
126+
}
124127
}
125128
}
126129

0 commit comments

Comments
 (0)