use bevy::{input::mouse::MouseMotion, prelude::*, window::CursorGrabMode};
use bevy_rapier3d::na::clamp;
use crate::{config::FpcConfiguration, Player};
#[derive(States, PartialEq, Eq, Debug, Clone, Hash, Default)]
pub enum AngularState {
#[default]
Enabled,
Disabled,
}
#[derive(Component, Default, Debug)]
pub struct VisionMotionTarget {
pub horizontal: f32,
pub vertical: f32,
}
pub fn handle_request(
mut query: Query<(&Children, &mut VisionMotionTarget, &Transform), With<Player>>,
mut children_query: Query<&Transform, (With<Camera3d>, Without<Player>)>,
mut mouse_evr: EventReader<MouseMotion>,
fpc_conf: Res<FpcConfiguration>,
) {
for ev in mouse_evr.read() {
query.iter_mut().for_each(|(children, mut vmt, transform)| {
let cursor_ratio = 0.001 * fpc_conf.angular_sensitivity;
let mut horizontal_transform = transform.clone();
horizontal_transform.rotation = Quat::from_rotation_y(vmt.horizontal);
horizontal_transform.rotate_y(-ev.delta.x * cursor_ratio);
let Vec3 { y, .. } = horizontal_transform.rotation.to_scaled_axis();
vmt.horizontal = y;
for &child in children.iter() {
let mut vertical_transform = children_query.get_mut(child).unwrap().clone();
vertical_transform.rotation = Quat::from_rotation_x(vmt.vertical);
vertical_transform.rotate_x(-ev.delta.y * cursor_ratio);
let Vec3 { x, .. } = vertical_transform.rotation.to_scaled_axis();
let clamped_angle = clamp(x, -fpc_conf.angular_clamping, fpc_conf.angular_clamping);
vertical_transform.rotation = Quat::from_rotation_x(clamped_angle);
let Vec3 { x, .. } = vertical_transform.rotation.to_scaled_axis();
vmt.vertical = x;
}
});
}
}
pub fn apply_motion(
mut query: Query<(&Children, &mut Transform, &VisionMotionTarget), With<Player>>,
mut children_query: Query<&mut Transform, (With<Camera3d>, Without<Player>)>,
time: Res<Time>,
fpc_conf: Res<FpcConfiguration>,
) {
let interpolation = time.delta_seconds() * 20. / fpc_conf.angular_smoothing;
query.iter_mut().for_each(
|(
children,
mut transform,
VisionMotionTarget {
horizontal,
vertical,
},
)| {
transform.rotation = transform
.rotation
.slerp(Quat::from_rotation_y(*horizontal), interpolation);
for &child in children.iter() {
let mut camera_transform_target = children_query.get_mut(child).unwrap();
camera_transform_target.rotation = camera_transform_target
.rotation
.slerp(Quat::from_rotation_x(*vertical), interpolation);
}
},
);
}
pub fn lock_cursor(mut windows: Query<&mut Window>) {
if let Ok(mut window) = windows.get_single_mut() {
window.cursor.grab_mode = CursorGrabMode::Locked;
window.cursor.visible = false;
}
}
pub fn free_cursor(mut windows: Query<&mut Window>) {
if let Ok(mut window) = windows.get_single_mut() {
window.cursor.grab_mode = CursorGrabMode::None;
window.cursor.visible = true;
}
}