Files
snow_trail/src/systems/camera.rs
2026-01-01 19:54:00 +01:00

203 lines
6.0 KiB
Rust

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();
}
}
}
}
}