mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 06:08:11 +08:00
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:
@@ -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.;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user