use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
use bevy::input::touch::Touch;
use bevy::prelude::*;
use crate::traits::Midpoint;
use crate::{ActiveCameraData, PanOrbitCamera};
#[derive(Resource, Default, Debug)]
pub struct MouseKeyTracker {
pub orbit: Vec2,
pub pan: Vec2,
pub scroll_line: f32,
pub scroll_pixel: f32,
pub rotation_angle: f32,
pub orbit_button_changed: bool,
}
pub fn mouse_key_tracker(
mut camera_movement: ResMut<MouseKeyTracker>,
mouse_input: Res<Input<MouseButton>>,
key_input: Res<Input<KeyCode>>,
mut mouse_motion: EventReader<MouseMotion>,
mut scroll_events: EventReader<MouseWheel>,
active_cam: Res<ActiveCameraData>,
orbit_cameras: Query<&PanOrbitCamera>,
) {
let mouse_delta = mouse_motion.read().map(|event| event.delta).sum::<Vec2>();
let (scroll_line_delta, scroll_pixel_delta) = scroll_events
.read()
.map(|event| match event.unit {
MouseScrollUnit::Line => (event.y, 0.0),
MouseScrollUnit::Pixel => (0.0, event.y * 0.005),
})
.fold((0.0, 0.0), |acc, item| (acc.0 + item.0, acc.1 + item.1));
if let Some(active_entity) = active_cam.entity {
if let Ok(pan_orbit) = orbit_cameras.get(active_entity) {
let mut orbit = Vec2::ZERO;
let mut pan = Vec2::ZERO;
let mut scroll_line = 0.0;
let mut scroll_pixel = 0.0;
let mut orbit_button_changed = false;
if orbit_pressed(pan_orbit, &mouse_input, &key_input) {
orbit += mouse_delta;
} else if pan_pressed(pan_orbit, &mouse_input, &key_input) {
pan += mouse_delta;
}
scroll_line += scroll_line_delta;
scroll_pixel += scroll_pixel_delta;
if orbit_just_pressed(pan_orbit, &mouse_input, &key_input)
|| orbit_just_released(pan_orbit, &mouse_input, &key_input)
{
orbit_button_changed = true;
}
camera_movement.orbit = orbit;
camera_movement.pan = pan;
camera_movement.scroll_line = scroll_line;
camera_movement.scroll_pixel = scroll_pixel;
camera_movement.orbit_button_changed = orbit_button_changed;
}
}
}
#[derive(Resource, Default, Debug)]
pub struct TouchTracker {
pub curr_pressed: (Option<Touch>, Option<Touch>),
pub prev_pressed: (Option<Touch>, Option<Touch>),
}
impl TouchTracker {
pub fn calculate_movement(&self) -> (Vec2, Vec2, f32) {
let mut orbit = Vec2::ZERO;
let mut pan = Vec2::ZERO;
let mut zoom_pixel = 0.0;
match (self.curr_pressed, self.prev_pressed) {
((Some(curr), None), (Some(prev), None)) => {
let curr_pos = curr.position();
let prev_pos = prev.position();
orbit += curr_pos - prev_pos;
}
((Some(curr1), Some(curr2)), (Some(prev1), Some(prev2))) => {
let curr1_pos = curr1.position();
let curr2_pos = curr2.position();
let prev1_pos = prev1.position();
let prev2_pos = prev2.position();
let curr_midpoint = curr1_pos.midpoint(curr2_pos);
let prev_midpoint = prev1_pos.midpoint(prev2_pos);
pan += curr_midpoint - prev_midpoint;
let curr_dist = curr1_pos.distance(curr2_pos);
let prev_dist = prev1_pos.distance(prev2_pos);
zoom_pixel += (curr_dist - prev_dist) * 0.015;
}
_ => {}
}
(orbit, pan, zoom_pixel)
}
}
pub fn touch_tracker(touches: Res<Touches>, mut touch_tracker: ResMut<TouchTracker>) {
let pressed: Vec<&Touch> = touches.iter().collect();
match pressed.len() {
0 => {
touch_tracker.curr_pressed = (None, None);
touch_tracker.prev_pressed = (None, None);
}
1 => {
let touch: &Touch = pressed.first().unwrap();
touch_tracker.prev_pressed = touch_tracker.curr_pressed;
touch_tracker.curr_pressed = (Some(*touch), None);
}
2 => {
let touch1: &Touch = pressed.first().unwrap();
let touch2: &Touch = pressed.last().unwrap();
touch_tracker.prev_pressed = touch_tracker.curr_pressed;
touch_tracker.curr_pressed = (Some(*touch1), Some(*touch2));
}
_ => {}
}
}
pub fn orbit_pressed(
pan_orbit: &PanOrbitCamera,
mouse_input: &Res<Input<MouseButton>>,
key_input: &Res<Input<KeyCode>>,
) -> bool {
let is_pressed = pan_orbit
.modifier_orbit
.map_or(true, |modifier| key_input.pressed(modifier))
&& mouse_input.pressed(pan_orbit.button_orbit);
is_pressed
&& pan_orbit
.modifier_pan
.map_or(true, |modifier| !key_input.pressed(modifier))
}
pub fn orbit_just_pressed(
pan_orbit: &PanOrbitCamera,
mouse_input: &Res<Input<MouseButton>>,
key_input: &Res<Input<KeyCode>>,
) -> bool {
let just_pressed = pan_orbit
.modifier_orbit
.map_or(true, |modifier| key_input.pressed(modifier))
&& (mouse_input.just_pressed(pan_orbit.button_orbit));
just_pressed
&& pan_orbit
.modifier_pan
.map_or(true, |modifier| !key_input.pressed(modifier))
}
pub fn orbit_just_released(
pan_orbit: &PanOrbitCamera,
mouse_input: &Res<Input<MouseButton>>,
key_input: &Res<Input<KeyCode>>,
) -> bool {
let just_released = pan_orbit
.modifier_orbit
.map_or(true, |modifier| key_input.pressed(modifier))
&& (mouse_input.just_released(pan_orbit.button_orbit));
just_released
&& pan_orbit
.modifier_pan
.map_or(true, |modifier| !key_input.pressed(modifier))
}
pub fn pan_pressed(
pan_orbit: &PanOrbitCamera,
mouse_input: &Res<Input<MouseButton>>,
key_input: &Res<Input<KeyCode>>,
) -> bool {
let is_pressed = pan_orbit
.modifier_pan
.map_or(true, |modifier| key_input.pressed(modifier))
&& mouse_input.pressed(pan_orbit.button_pan);
is_pressed
&& pan_orbit
.modifier_orbit
.map_or(true, |modifier| !key_input.pressed(modifier))
}
pub fn pan_just_pressed(
pan_orbit: &PanOrbitCamera,
mouse_input: &Res<Input<MouseButton>>,
key_input: &Res<Input<KeyCode>>,
) -> bool {
let just_pressed = pan_orbit
.modifier_pan
.map_or(true, |modifier| key_input.pressed(modifier))
&& (mouse_input.just_pressed(pan_orbit.button_pan));
just_pressed
&& pan_orbit
.modifier_orbit
.map_or(true, |modifier| !key_input.pressed(modifier))
}