use std::{collections::HashMap, error::Error, f32::consts::PI, fmt::Debug, hash::Hash}; use bevy::prelude::*; use bevy_rapier2d::prelude::*; use bevy_tts::Tts; use leafwing_input_manager::{axislike::DualAxisData, prelude::*}; use crate::{ core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player}, error::error_handler, exploration::{ExplorationFocused, Exploring}, log::Log, utils::target_and_other, }; #[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)] pub enum NavigationAction { Move, Translate, Rotate, SetLinearVelocity, SetAngularVelocity, SnapLeft, SnapRight, SnapCardinal, SnapReverse, } #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct BackwardMovementFactor(pub f32); impl Default for BackwardMovementFactor { fn default() -> Self { Self(1.) } } #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct ForwardMovementFactor(pub f32); impl Default for ForwardMovementFactor { fn default() -> Self { Self(1.) } } #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct StrafeMovementFactor(pub f32); impl Default for StrafeMovementFactor { fn default() -> Self { Self(1.) } } #[derive(Component, Clone, Copy, Default, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct RotationSpeed(pub Angle); #[derive(Deref, DerefMut)] struct SnapTimer(Timer); impl Default for SnapTimer { fn default() -> Self { Self(Timer::from_seconds(0.2, TimerMode::Once)) } } #[derive(Resource, Default, Deref, DerefMut)] struct SnapTimers(HashMap); #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct Speed(pub f32); impl Default for Speed { fn default() -> Self { Self(1.) } } fn snap( mut tts: ResMut, mut snap_timers: ResMut, mut query: Query< ( Entity, &ActionState, &mut Transform, &CardinalDirection, ), With, >, ) -> Result<(), Box> { for (entity, actions, mut transform, direction) in &mut query { if snap_timers.contains_key(&entity) { continue; } else if actions.just_pressed(NavigationAction::SnapLeft) { snap_timers.insert(entity, SnapTimer::default()); transform.rotation = Quat::from_rotation_z(match direction { CardinalDirection::North => PI, CardinalDirection::East => PI / 2., CardinalDirection::South => 0., CardinalDirection::West => -PI / 2., }); } else if actions.just_pressed(NavigationAction::SnapRight) { snap_timers.insert(entity, SnapTimer::default()); transform.rotation = Quat::from_rotation_z(match direction { CardinalDirection::North => 0., CardinalDirection::East => -PI / 2., CardinalDirection::South => PI, CardinalDirection::West => PI / 2., }); } else if actions.just_pressed(NavigationAction::SnapReverse) { snap_timers.insert(entity, SnapTimer::default()); transform.rotate(Quat::from_rotation_z(PI)); } else if actions.just_pressed(NavigationAction::SnapCardinal) { let yaw: Angle = direction.into(); let yaw = yaw.radians(); transform.rotation = Quat::from_rotation_z(yaw); tts.speak(direction.to_string(), true)?; } } Ok(()) } fn tick_snap_timers(time: Res