use bevy::input::touch::Touch;
use bevy::math::Vec2;
use bevy::prelude::*;
#[derive(Reflect, Default, Debug, Copy, Clone, PartialEq, Eq)]
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,
reason = "computed but not yet wired — planned for touch-based camera roll"
)]
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) {
((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,
}
}
}
#[allow(clippy::unwrap_used)]
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));
},
_ => {},
}
}