|
use crate::consts::{DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS, DRAG_BEYOND_VIEWPORT_SPEED_FACTOR}; |
|
use crate::messages::prelude::*; |
|
use crate::messages::tool::tool_messages::tool_prelude::*; |
|
|
|
#[derive(Clone, Debug, Default)] |
|
pub struct AutoPanning { |
|
subscribed_to_animation_frame: bool, |
|
} |
|
|
|
impl AutoPanning { |
|
pub fn start(&mut self, messages: &[Message], responses: &mut VecDeque<Message>) { |
|
if !self.subscribed_to_animation_frame { |
|
self.subscribed_to_animation_frame = true; |
|
|
|
for message in messages { |
|
responses.add(BroadcastMessage::SubscribeEvent { |
|
on: BroadcastEvent::AnimationFrame, |
|
send: Box::new(message.clone()), |
|
}); |
|
} |
|
} |
|
} |
|
|
|
pub fn stop(&mut self, messages: &[Message], responses: &mut VecDeque<Message>) { |
|
if self.subscribed_to_animation_frame { |
|
self.subscribed_to_animation_frame = false; |
|
|
|
for message in messages { |
|
responses.add(BroadcastMessage::UnsubscribeEvent { |
|
on: BroadcastEvent::AnimationFrame, |
|
message: Box::new(message.clone()), |
|
}); |
|
} |
|
} |
|
} |
|
|
|
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; |
|
|
|
match is_pointer_outside_edge { |
|
true => self.start(messages, responses), |
|
false => self.stop(messages, responses), |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
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), |
|
viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS), |
|
); |
|
let mouse_position_percent = mouse_position / viewport_size; |
|
|
|
let mut shift_percent = DVec2::ZERO; |
|
|
|
if mouse_position_percent.x < 0. { |
|
shift_percent.x = -mouse_position_percent.x; |
|
} else if mouse_position_percent.x > 1. { |
|
shift_percent.x = 1. - mouse_position_percent.x; |
|
} |
|
|
|
if mouse_position_percent.y < 0. { |
|
shift_percent.y = -mouse_position_percent.y; |
|
} else if mouse_position_percent.y > 1. { |
|
shift_percent.y = 1. - mouse_position_percent.y; |
|
} |
|
|
|
if shift_percent.x == 0. && shift_percent.y == 0. { |
|
return None; |
|
} |
|
|
|
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::CanvasPan { delta }); |
|
Some(delta) |
|
} |
|
} |
|
|