use raidillon_engine::system::{System, SystemContext}; use glam::{Quat, Vec3}; use winit::event::DeviceEvent::MouseMotion; use winit::event::{ElementState, Event, MouseButton, WindowEvent}; use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::CursorGrabMode; use raidillon_assets::model_path; use raidillon_platform::{Camera, PlatformContext}; use raidillon_engine::InputState; use raidillon_engine::EngineResources; use raidillon_core::scene::Scene; use raidillon_ecs::components::CameraMode; pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), mouse_enabled: bool, position: Vec3, yaw: f32, pitch: f32, speed: f32, sensitivity: f32, } impl Default for FPSDebugCameraSystem { fn default() -> Self { Self { mouse_delta: Default::default(), mouse_enabled: Default::default(), position: Vec3::new(0.0, 0.0, 2.0), yaw: -90.0, pitch: 0.0, speed: 8.0, sensitivity: 0.1, } } } impl System for FPSDebugCameraSystem { fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { if !self.is_camera_mode_valid(scene) { return } let pctx = res.get::().unwrap(); let event2 = pctx.current_event.clone(); match event2 { Event::DeviceEvent { device_id, event} => { match event { MouseMotion { delta } => { self.mouse_delta.0 += delta.0; self.mouse_delta.1 += delta.1; }, _ => {} } }, Event::WindowEvent { event, .. } => match event { WindowEvent::MouseInput { state, button, .. } => { if button == MouseButton::Right { // blood and tear let window = pctx.window.lock().unwrap(); match state { ElementState::Pressed => { if window .set_cursor_grab(CursorGrabMode::Confined) .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) .is_ok() { window.set_cursor_visible(false); self.mouse_enabled = true; } } ElementState::Released => { let _ = window.set_cursor_grab(CursorGrabMode::None); window.set_cursor_visible(true); self.mouse_enabled = false; } } } } _ => {}, }, _ => {}, } } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { if !self.is_camera_mode_valid(scene) { return } let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); if self.mouse_enabled { self.yaw += self.mouse_delta.0 as f32 * self.sensitivity; self.pitch -= self.mouse_delta.1 as f32 * self.sensitivity; self.pitch = self.pitch.clamp(-89.0, 89.0); } let front = self.front(); let right_vec = front.cross(Vec3::Y).normalize(); if input.key_held(KeyCode::KeyW) { self.position += front * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyS) { self.position -= front * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyA) { self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyD) { self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; } scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { camera.eye = self.position; camera.center = self.position + front; }); self.mouse_delta = (0.0, 0.0); } } impl FPSDebugCameraSystem { pub fn front(&self) -> Vec3 { let yaw_rad = self.yaw.to_radians(); let pitch_rad = self.pitch.to_radians(); Vec3::new( yaw_rad.cos() * pitch_rad.cos(), pitch_rad.sin(), yaw_rad.sin() * pitch_rad.cos(), ).normalize() } fn is_camera_mode_valid(&self, scene: &mut Scene) -> bool { let mut q = scene.world.query::<(&Camera, &CameraMode)>(); let (cam_ent, (cam, cam_mode)) = q .iter() .next() .unwrap(); *cam_mode == CameraMode::Debug } }