diff --git a/editor/src/consts.rs b/editor/src/consts.rs index 68e0b9a9..e19f2913 100644 --- a/editor/src/consts.rs +++ b/editor/src/consts.rs @@ -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 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 pub const SNAP_POINT_TOLERANCE: f64 = 5.; diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index fcbb2558..f6573b99 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -40,7 +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"]; +const DEBUG_MESSAGE_BLOCK_LIST: &[&str] = &["AnimationFrame", "PointerMove", "PointerOutsideViewport", "FrameTimeAdvance"]; impl Dispatcher { pub fn new() -> Self { diff --git a/editor/src/messages/input_mapper/utility_types/misc.rs b/editor/src/messages/input_mapper/utility_types/misc.rs index 739f92d3..c22e875e 100644 --- a/editor/src/messages/input_mapper/utility_types/misc.rs +++ b/editor/src/messages/input_mapper/utility_types/misc.rs @@ -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::prelude::*; +use core::time::Duration; use serde::{Deserialize, Serialize}; #[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, +} + +impl FrameTimeInfo { + pub fn frame_duration(&self) -> Option { + 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; + } +} diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message.rs index f3e656db..912225b4 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message.rs @@ -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::prelude::*; +use core::time::Duration; use serde::{Deserialize, Serialize}; #[impl_message(Message, InputPreprocessor)] @@ -14,5 +15,6 @@ pub enum InputPreprocessorMessage { PointerDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, PointerMove { 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 }, } diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index 448b5546..c7a35741 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -1,5 +1,6 @@ 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::misc::FrameTimeInfo; use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; @@ -7,6 +8,7 @@ use glam::DVec2; #[derive(Debug, Default)] pub struct InputPreprocessorMessageHandler { + pub frame_time: FrameTimeInfo, pub keyboard: KeyStates, pub mouse: MouseState, pub viewport_bounds: ViewportBounds, @@ -84,6 +86,9 @@ impl MessageHandler for InputP self.translate_mouse_event(mouse_state, false, responses); } + InputPreprocessorMessage::FrameTimeAdvance { timestamp } => { + self.frame_time.advance_timestamp(timestamp); + } InputPreprocessorMessage::WheelScroll { editor_mouse_state, modifier_keys } => { self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses); diff --git a/editor/src/messages/tool/common_functionality/auto_panning.rs b/editor/src/messages/tool/common_functionality/auto_panning.rs index b0747cfe..ede9f667 100644 --- a/editor/src/messages/tool/common_functionality/auto_panning.rs +++ b/editor/src/messages/tool/common_functionality/auto_panning.rs @@ -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) { + pub fn setup_by_mouse_position(&mut self, input: &InputPreprocessorMessageHandler, messages: &[Message], responses: &mut VecDeque) { + 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; match is_pointer_outside_edge { @@ -46,9 +48,15 @@ impl AutoPanning { /// 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. - /// The shift is proportional to the distance between edge and mouse. It is also guaranteed to be integral. - pub fn shift_viewport(mouse_position: DVec2, viewport_size: DVec2, responses: &mut VecDeque) -> Option { - let mouse_position = mouse_position.clamp( + /// The shift is proportional to the distance between edge and mouse, and to the duration of the frame. + /// It is also guaranteed to be integral. + pub fn shift_viewport(&self, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque) -> Option { + 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), viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS), ); @@ -72,7 +80,8 @@ impl AutoPanning { 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 }); Some(delta) } diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index 76f2f39d..84defb0a 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -213,15 +213,12 @@ impl Fsm for ArtboardToolFsmState { let mouse_position = input.mouse.position; tool_data.resize_artboard(responses, document, mouse_position, from_center, constrain_square); - tool_data.auto_panning.setup_by_mouse_position( - mouse_position, - input.viewport_bounds.size(), - &[ - ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), - ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), - ], - responses, - ); + // AutoPanning + let messages = [ + 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); ArtboardToolFsmState::ResizingBounds } @@ -245,15 +242,12 @@ impl Fsm for ArtboardToolFsmState { bounds.bounds[0] = position.round(); bounds.bounds[1] = position.round() + size.round(); - tool_data.auto_panning.setup_by_mouse_position( - mouse_position, - input.viewport_bounds.size(), - &[ - ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), - ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), - ], - responses, - ); + // AutoPanning + let messages = [ + 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); } ArtboardToolFsmState::Dragging } @@ -303,15 +297,12 @@ impl Fsm for ArtboardToolFsmState { }) } - tool_data.auto_panning.setup_by_mouse_position( - mouse_position, - input.viewport_bounds.size(), - &[ - ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), - ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), - ], - responses, - ); + // AutoPanning + let messages = [ + 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); ArtboardToolFsmState::Drawing } @@ -326,12 +317,14 @@ impl Fsm for ArtboardToolFsmState { ArtboardToolFsmState::Ready } (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::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_start += shift; } @@ -339,20 +332,20 @@ impl Fsm for ArtboardToolFsmState { ArtboardToolFsmState::Dragging } (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; } ArtboardToolFsmState::Drawing } (state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => { - tool_data.auto_panning.stop( - &[ - ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), - ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), - ], - responses, - ); + // AutoPanning + let messages = [ + ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(), + ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(), + ]; + tool_data.auto_panning.stop(&messages, responses); state } diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index 4f76f1f0..c9fca4c8 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -231,7 +231,7 @@ impl Fsm for EllipseToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); self } @@ -242,7 +242,7 @@ impl Fsm for EllipseToolFsmState { } (EllipseToolFsmState::Drawing, EllipseToolMessage::PointerOutsideViewport { .. }) => { // 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 } diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index 39d3ff2a..2b0a2ddc 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -440,13 +440,13 @@ impl Fsm for GradientToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &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(shift) = tool_data.auto_panning.shift_viewport(input, responses) { if let Some(selected_gradient) = &mut tool_data.selected_gradient { selected_gradient.transform.translation += shift; } diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index dcfdf619..ee4fff1f 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -204,7 +204,7 @@ impl Fsm for LineToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); LineToolFsmState::Drawing } @@ -215,7 +215,7 @@ impl Fsm for LineToolFsmState { } (LineToolFsmState::Drawing, LineToolMessage::PointerOutsideViewport { .. }) => { // 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 } diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 380a6581..374e17de 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -496,7 +496,7 @@ impl Fsm for PathToolFsmState { // 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); PathToolFsmState::DrawingBox } @@ -507,13 +507,13 @@ impl Fsm for PathToolFsmState { // 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); + tool_data.auto_panning.setup_by_mouse_position(input, &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) { + if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { tool_data.drag_start_pos += shift; } @@ -521,7 +521,7 @@ impl Fsm for PathToolFsmState { } (PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => { // 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); shape_editor.move_selected_points(&document.network, &document.metadata, -delta, shift_state, responses); } diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 941bef87..6040fc0d 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -685,7 +685,7 @@ impl Fsm for PenToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); state } @@ -704,7 +704,7 @@ impl Fsm for PenToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); state } @@ -715,13 +715,13 @@ impl Fsm for PenToolFsmState { } (PenToolFsmState::DraggingHandle, PenToolMessage::PointerOutsideViewport { .. }) => { // 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::PlacingAnchor, PenToolMessage::PointerOutsideViewport { .. }) => { // 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 } diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 3c9ff25a..88986c50 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -275,7 +275,7 @@ impl Fsm for PolygonToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); self } @@ -286,7 +286,7 @@ impl Fsm for PolygonToolFsmState { } (PolygonToolFsmState::Drawing, PolygonToolMessage::PointerOutsideViewport { .. }) => { // 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 } diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 9afa803a..819577c0 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -237,7 +237,7 @@ impl Fsm for RectangleToolFsmState { 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); self } @@ -248,7 +248,7 @@ impl Fsm for RectangleToolFsmState { } (RectangleToolFsmState::Drawing, RectangleToolMessage::PointerOutsideViewport { .. }) => { // 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 } diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 9e5581b7..59907d15 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -654,15 +654,12 @@ impl Fsm for SelectToolFsmState { } tool_data.drag_current += mouse_delta; - tool_data.auto_panning.setup_by_mouse_position( - input.mouse.position, - input.viewport_bounds.size(), - &[ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), - ], - responses, - ); + // AutoPanning + let messages = [ + SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), + SelectToolMessage::PointerMove(modifier_keys).into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); SelectToolFsmState::Dragging } @@ -698,15 +695,12 @@ impl Fsm for SelectToolFsmState { selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse()); - tool_data.auto_panning.setup_by_mouse_position( - input.mouse.position, - input.viewport_bounds.size(), - &[ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), - ], - responses, - ); + // AutoPanning + let messages = [ + SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), + SelectToolMessage::PointerMove(modifier_keys).into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); } } 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); tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses); - tool_data.auto_panning.setup_by_mouse_position( - input.mouse.position, - input.viewport_bounds.size(), - &[ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), - ], - responses, - ); + // AutoPanning + let messages = [ + SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), + SelectToolMessage::PointerMove(modifier_keys).into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); SelectToolFsmState::DraggingPivot } @@ -767,15 +758,12 @@ impl Fsm for SelectToolFsmState { tool_data.drag_current = input.mouse.position; responses.add(OverlaysMessage::Draw); - tool_data.auto_panning.setup_by_mouse_position( - input.mouse.position, - input.viewport_bounds.size(), - &[ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), - ], - responses, - ); + // AutoPanning + let messages = [ + SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), + SelectToolMessage::PointerMove(modifier_keys).into(), + ]; + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); let selection = tool_data.nested_selection_behavior; SelectToolFsmState::DrawingBox { selection } @@ -800,7 +788,8 @@ impl Fsm for SelectToolFsmState { SelectToolFsmState::Ready { selection } } (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_start += shift; } @@ -808,7 +797,8 @@ impl Fsm for SelectToolFsmState { SelectToolFsmState::Dragging } (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 { bounds.center_of_transformation += shift; bounds.original_bound_transform.translation += shift; @@ -818,25 +808,26 @@ impl Fsm for SelectToolFsmState { self } (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 } (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; } self } (state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => { - tool_data.auto_panning.stop( - &[ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), - ], - responses, - ); + // AutoPanning + let messages = [ + SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), + SelectToolMessage::PointerMove(modifier_keys).into(), + ]; + tool_data.auto_panning.stop(&messages, responses); state } diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index 5146ae77..39d30cef 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -271,13 +271,13 @@ impl Fsm for SplineToolFsmState { // 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); + tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); SplineToolFsmState::Drawing } (SplineToolFsmState::Drawing, SplineToolMessage::PointerOutsideViewport) => { // 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 } diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index 35093993..99631d04 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -48,7 +48,7 @@ pub fn wasm_memory() -> JsValue { } /// Helper function for calling JS's `requestAnimationFrame` with the given closure -fn request_animation_frame(f: &Closure) { +fn request_animation_frame(f: &Closure) { web_sys::window() .expect("No global `window` exists") .request_animation_frame(f.as_ref().unchecked_ref()) @@ -235,10 +235,17 @@ impl JsEditorHandle { let f = std::rc::Rc::new(RefCell::new(None)); 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()); 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)) { handle.send_frontend_message_to_js(message); }