diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 6402f609fd..21bedacc8b 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1496,8 +1496,9 @@ impl MessageHandler> for DocumentMes if !self.graph_view_overlay_open { let transform = self.navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), &self.document_ptz); self.network_interface.set_document_to_viewport_transform(transform); - // Ensure selection box is kept in sync with the pointer when the PTZ changes - responses.add(SelectToolMessage::PointerMove { + // Ensure dragging operations are kept in sync with the pointer when the PTZ changes + // Using DocumentPTZUpdate allows tools to recalculate viewport positions from document-space + responses.add(SelectToolMessage::DocumentPTZUpdate { modifier_keys: SelectToolPointerKeys { axis_align: Key::Shift, snap_angle: Key::Shift, diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 717903ab10..7ef47aa5a8 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -2,7 +2,7 @@ use super::tool_prelude::*; use crate::consts::*; -use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; +use crate::messages::input_mapper::utility_types::input_mouse::{DocumentPosition, ViewportPosition}; use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; @@ -116,6 +116,10 @@ pub enum SelectToolMessage { offset: Option, flush: bool, }, + /// Called when PTZ (Pan/Tilt/Zoom) changes occur to update viewport-space positions + DocumentPTZUpdate { + modifier_keys: SelectToolPointerKeys, + }, } impl ToolMetadata for SelectTool { @@ -378,6 +382,8 @@ impl Default for SelectToolFsmState { struct SelectToolData { drag_start: ViewportPosition, drag_current: ViewportPosition, + /// Document-space position of drag start, used to maintain correct positions during PTZ changes + drag_start_document: DocumentPosition, lasso_polygon: Vec, selection_mode: Option, layers_dragging: Vec, // Unordered, often used as temporary buffer @@ -1023,6 +1029,8 @@ impl Fsm for SelectToolFsmState { ) => { tool_data.drag_start = input.mouse.position; tool_data.drag_current = input.mouse.position; + // Store drag start in document space to handle PTZ changes during dragging + tool_data.drag_start_document = document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position); tool_data.selection_mode = None; let mut selected: Vec<_> = document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface).collect(); @@ -1393,6 +1401,39 @@ impl Fsm for SelectToolFsmState { state } + // Handle PTZ (Pan/Tilt/Zoom) updates during dragging operations + ( + SelectToolFsmState::Dragging { + axis, + using_compass, + has_dragged, + deepest, + remove, + }, + SelectToolMessage::DocumentPTZUpdate { modifier_keys }, + ) => { + // Recalculate drag_start in viewport space from the stored document-space position + let new_drag_start = document.metadata().document_to_viewport.transform_point2(tool_data.drag_start_document); + let shift = new_drag_start - tool_data.drag_start; + tool_data.drag_start = new_drag_start; + tool_data.drag_current += shift; + + // Trigger a PointerMove to update the layer positions + responses.add(SelectToolMessage::PointerMove { modifier_keys }); + + SelectToolFsmState::Dragging { + axis, + using_compass, + has_dragged, + deepest, + remove, + } + } + // For non-dragging states, just trigger a PointerMove + (state, SelectToolMessage::DocumentPTZUpdate { modifier_keys }) => { + responses.add(SelectToolMessage::PointerMove { modifier_keys }); + state + } (SelectToolFsmState::Dragging { has_dragged, remove, deepest, .. }, SelectToolMessage::DragStop { remove_from_selection }) => { // Deselect layer if not snap dragging responses.add(DocumentMessage::EndTransaction);