diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index 596b43af1..fcbb2558f 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -40,6 +40,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad), ]; +const DEBUG_MESSAGE_BLOCK_LIST: &[&str] = &["AnimationFrame", "PointerMove", "PointerOutsideViewport"]; impl Dispatcher { pub fn new() -> Self { @@ -224,7 +225,7 @@ impl Dispatcher { fn log_message(&self, message: &Message, queues: &[VecDeque], message_logging_verbosity: MessageLoggingVerbosity) { let message_name = MessageDiscriminant::from(message).local_name(); - if !(message_name.ends_with("PointerMove") || message_name.ends_with("AnimationFrame")) { + if !DEBUG_MESSAGE_BLOCK_LIST.iter().any(|blocked_name| message_name.ends_with(blocked_name)) { match message_logging_verbosity { MessageLoggingVerbosity::Off => {} MessageLoggingVerbosity::Names => { diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index c8f837349..aac778f1c 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -1,5 +1,6 @@ use super::tool_prelude::*; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::resize::Resize; @@ -55,6 +56,7 @@ pub enum EllipseToolMessage { DragStart, DragStop, PointerMove { center: Key, lock_ratio: Key }, + PointerOutsideViewport { center: Key, lock_ratio: Key }, UpdateOptions(EllipseOptionsUpdate), } @@ -173,6 +175,7 @@ enum EllipseToolFsmState { #[derive(Clone, Debug, Default)] struct EllipseToolData { data: Resize, + auto_panning: AutoPanning, } impl Fsm for EllipseToolFsmState { @@ -223,6 +226,13 @@ impl Fsm for EllipseToolFsmState { responses.add(message); } + // Auto-panning + let messages = [ + EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + EllipseToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + self } (_, EllipseToolMessage::PointerMove { .. }) => { @@ -230,6 +240,22 @@ impl Fsm for EllipseToolFsmState { responses.add(OverlaysMessage::Draw); self } + (EllipseToolFsmState::Drawing, EllipseToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + EllipseToolFsmState::Drawing + } + (state, EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }) => { + // Auto-panning + let messages = [ + EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + EllipseToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (EllipseToolFsmState::Drawing, EllipseToolMessage::DragStop) => { input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses); shape_data.cleanup(responses); diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index ed1748867..39d3ff2a5 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -2,6 +2,7 @@ use super::tool_prelude::*; use crate::consts::{LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD}; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::graph_modification_utils::get_gradient; use crate::messages::tool::common_functionality::snapping::SnapManager; @@ -31,6 +32,7 @@ pub enum GradientToolMessage { InsertStop, PointerDown, PointerMove { constrain_axis: Key }, + PointerOutsideViewport { constrain_axis: Key }, PointerUp, UpdateOptions(GradientOptionsUpdate), } @@ -225,6 +227,7 @@ struct GradientToolData { selected_gradient: Option, snap_manager: SnapManager, drag_start: DVec2, + auto_panning: AutoPanning, } impl Fsm for GradientToolFsmState { @@ -431,9 +434,36 @@ impl Fsm for GradientToolFsmState { let mouse = input.mouse.position; // tool_data.snap_manager.snap_position(responses, document, input.mouse.position); selected_gradient.update_gradient(mouse, responses, input.keyboard.get(constrain_axis as usize), selected_gradient.gradient.gradient_type); } + + // Auto-panning + let messages = [ + GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(), + GradientToolMessage::PointerMove { constrain_axis }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + GradientToolFsmState::Drawing } + (GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { + if let Some(selected_gradient) = &mut tool_data.selected_gradient { + selected_gradient.transform.translation += shift; + } + } + GradientToolFsmState::Drawing + } + (state, GradientToolMessage::PointerOutsideViewport { constrain_axis }) => { + // Auto-panning + let messages = [ + GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(), + GradientToolMessage::PointerMove { constrain_axis }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (GradientToolFsmState::Drawing, GradientToolMessage::PointerUp) => { input.mouse.finish_transaction(tool_data.drag_start, responses); tool_data.snap_manager.cleanup(responses); diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index 98c2c7641..dcfdf619a 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -2,6 +2,7 @@ use super::tool_prelude::*; use crate::consts::LINE_ROTATE_SNAP_ANGLE; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager}; @@ -44,6 +45,7 @@ pub enum LineToolMessage { DragStart, DragStop, PointerMove { center: Key, lock_angle: Key, snap_angle: Key }, + PointerOutsideViewport { center: Key, lock_angle: Key, snap_angle: Key }, UpdateOptions(LineOptionsUpdate), } @@ -149,6 +151,7 @@ struct LineToolData { weight: f64, layer: Option, snap_manager: SnapManager, + auto_panning: AutoPanning, } impl Fsm for LineToolFsmState { @@ -196,6 +199,13 @@ impl Fsm for LineToolFsmState { let snap_data = SnapData::ignore(document, input, &ignore); responses.add(generate_transform(tool_data, snap_data, keyboard.key(lock_angle), keyboard.key(snap_angle), keyboard.key(center))); + // Auto-panning + let messages = [ + LineToolMessage::PointerOutsideViewport { center, snap_angle, lock_angle }.into(), + LineToolMessage::PointerMove { center, snap_angle, lock_angle }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + LineToolFsmState::Drawing } (_, LineToolMessage::PointerMove { .. }) => { @@ -203,6 +213,22 @@ impl Fsm for LineToolFsmState { responses.add(OverlaysMessage::Draw); self } + (LineToolFsmState::Drawing, LineToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + LineToolFsmState::Drawing + } + (state, LineToolMessage::PointerOutsideViewport { center, lock_angle, snap_angle }) => { + // Auto-panning + let messages = [ + LineToolMessage::PointerOutsideViewport { center, lock_angle, snap_angle }.into(), + LineToolMessage::PointerMove { center, lock_angle, snap_angle }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (LineToolFsmState::Drawing, LineToolMessage::DragStop) => { tool_data.snap_manager.cleanup(responses); input.mouse.finish_transaction(tool_data.drag_start, responses); diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 538a6897c..67dfaad4a 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -3,6 +3,7 @@ use crate::consts::{COLOR_OVERLAY_YELLOW, DRAG_THRESHOLD, INSERT_POINT_ON_SEGMEN use crate::messages::portfolio::document::overlays::utility_functions::path_overlays; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::graph_modification_utils::{get_manipulator_from_id, get_mirror_handles, get_subpaths}; use crate::messages::tool::common_functionality::shape_editor::{ClosestSegment, ManipulatorAngle, ManipulatorPointInfo, OpposingHandleLengths, SelectedPointsInfo, ShapeState}; use crate::messages::tool::common_functionality::snapping::{SnapData, SnapManager}; @@ -58,6 +59,10 @@ pub enum PathToolMessage { alt: Key, shift: Key, }, + PointerOutsideViewport { + alt: Key, + shift: Key, + }, RightClick, SelectAllAnchors, SelectedPointUpdated, @@ -240,6 +245,7 @@ struct PathToolData { selection_status: SelectionStatus, segment: Option, double_click_handled: bool, + auto_panning: AutoPanning, } impl PathToolData { @@ -470,20 +476,51 @@ impl Fsm for PathToolFsmState { let direct_insert_without_sliding = input.keyboard.get(ctrl as usize); tool_data.mouse_down(shape_editor, document, input, responses, add_to_selection, direct_insert_without_sliding) } - (PathToolFsmState::DrawingBox, PathToolMessage::PointerMove { .. }) => { + (PathToolFsmState::DrawingBox, PathToolMessage::PointerMove { alt, shift }) => { tool_data.previous_mouse_position = input.mouse.position; responses.add(OverlaysMessage::Draw); + // Auto-panning + let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + PathToolFsmState::DrawingBox } (PathToolFsmState::Dragging, PathToolMessage::PointerMove { alt, shift }) => { - let alt = input.keyboard.get(alt as usize); - let shift = input.keyboard.get(shift as usize); - tool_data.drag(shift, alt, shape_editor, document, input, responses); + let alt_state = input.keyboard.get(alt as usize); + let shift_state = input.keyboard.get(shift as usize); + tool_data.drag(shift_state, alt_state, shape_editor, document, input, responses); + + // Auto-panning + let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); PathToolFsmState::Dragging } + (PathToolFsmState::DrawingBox, PathToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { + tool_data.drag_start_pos += shift; + } + PathToolFsmState::DrawingBox + } + (PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => { + // Auto-panning + if let Some(delta) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { + let shift_state = input.keyboard.get(shift as usize); + shape_editor.move_selected_points(&document.network, &document.metadata, -delta, shift_state, responses); + } + + PathToolFsmState::Dragging + } + (state, PathToolMessage::PointerOutsideViewport { alt, shift }) => { + // Auto-panning + let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (PathToolFsmState::DrawingBox, PathToolMessage::Enter { add_to_selection }) => { let shift_pressed = input.keyboard.get(add_to_selection as usize); diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 035752640..060262d5b 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -4,6 +4,7 @@ use crate::messages::portfolio::document::node_graph::VectorDataModification; use crate::messages::portfolio::document::overlays::utility_functions::path_overlays; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils::get_subpaths; @@ -53,6 +54,7 @@ pub enum PenToolMessage { DragStart, DragStop, PointerMove { snap_angle: Key, break_handle: Key, lock_angle: Key }, + PointerOutsideViewport { snap_angle: Key, break_handle: Key, lock_angle: Key }, Redo, Undo, UpdateOptions(PenOptionsUpdate), @@ -202,6 +204,7 @@ struct PenToolData { // Indicates that curve extension is occurring from the first point, rather than (more commonly) the last point from_start: bool, angle: f64, + auto_panning: AutoPanning, } impl PenToolData { fn extend_subpath(&mut self, layer: LayerNodeIdentifier, subpath_index: usize, from_start: bool, document: &DocumentMessageHandler, responses: &mut VecDeque) { @@ -674,9 +677,18 @@ impl Fsm for PenToolFsmState { break_handle: input.keyboard.key(break_handle), }; let snap_data = SnapData::new(document, input); - tool_data + let state = tool_data .drag_handle(snap_data, transform, input.mouse.position, modifiers, responses) - .unwrap_or(PenToolFsmState::Ready) + .unwrap_or(PenToolFsmState::Ready); + + // Auto-panning + let messages = [ + PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(), + PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + + state } (PenToolFsmState::PlacingAnchor, PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }) => { let modifiers = ModifierState { @@ -684,15 +696,46 @@ impl Fsm for PenToolFsmState { lock_angle: input.keyboard.key(lock_angle), break_handle: input.keyboard.key(break_handle), }; - tool_data + let state = tool_data .place_anchor(SnapData::new(document, input), transform, input.mouse.position, modifiers, responses) - .unwrap_or(PenToolFsmState::Ready) + .unwrap_or(PenToolFsmState::Ready); + + // Auto-panning + let messages = [ + PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(), + PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + + state } (PenToolFsmState::Ready, PenToolMessage::PointerMove { .. }) => { tool_data.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position); responses.add(OverlaysMessage::Draw); self } + (PenToolFsmState::DraggingHandle, PenToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + PenToolFsmState::DraggingHandle + } + (PenToolFsmState::PlacingAnchor, PenToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + PenToolFsmState::PlacingAnchor + } + (state, PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }) => { + // Auto-panning + let messages = [ + PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(), + PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (PenToolFsmState::DraggingHandle | PenToolFsmState::PlacingAnchor, PenToolMessage::Abort | PenToolMessage::Confirm) => { // Abort or commit the transaction to the undo history let message = tool_data.finish_transaction(self, document, responses).unwrap_or(DocumentMessage::AbortTransaction); diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 93ee432f2..3c9ff25a6 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -1,5 +1,6 @@ use super::tool_prelude::*; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::resize::Resize; @@ -49,6 +50,7 @@ pub enum PolygonToolMessage { DragStart, DragStop, PointerMove { center: Key, lock_ratio: Key }, + PointerOutsideViewport { center: Key, lock_ratio: Key }, UpdateOptions(PolygonOptionsUpdate), } @@ -217,6 +219,7 @@ enum PolygonToolFsmState { #[derive(Clone, Debug, Default)] struct PolygonToolData { data: Resize, + auto_panning: AutoPanning, } impl Fsm for PolygonToolFsmState { @@ -267,6 +270,13 @@ impl Fsm for PolygonToolFsmState { responses.add(message); } + // Auto-panning + let messages = [ + PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + PolygonToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + self } (_, PolygonToolMessage::PointerMove { .. }) => { @@ -274,6 +284,22 @@ impl Fsm for PolygonToolFsmState { responses.add(OverlaysMessage::Draw); self } + (PolygonToolFsmState::Drawing, PolygonToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + PolygonToolFsmState::Drawing + } + (state, PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }) => { + // Auto-panning + let messages = [ + PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + PolygonToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (PolygonToolFsmState::Drawing, PolygonToolMessage::DragStop) => { input.mouse.finish_transaction(polygon_data.viewport_drag_start(document), responses); polygon_data.cleanup(responses); diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 04c021761..9afa803a4 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -1,5 +1,6 @@ use super::tool_prelude::*; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::resize::Resize; @@ -55,6 +56,7 @@ pub enum RectangleToolMessage { DragStart, DragStop, PointerMove { center: Key, lock_ratio: Key }, + PointerOutsideViewport { center: Key, lock_ratio: Key }, UpdateOptions(RectangleOptionsUpdate), } @@ -174,6 +176,7 @@ enum RectangleToolFsmState { #[derive(Clone, Debug, Default)] struct RectangleToolData { data: Resize, + auto_panning: AutoPanning, } impl Fsm for RectangleToolFsmState { @@ -229,6 +232,13 @@ impl Fsm for RectangleToolFsmState { responses.add(message); } + // Auto-panning + let messages = [ + RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + RectangleToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + self } (_, RectangleToolMessage::PointerMove { .. }) => { @@ -236,6 +246,22 @@ impl Fsm for RectangleToolFsmState { responses.add(OverlaysMessage::Draw); self } + (RectangleToolFsmState::Drawing, RectangleToolMessage::PointerOutsideViewport { .. }) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + RectangleToolFsmState::Drawing + } + (state, RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }) => { + // Auto-panning + let messages = [ + RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), + RectangleToolMessage::PointerMove { center, lock_ratio }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (RectangleToolFsmState::Drawing, RectangleToolMessage::DragStop) => { input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses); shape_data.cleanup(responses); diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index bc5d4df7e..2a1f2fdb7 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -2,6 +2,7 @@ use super::tool_prelude::*; use crate::consts::DRAG_THRESHOLD; use crate::messages::portfolio::document::node_graph::VectorDataModification; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::snapping::SnapManager; @@ -47,6 +48,7 @@ pub enum SplineToolMessage { DragStart, DragStop, PointerMove, + PointerOutsideViewport, Undo, UpdateOptions(SplineOptionsUpdate), } @@ -184,6 +186,7 @@ struct SplineToolData { weight: f64, layer: Option, snap_manager: SnapManager, + auto_panning: AutoPanning, } impl Fsm for SplineToolFsmState { @@ -266,8 +269,25 @@ impl Fsm for SplineToolFsmState { update_spline(tool_data, true, responses); + // Auto-panning + let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()]; + tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses); + SplineToolFsmState::Drawing } + (SplineToolFsmState::Drawing, SplineToolMessage::PointerOutsideViewport) => { + // Auto-panning + let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); + + SplineToolFsmState::Drawing + } + (state, SplineToolMessage::PointerOutsideViewport) => { + // Auto-panning + let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()]; + tool_data.auto_panning.stop(&messages, responses); + + state + } (SplineToolFsmState::Drawing, SplineToolMessage::Confirm | SplineToolMessage::Abort) => { if tool_data.points.len() >= 2 { update_spline(tool_data, false, responses);