use super::*;
#[derive(Clone, Copy, Debug)]
pub struct Control2D {
pub min_zoom_factor: f32,
pub max_zoom_factor: f32,
}
impl Control2D {
pub fn new(min_zoom_factor: f32, max_zoom_factor: f32) -> Self {
Self {
min_zoom_factor,
max_zoom_factor,
}
}
pub fn handle_events(
&mut self,
camera: &mut three_d_asset::Camera,
events: &mut [Event],
device_pixel_ratio: f32,
) -> bool {
let mut change = false;
for event in events.iter_mut() {
match event {
Event::PinchGesture {
delta,
position,
handled,
..
} if !*handled => {
self.zoom(camera, *delta, *position, 0.5);
*handled = true;
change = true;
}
Event::MouseWheel {
delta,
position,
handled,
..
} if !*handled && delta.0.abs() + delta.1.abs() > f32::EPSILON => {
if delta.0.abs() < f32::EPSILON && delta.1.fract().abs() > f32::EPSILON {
self.zoom(camera, delta.1, *position, 0.005);
} else {
self.pan(camera, *delta, device_pixel_ratio);
}
*handled = true;
change = true;
}
Event::MouseMotion {
delta,
button,
handled,
..
} if !*handled && Some(MouseButton::Right) == *button => {
self.pan(camera, *delta, device_pixel_ratio);
*handled = true;
change = true;
}
_ => {}
}
}
change
}
fn zoom(
&self,
camera: &mut three_d_asset::Camera,
delta: f32,
position: PhysicalPoint,
sensitivity: f32,
) {
let mut target = camera.position_at_pixel(position);
target.z = 0.0;
let distance = 1.0 / camera.zoom_factor();
let zoom_amount = distance * (1.0 - (-delta * sensitivity).exp());
camera.zoom_towards(
target,
zoom_amount,
1.0 / self.max_zoom_factor,
1.0 / self.min_zoom_factor,
);
}
fn pan(&self, camera: &mut three_d_asset::Camera, delta: (f32, f32), device_pixel_ratio: f32) {
let origo = camera.position_at_pixel(vec2(0.0, 0.0));
let point = camera.position_at_pixel(vec2(device_pixel_ratio * delta.0, 0.0));
let x = delta.0.signum() * (point - origo).magnitude();
let point = camera.position_at_pixel(vec2(device_pixel_ratio * delta.1, 0.0));
let y = delta.1.signum() * (point - origo).magnitude();
let right = camera.right_direction();
let up = right.cross(camera.view_direction());
camera.translate(-right * x + up * y);
}
}