Make auto-panning speed uniform (#1690)

* Make auto-panning speed uniform

* Abstract time-delta calculation to `TimeInfo`

* Update docs and add additional check

* Apply code review changes
This commit is contained in:
Elbert Ronnie
2024-03-16 06:36:22 +00:00
committed by GitHub
parent 56f8ecacc9
commit 42c822020e
17 changed files with 140 additions and 113 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ pub const VIEWPORT_ROTATE_SNAP_INTERVAL: f64 = 15.;
pub const VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR: f64 = 0.95; pub const VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR: f64 = 0.95;
pub const DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS: f64 = 50.; pub const DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS: f64 = 50.;
pub const DRAG_BEYOND_VIEWPORT_SPEED_FACTOR: f64 = 0.5; pub const DRAG_BEYOND_VIEWPORT_SPEED_FACTOR: f64 = 20.;
// Snapping point // Snapping point
pub const SNAP_POINT_TOLERANCE: f64 = 5.; pub const SNAP_POINT_TOLERANCE: f64 = 5.;
+1 -1
View File
@@ -40,7 +40,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
]; ];
const DEBUG_MESSAGE_BLOCK_LIST: &[&str] = &["AnimationFrame", "PointerMove", "PointerOutsideViewport"]; const DEBUG_MESSAGE_BLOCK_LIST: &[&str] = &["AnimationFrame", "PointerMove", "PointerOutsideViewport", "FrameTimeAdvance"];
impl Dispatcher { impl Dispatcher {
pub fn new() -> Self { pub fn new() -> Self {
@@ -4,6 +4,7 @@ use crate::messages::input_mapper::utility_types::input_keyboard::{KeyStates, NU
use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS; use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use core::time::Duration;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -146,3 +147,22 @@ impl ActionKeys {
} }
} }
} }
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct FrameTimeInfo {
timestamp: Duration,
prev_timestamp: Option<Duration>,
}
impl FrameTimeInfo {
pub fn frame_duration(&self) -> Option<Duration> {
self.prev_timestamp.map(|prev| self.timestamp - prev)
}
pub fn advance_timestamp(&mut self, next_timestamp: Duration) {
debug_assert!(next_timestamp >= self.timestamp);
self.prev_timestamp = Some(self.timestamp);
self.timestamp = next_timestamp;
}
}
@@ -2,6 +2,7 @@ use crate::messages::input_mapper::utility_types::input_keyboard::{Key, Modifier
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ViewportBounds}; use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ViewportBounds};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use core::time::Duration;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[impl_message(Message, InputPreprocessor)] #[impl_message(Message, InputPreprocessor)]
@@ -14,5 +15,6 @@ pub enum InputPreprocessorMessage {
PointerDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, PointerDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
PointerMove { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, PointerMove { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
PointerUp { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, PointerUp { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
FrameTimeAdvance { timestamp: Duration },
WheelScroll { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, WheelScroll { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
} }
@@ -1,5 +1,6 @@
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeyStates, ModifierKeys}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeyStates, ModifierKeys};
use crate::messages::input_mapper::utility_types::input_mouse::{MouseButton, MouseKeys, MouseState, ViewportBounds}; use crate::messages::input_mapper::utility_types::input_mouse::{MouseButton, MouseKeys, MouseState, ViewportBounds};
use crate::messages::input_mapper::utility_types::misc::FrameTimeInfo;
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*; use crate::messages::prelude::*;
@@ -7,6 +8,7 @@ use glam::DVec2;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct InputPreprocessorMessageHandler { pub struct InputPreprocessorMessageHandler {
pub frame_time: FrameTimeInfo,
pub keyboard: KeyStates, pub keyboard: KeyStates,
pub mouse: MouseState, pub mouse: MouseState,
pub viewport_bounds: ViewportBounds, pub viewport_bounds: ViewportBounds,
@@ -84,6 +86,9 @@ impl MessageHandler<InputPreprocessorMessage, KeyboardPlatformLayout> for InputP
self.translate_mouse_event(mouse_state, false, responses); self.translate_mouse_event(mouse_state, false, responses);
} }
InputPreprocessorMessage::FrameTimeAdvance { timestamp } => {
self.frame_time.advance_timestamp(timestamp);
}
InputPreprocessorMessage::WheelScroll { editor_mouse_state, modifier_keys } => { InputPreprocessorMessage::WheelScroll { editor_mouse_state, modifier_keys } => {
self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses);
@@ -34,7 +34,9 @@ impl AutoPanning {
} }
} }
pub fn setup_by_mouse_position(&mut self, mouse_position: DVec2, viewport_size: DVec2, messages: &[Message], responses: &mut VecDeque<Message>) { pub fn setup_by_mouse_position(&mut self, input: &InputPreprocessorMessageHandler, messages: &[Message], responses: &mut VecDeque<Message>) {
let mouse_position = input.mouse.position;
let viewport_size = input.viewport_bounds.size();
let is_pointer_outside_edge = mouse_position.x < 0. || mouse_position.x > viewport_size.x || mouse_position.y < 0. || mouse_position.y > viewport_size.y; let is_pointer_outside_edge = mouse_position.x < 0. || mouse_position.x > viewport_size.x || mouse_position.y < 0. || mouse_position.y > viewport_size.y;
match is_pointer_outside_edge { match is_pointer_outside_edge {
@@ -46,9 +48,15 @@ impl AutoPanning {
/// Shifts the viewport when the mouse reaches the edge of the viewport. /// Shifts the viewport when the mouse reaches the edge of the viewport.
/// ///
/// If the mouse was beyond any edge, it returns the amount shifted. Otherwise it returns None. /// If the mouse was beyond any edge, it returns the amount shifted. Otherwise it returns None.
/// The shift is proportional to the distance between edge and mouse. It is also guaranteed to be integral. /// The shift is proportional to the distance between edge and mouse, and to the duration of the frame.
pub fn shift_viewport(mouse_position: DVec2, viewport_size: DVec2, responses: &mut VecDeque<Message>) -> Option<DVec2> { /// It is also guaranteed to be integral.
let mouse_position = mouse_position.clamp( pub fn shift_viewport(&self, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> Option<DVec2> {
if !self.subscribed_to_animation_frame {
return None;
}
let viewport_size = input.viewport_bounds.size();
let mouse_position = input.mouse.position.clamp(
DVec2::ZERO - DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS), DVec2::ZERO - DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS), viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
); );
@@ -72,7 +80,8 @@ impl AutoPanning {
return None; return None;
} }
let delta = (shift_percent * DRAG_BEYOND_VIEWPORT_SPEED_FACTOR * viewport_size).round(); let time_delta = input.frame_time.frame_duration()?.as_secs_f64();
let delta = (shift_percent * DRAG_BEYOND_VIEWPORT_SPEED_FACTOR * viewport_size * time_delta).round();
responses.add(NavigationMessage::TranslateCanvas { delta }); responses.add(NavigationMessage::TranslateCanvas { delta });
Some(delta) Some(delta)
} }
@@ -213,15 +213,12 @@ impl Fsm for ArtboardToolFsmState {
let mouse_position = input.mouse.position; let mouse_position = input.mouse.position;
tool_data.resize_artboard(responses, document, mouse_position, from_center, constrain_square); tool_data.resize_artboard(responses, document, mouse_position, from_center, constrain_square);
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
mouse_position, let messages = [
input.viewport_bounds.size(), ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
&[ ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), ];
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
ArtboardToolFsmState::ResizingBounds ArtboardToolFsmState::ResizingBounds
} }
@@ -245,15 +242,12 @@ impl Fsm for ArtboardToolFsmState {
bounds.bounds[0] = position.round(); bounds.bounds[0] = position.round();
bounds.bounds[1] = position.round() + size.round(); bounds.bounds[1] = position.round() + size.round();
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
mouse_position, let messages = [
input.viewport_bounds.size(), ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
&[ ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), ];
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
} }
ArtboardToolFsmState::Dragging ArtboardToolFsmState::Dragging
} }
@@ -303,15 +297,12 @@ impl Fsm for ArtboardToolFsmState {
}) })
} }
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
mouse_position, let messages = [
input.viewport_bounds.size(), ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
&[ ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), ];
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
ArtboardToolFsmState::Drawing ArtboardToolFsmState::Drawing
} }
@@ -326,12 +317,14 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Ready ArtboardToolFsmState::Ready
} }
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => { (ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); // AutoPanning
let _ = tool_data.auto_panning.shift_viewport(input, responses);
ArtboardToolFsmState::ResizingBounds ArtboardToolFsmState::ResizingBounds
} }
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => { (ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_current += shift; tool_data.drag_current += shift;
tool_data.drag_start += shift; tool_data.drag_start += shift;
} }
@@ -339,20 +332,20 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Dragging ArtboardToolFsmState::Dragging
} }
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => { (ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_start += shift; tool_data.drag_start += shift;
} }
ArtboardToolFsmState::Drawing ArtboardToolFsmState::Drawing
} }
(state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => { (state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => {
tool_data.auto_panning.stop( // AutoPanning
&[ let messages = [
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
], ];
responses, tool_data.auto_panning.stop(&messages, responses);
);
state state
} }
@@ -231,7 +231,7 @@ impl Fsm for EllipseToolFsmState {
EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
EllipseToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
self self
} }
@@ -242,7 +242,7 @@ impl Fsm for EllipseToolFsmState {
} }
(EllipseToolFsmState::Drawing, EllipseToolMessage::PointerOutsideViewport { .. }) => { (EllipseToolFsmState::Drawing, EllipseToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
EllipseToolFsmState::Drawing EllipseToolFsmState::Drawing
} }
@@ -440,13 +440,13 @@ impl Fsm for GradientToolFsmState {
GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(), GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(),
GradientToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
GradientToolFsmState::Drawing GradientToolFsmState::Drawing
} }
(GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => { (GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(selected_gradient) = &mut tool_data.selected_gradient { if let Some(selected_gradient) = &mut tool_data.selected_gradient {
selected_gradient.transform.translation += shift; selected_gradient.transform.translation += shift;
} }
@@ -204,7 +204,7 @@ impl Fsm for LineToolFsmState {
LineToolMessage::PointerOutsideViewport { center, snap_angle, lock_angle }.into(), LineToolMessage::PointerOutsideViewport { center, snap_angle, lock_angle }.into(),
LineToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
LineToolFsmState::Drawing LineToolFsmState::Drawing
} }
@@ -215,7 +215,7 @@ impl Fsm for LineToolFsmState {
} }
(LineToolFsmState::Drawing, LineToolMessage::PointerOutsideViewport { .. }) => { (LineToolFsmState::Drawing, LineToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
LineToolFsmState::Drawing LineToolFsmState::Drawing
} }
@@ -496,7 +496,7 @@ impl Fsm for PathToolFsmState {
// Auto-panning // Auto-panning
let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()]; 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
PathToolFsmState::DrawingBox PathToolFsmState::DrawingBox
} }
@@ -507,13 +507,13 @@ impl Fsm for PathToolFsmState {
// Auto-panning // Auto-panning
let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()]; 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
PathToolFsmState::Dragging PathToolFsmState::Dragging
} }
(PathToolFsmState::DrawingBox, PathToolMessage::PointerOutsideViewport { .. }) => { (PathToolFsmState::DrawingBox, PathToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_start_pos += shift; tool_data.drag_start_pos += shift;
} }
@@ -521,7 +521,7 @@ impl Fsm for PathToolFsmState {
} }
(PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => { (PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => {
// Auto-panning // Auto-panning
if let Some(delta) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { if let Some(delta) = tool_data.auto_panning.shift_viewport(input, responses) {
let shift_state = input.keyboard.get(shift as usize); let shift_state = input.keyboard.get(shift as usize);
shape_editor.move_selected_points(&document.network, &document.metadata, -delta, shift_state, responses); shape_editor.move_selected_points(&document.network, &document.metadata, -delta, shift_state, responses);
} }
@@ -685,7 +685,7 @@ impl Fsm for PenToolFsmState {
PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(), PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(),
PenToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
state state
} }
@@ -704,7 +704,7 @@ impl Fsm for PenToolFsmState {
PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(), PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(),
PenToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
state state
} }
@@ -715,13 +715,13 @@ impl Fsm for PenToolFsmState {
} }
(PenToolFsmState::DraggingHandle, PenToolMessage::PointerOutsideViewport { .. }) => { (PenToolFsmState::DraggingHandle, PenToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
PenToolFsmState::DraggingHandle PenToolFsmState::DraggingHandle
} }
(PenToolFsmState::PlacingAnchor, PenToolMessage::PointerOutsideViewport { .. }) => { (PenToolFsmState::PlacingAnchor, PenToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
PenToolFsmState::PlacingAnchor PenToolFsmState::PlacingAnchor
} }
@@ -275,7 +275,7 @@ impl Fsm for PolygonToolFsmState {
PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
PolygonToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
self self
} }
@@ -286,7 +286,7 @@ impl Fsm for PolygonToolFsmState {
} }
(PolygonToolFsmState::Drawing, PolygonToolMessage::PointerOutsideViewport { .. }) => { (PolygonToolFsmState::Drawing, PolygonToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
PolygonToolFsmState::Drawing PolygonToolFsmState::Drawing
} }
@@ -237,7 +237,7 @@ impl Fsm for RectangleToolFsmState {
RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }.into(), RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
RectangleToolMessage::PointerMove { 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
self self
} }
@@ -248,7 +248,7 @@ impl Fsm for RectangleToolFsmState {
} }
(RectangleToolFsmState::Drawing, RectangleToolMessage::PointerOutsideViewport { .. }) => { (RectangleToolFsmState::Drawing, RectangleToolMessage::PointerOutsideViewport { .. }) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
RectangleToolFsmState::Drawing RectangleToolFsmState::Drawing
} }
@@ -654,15 +654,12 @@ impl Fsm for SelectToolFsmState {
} }
tool_data.drag_current += mouse_delta; tool_data.drag_current += mouse_delta;
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
input.mouse.position, let messages = [
input.viewport_bounds.size(), SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
&[ SelectToolMessage::PointerMove(modifier_keys).into(),
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), ];
SelectToolMessage::PointerMove(modifier_keys).into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
SelectToolFsmState::Dragging SelectToolFsmState::Dragging
} }
@@ -698,15 +695,12 @@ impl Fsm for SelectToolFsmState {
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse()); selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
input.mouse.position, let messages = [
input.viewport_bounds.size(), SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
&[ SelectToolMessage::PointerMove(modifier_keys).into(),
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), ];
SelectToolMessage::PointerMove(modifier_keys).into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
} }
} }
SelectToolFsmState::ResizingBounds SelectToolFsmState::ResizingBounds
@@ -751,15 +745,12 @@ impl Fsm for SelectToolFsmState {
let snapped_mouse_position = mouse_position; //tool_data.snap_manager.snap_position(responses, document, mouse_position); let snapped_mouse_position = mouse_position; //tool_data.snap_manager.snap_position(responses, document, mouse_position);
tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses); tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses);
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
input.mouse.position, let messages = [
input.viewport_bounds.size(), SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
&[ SelectToolMessage::PointerMove(modifier_keys).into(),
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), ];
SelectToolMessage::PointerMove(modifier_keys).into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
SelectToolFsmState::DraggingPivot SelectToolFsmState::DraggingPivot
} }
@@ -767,15 +758,12 @@ impl Fsm for SelectToolFsmState {
tool_data.drag_current = input.mouse.position; tool_data.drag_current = input.mouse.position;
responses.add(OverlaysMessage::Draw); responses.add(OverlaysMessage::Draw);
tool_data.auto_panning.setup_by_mouse_position( // AutoPanning
input.mouse.position, let messages = [
input.viewport_bounds.size(), SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
&[ SelectToolMessage::PointerMove(modifier_keys).into(),
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), ];
SelectToolMessage::PointerMove(modifier_keys).into(), tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
],
responses,
);
let selection = tool_data.nested_selection_behavior; let selection = tool_data.nested_selection_behavior;
SelectToolFsmState::DrawingBox { selection } SelectToolFsmState::DrawingBox { selection }
@@ -800,7 +788,8 @@ impl Fsm for SelectToolFsmState {
SelectToolFsmState::Ready { selection } SelectToolFsmState::Ready { selection }
} }
(SelectToolFsmState::Dragging, SelectToolMessage::PointerOutsideViewport(_)) => { (SelectToolFsmState::Dragging, SelectToolMessage::PointerOutsideViewport(_)) => {
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_current += shift; tool_data.drag_current += shift;
tool_data.drag_start += shift; tool_data.drag_start += shift;
} }
@@ -808,7 +797,8 @@ impl Fsm for SelectToolFsmState {
SelectToolFsmState::Dragging SelectToolFsmState::Dragging
} }
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerOutsideViewport(_)) => { (SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerOutsideViewport(_)) => {
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager { if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += shift; bounds.center_of_transformation += shift;
bounds.original_bound_transform.translation += shift; bounds.original_bound_transform.translation += shift;
@@ -818,25 +808,26 @@ impl Fsm for SelectToolFsmState {
self self
} }
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport(_)) => { (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport(_)) => {
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); // AutoPanning
let _ = tool_data.auto_panning.shift_viewport(input, responses);
self self
} }
(SelectToolFsmState::DrawingBox { .. }, SelectToolMessage::PointerOutsideViewport(_)) => { (SelectToolFsmState::DrawingBox { .. }, SelectToolMessage::PointerOutsideViewport(_)) => {
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) { // AutoPanning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_start += shift; tool_data.drag_start += shift;
} }
self self
} }
(state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => { (state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
tool_data.auto_panning.stop( // AutoPanning
&[ let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(), SelectToolMessage::PointerMove(modifier_keys).into(),
], ];
responses, tool_data.auto_panning.stop(&messages, responses);
);
state state
} }
@@ -271,13 +271,13 @@ impl Fsm for SplineToolFsmState {
// Auto-panning // Auto-panning
let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()]; 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); tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
SplineToolFsmState::Drawing SplineToolFsmState::Drawing
} }
(SplineToolFsmState::Drawing, SplineToolMessage::PointerOutsideViewport) => { (SplineToolFsmState::Drawing, SplineToolMessage::PointerOutsideViewport) => {
// Auto-panning // Auto-panning
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses); let _ = tool_data.auto_panning.shift_viewport(input, responses);
SplineToolFsmState::Drawing SplineToolFsmState::Drawing
} }
+9 -2
View File
@@ -48,7 +48,7 @@ pub fn wasm_memory() -> JsValue {
} }
/// Helper function for calling JS's `requestAnimationFrame` with the given closure /// Helper function for calling JS's `requestAnimationFrame` with the given closure
fn request_animation_frame(f: &Closure<dyn FnMut()>) { fn request_animation_frame(f: &Closure<dyn FnMut(f64)>) {
web_sys::window() web_sys::window()
.expect("No global `window` exists") .expect("No global `window` exists")
.request_animation_frame(f.as_ref().unchecked_ref()) .request_animation_frame(f.as_ref().unchecked_ref())
@@ -235,10 +235,17 @@ impl JsEditorHandle {
let f = std::rc::Rc::new(RefCell::new(None)); let f = std::rc::Rc::new(RefCell::new(None));
let g = f.clone(); let g = f.clone();
*g.borrow_mut() = Some(Closure::new(move || { *g.borrow_mut() = Some(Closure::new(move |timestamp| {
wasm_bindgen_futures::spawn_local(poll_node_graph_evaluation()); wasm_bindgen_futures::spawn_local(poll_node_graph_evaluation());
call_closure_with_editor_and_handle(|editor, handle| { call_closure_with_editor_and_handle(|editor, handle| {
let micros: f64 = timestamp * 1000.;
let timestamp = Duration::from_micros(micros.round() as u64);
for message in editor.handle_message(InputPreprocessorMessage::FrameTimeAdvance { timestamp }) {
handle.send_frontend_message_to_js(message);
}
for message in editor.handle_message(BroadcastMessage::TriggerEvent(BroadcastEvent::AnimationFrame)) { for message in editor.handle_message(BroadcastMessage::TriggerEvent(BroadcastEvent::AnimationFrame)) {
handle.send_frontend_message_to_js(message); handle.send_frontend_message_to_js(message);
} }