diff --git a/src/main.rs b/src/main.rs index 2b18f0d..af04f75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ fn main() { handle_input )) .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) + .add_plugins(CameraControllerPlugin) .run(); } @@ -42,6 +43,7 @@ fn setup(mut commands: Commands, asset_server: Res) { transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() }, + CameraController::default(), Skybox { image: skybox_handle.clone(), brightness: 150.0, @@ -117,3 +119,221 @@ fn handle_input( app_exit_events.send(bevy::app::AppExit); } } + + +// ------------------------------------------------------------------------------ +// --------- copy&pasted from bevy's helpers/camera_controller.rs --------------- +// ------------------------------------------------------------------------------ +use bevy::input::mouse::MouseMotion; +use bevy::window::CursorGrabMode; +use std::{f32::consts::*, fmt}; + +pub struct CameraControllerPlugin; + +impl Plugin for CameraControllerPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Update, run_camera_controller); + } +} + +/// Based on Valorant's default sensitivity, not entirely sure why it is exactly 1.0 / 180.0, +/// but I'm guessing it is a misunderstanding between degrees/radians and then sticking with +/// it because it felt nice. +pub const RADIANS_PER_DOT: f32 = 1.0 / 180.0 * 0.5; + +#[derive(Component)] +pub struct CameraController { + pub enabled: bool, + pub initialized: bool, + pub sensitivity: f32, + pub key_forward: KeyCode, + pub key_back: KeyCode, + pub key_left: KeyCode, + pub key_right: KeyCode, + pub key_up: KeyCode, + pub key_down: KeyCode, + pub key_run: KeyCode, + pub mouse_key_cursor_grab: MouseButton, + pub keyboard_key_toggle_cursor_grab: KeyCode, + pub walk_speed: f32, + pub run_speed: f32, + pub friction: f32, + pub pitch: f32, + pub yaw: f32, + pub velocity: Vec3, +} + +impl Default for CameraController { + fn default() -> Self { + Self { + enabled: true, + initialized: false, + sensitivity: 1.0, + key_forward: KeyCode::KeyW, + key_back: KeyCode::KeyS, + key_left: KeyCode::KeyA, + key_right: KeyCode::KeyD, + key_up: KeyCode::KeyE, + key_down: KeyCode::KeyQ, + key_run: KeyCode::ShiftLeft, + mouse_key_cursor_grab: MouseButton::Left, + keyboard_key_toggle_cursor_grab: KeyCode::KeyM, + walk_speed: 5.0, + run_speed: 15.0, + friction: 0.5, + pitch: 0.0, + yaw: 0.0, + velocity: Vec3::ZERO, + } + } +} + +impl fmt::Display for CameraController { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + " +Freecam Controls: + Mouse\t- Move camera orientation + {:?}\t- Hold to grab cursor + {:?}\t- Toggle cursor grab + {:?} & {:?}\t- Fly forward & backwards + {:?} & {:?}\t- Fly sideways left & right + {:?} & {:?}\t- Fly up & down + {:?}\t- Fly faster while held", + self.mouse_key_cursor_grab, + self.keyboard_key_toggle_cursor_grab, + self.key_forward, + self.key_back, + self.key_left, + self.key_right, + self.key_up, + self.key_down, + self.key_run, + ) + } +} + +#[allow(clippy::too_many_arguments)] +fn run_camera_controller( + time: Res