use glam::Vec3; use crate::utility::input::InputState; use crate::world::World; pub fn camera_input_system(world: &mut World, input_state: &InputState) { let cameras: Vec<_> = world.cameras.all(); for camera_entity in cameras { if let Some(camera) = world.cameras.get_mut(camera_entity) { if !camera.is_active { continue; } if input_state.mouse_delta.0.abs() > 0.0 || input_state.mouse_delta.1.abs() > 0.0 { let is_following = world .camera_follows .get(camera_entity) .map(|f| f.is_following) .unwrap_or(false); camera.yaw += input_state.mouse_delta.0 * 0.0008; if is_following { camera.pitch += input_state.mouse_delta.1 * 0.0008; } else { camera.pitch -= input_state.mouse_delta.1 * 0.0008; } camera.pitch = camera .pitch .clamp(-89.0_f32.to_radians(), 89.0_f32.to_radians()); } } } } pub fn camera_follow_system(world: &mut World) { let camera_entities: Vec<_> = world.camera_follows.all(); for camera_entity in camera_entities { if let Some(follow) = world.camera_follows.get(camera_entity) { if !follow.is_following { continue; } let target_entity = follow.target_entity; let offset = follow.offset; if let Some(target_transform) = world.transforms.get(target_entity) { let target_position = target_transform.position; if let Some(camera) = world.cameras.get_mut(camera_entity) { let distance = offset.length(); let orbit_yaw = camera.yaw + std::f32::consts::PI; let offset_x = distance * orbit_yaw.cos() * camera.pitch.cos(); let offset_y = distance * camera.pitch.sin(); let offset_z = distance * orbit_yaw.sin() * camera.pitch.cos(); let new_offset = Vec3::new(offset_x, offset_y, offset_z); if let Some(camera_transform) = world.transforms.get_mut(camera_entity) { camera_transform.position = target_position + new_offset; } if let Some(follow_mut) = world.camera_follows.get_mut(camera_entity) { follow_mut.offset = new_offset; } } } } } } pub fn camera_noclip_system(world: &mut World, input_state: &InputState, delta: f32) { let cameras: Vec<_> = world.cameras.all(); for camera_entity in cameras { if let Some(camera) = world.cameras.get(camera_entity) { if !camera.is_active { continue; } let forward = camera.get_forward(); let right = camera.get_right(); let mut input_vec = Vec3::ZERO; if input_state.w { input_vec.z += 1.0; } if input_state.s { input_vec.z -= 1.0; } if input_state.d { input_vec.x += 1.0; } if input_state.a { input_vec.x -= 1.0; } if input_state.space { input_vec.y += 1.0; } if input_vec.length_squared() > 0.0 { input_vec = input_vec.normalize(); } let mut speed = 10.0 * delta; if input_state.shift { speed *= 2.0; } if let Some(camera_transform) = world.transforms.get_mut(camera_entity) { camera_transform.position += forward * input_vec.z * speed; camera_transform.position += right * input_vec.x * speed; camera_transform.position += Vec3::Y * input_vec.y * speed; } } } } pub fn start_camera_following(world: &mut World, camera_entity: crate::entity::EntityHandle) { if let Some(follow) = world.camera_follows.get_mut(camera_entity) { let target_entity = follow.target_entity; if let Some(target_transform) = world.transforms.get(target_entity) { if let Some(camera_transform) = world.transforms.get(camera_entity) { let offset = camera_transform.position - target_transform.position; follow.offset = offset; follow.is_following = true; let distance = offset.length(); if distance > 0.0 { if let Some(camera) = world.cameras.get_mut(camera_entity) { camera.pitch = (offset.y / distance).asin(); camera.yaw = offset.z.atan2(offset.x) + std::f32::consts::PI; } } } } } } pub fn stop_camera_following(world: &mut World, camera_entity: crate::entity::EntityHandle) { if let Some(follow) = world.camera_follows.get_mut(camera_entity) { follow.is_following = false; if let Some(camera_transform) = world.transforms.get(camera_entity) { if let Some(target_transform) = world.transforms.get(follow.target_entity) { let look_direction = (target_transform.position - camera_transform.position).normalize(); if let Some(camera) = world.cameras.get_mut(camera_entity) { camera.yaw = look_direction.z.atan2(look_direction.x); camera.pitch = look_direction.y.asin(); } } } } }