use bevy::input::touch::Touch;
use bevy::math::Vec2;
use bevy::prelude::{Res, ResMut, Resource, Touches};
#[derive(Default, Debug, Copy, Clone, PartialEq)]
pub enum TouchControls {
#[default]
OneFingerOrbit,
TwoFingerOrbit,
}
#[derive(Debug, Clone)]
pub enum TouchGestures {
None,
OneFinger(OneFingerGestures),
TwoFinger(TwoFingerGestures),
}
#[derive(Debug, Clone, Copy)]
pub struct OneFingerGestures {
pub motion: Vec2,
}
#[derive(Debug, Clone, Copy)]
pub struct TwoFingerGestures {
pub motion: Vec2,
pub pinch: f32,
#[allow(dead_code)]
pub rotation: f32,
}
#[derive(Resource, Default, Debug)]
pub struct TouchTracker {
curr_pressed: (Option<Touch>, Option<Touch>),
prev_pressed: (Option<Touch>, Option<Touch>),
}
impl TouchTracker {
pub fn get_touch_gestures(&self) -> TouchGestures {
match (self.curr_pressed, self.prev_pressed) {
((None, None), (None, None)) => TouchGestures::None,
((Some(curr), None), (Some(prev), None)) => {
let curr_pos = curr.position();
let prev_pos = prev.position();
let motion = curr_pos - prev_pos;
TouchGestures::OneFinger(OneFingerGestures { motion })
}
((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);
let motion = curr_midpoint - prev_midpoint;
let curr_dist = curr1_pos.distance(curr2_pos);
let prev_dist = prev1_pos.distance(prev2_pos);
let pinch = curr_dist - prev_dist;
let prev_vec = prev2_pos - prev1_pos;
let curr_vec = curr2_pos - curr1_pos;
let prev_angle_negy = prev_vec.angle_to(Vec2::NEG_Y);
let curr_angle_negy = curr_vec.angle_to(Vec2::NEG_Y);
let prev_angle_posy = prev_vec.angle_to(Vec2::Y);
let curr_angle_posy = curr_vec.angle_to(Vec2::Y);
let rotate_angle_negy = curr_angle_negy - prev_angle_negy;
let rotate_angle_posy = curr_angle_posy - prev_angle_posy;
let rotation = if rotate_angle_negy.abs() < rotate_angle_posy.abs() {
rotate_angle_negy
} else {
rotate_angle_posy
};
TouchGestures::TwoFinger(TwoFingerGestures {
motion,
pinch,
rotation,
})
}
_ => TouchGestures::None,
}
}
}
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));
}
_ => {}
}
}