Add auto-panning to all remaining tools (#1682)

* Add auto-panning to Gradient tool

* Add auto-panning to Path tool

* Add auto-panning to Pen tool

* Add auto-panning to Spline tool

* Add auto-panning to Line tool

* Add auto-panning to Rectangle tool

* Add auto-panning to Ellipse tool

* Add auto-panning to Polygon tool

* Hide `PointerOutsideViewport` in debug messages

* cargo fmt

* Code review cleanup

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Elbert Ronnie 2024-03-14 11:35:33 +05:30 committed by GitHub
parent 9ac10cdcf8
commit ea4f3d8bba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 244 additions and 9 deletions

View file

@ -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>], 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 => {

View file

@ -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);

View file

@ -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<SelectedGradient>,
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);

View file

@ -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<LayerNodeIdentifier>,
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);

View file

@ -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<ClosestSegment>,
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);

View file

@ -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<Message>) {
@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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<LayerNodeIdentifier>,
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);