106 lines
3.5 KiB
Rust
106 lines
3.5 KiB
Rust
use lyra_engine::{
|
|
game::Game,
|
|
input::{ActionHandler, CommonActionLabel},
|
|
math::{Quat, Vec3, EulerRot},
|
|
plugin::Plugin, ecs::{Component, query::{Res, View}}, DeltaTime, scene::CameraComponent,
|
|
};
|
|
|
|
/* enum FreeFlyCameraActions {
|
|
MoveForwardBackward,
|
|
MoveLeftRight,
|
|
MoveUpDown,
|
|
LookLeftRight,
|
|
LookUpDown,
|
|
LookRoll,
|
|
} */
|
|
|
|
#[derive(Clone, Component)]
|
|
pub struct FreeFlyCamera {
|
|
pub speed: f32,
|
|
pub slow_speed_factor: f32,
|
|
pub look_speed: f32,
|
|
pub mouse_sensitivity: f32,
|
|
pub look_with_keys: bool,
|
|
}
|
|
|
|
impl Default for FreeFlyCamera {
|
|
fn default() -> Self {
|
|
Self {
|
|
speed: 4.0,
|
|
slow_speed_factor: 0.25,
|
|
look_speed: 0.3,
|
|
mouse_sensitivity: 1.0,
|
|
look_with_keys: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FreeFlyCamera {
|
|
#[allow(dead_code)]
|
|
pub fn new(speed: f32, slow_speed_factor: f32, look_speed: f32, mouse_sensitivity: f32, look_with_keys: bool) -> Self {
|
|
Self {
|
|
speed,
|
|
slow_speed_factor,
|
|
look_speed,
|
|
mouse_sensitivity,
|
|
look_with_keys,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn free_fly_camera_controller(delta_time: Res<DeltaTime>, handler: Res<ActionHandler>, view: View<(&mut CameraComponent, &FreeFlyCamera)>) -> anyhow::Result<()> {
|
|
let delta_time = **delta_time;
|
|
for (mut cam, fly) in view.into_iter() {
|
|
let forward = cam.transform.forward();
|
|
let left = cam.transform.left();
|
|
let up = Vec3::Y;
|
|
|
|
let move_y = handler.get_axis_modifier(CommonActionLabel::MoveUpDown).unwrap_or(0.0);
|
|
let move_x = handler.get_axis_modifier(CommonActionLabel::MoveLeftRight).unwrap_or(0.0);
|
|
let move_z = handler.get_axis_modifier(CommonActionLabel::MoveForwardBackward).unwrap_or(0.0);
|
|
|
|
let mut velocity = Vec3::ZERO;
|
|
velocity += move_y * up;
|
|
velocity += move_x * left;
|
|
velocity += move_z * forward;
|
|
|
|
if velocity != Vec3::ZERO {
|
|
cam.transform.translation += velocity.normalize() * fly.speed * delta_time; // TODO: speeding up
|
|
}
|
|
|
|
let motion_x = handler.get_axis_modifier(CommonActionLabel::LookLeftRight).unwrap_or(0.0);
|
|
let motion_y = handler.get_axis_modifier(CommonActionLabel::LookUpDown).unwrap_or(0.0);
|
|
let motion_z = handler.get_axis_modifier(CommonActionLabel::LookRoll).unwrap_or(0.0);
|
|
|
|
let mut camera_rot = Vec3::ZERO;
|
|
camera_rot.y -= motion_x * fly.mouse_sensitivity;
|
|
camera_rot.x -= motion_y * fly.mouse_sensitivity;
|
|
camera_rot.z -= motion_z * fly.mouse_sensitivity;
|
|
|
|
if camera_rot != Vec3::ZERO {
|
|
let look_velocity = camera_rot * fly.look_speed * delta_time;
|
|
|
|
let (mut y, mut x, _) = cam.transform.rotation.to_euler(EulerRot::YXZ);
|
|
x += look_velocity.x;
|
|
y += look_velocity.y;
|
|
x = x.clamp(-1.54, 1.54);
|
|
|
|
// rotation is not commutative, keep this order to avoid unintended roll
|
|
cam.transform.rotation = Quat::from_axis_angle(Vec3::Y, y)
|
|
* Quat::from_axis_angle(Vec3::X, x);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// A plugin that adds the free fly camera controller system to the world. It is expected that
|
|
/// there is a [`FreeFlyCamera`] in the world, if there isn't, the camera would not move.
|
|
pub struct FreeFlyCameraPlugin;
|
|
|
|
impl Plugin for FreeFlyCameraPlugin {
|
|
fn setup(&self, game: &mut Game) {
|
|
game.with_system("free_fly_camera_system", free_fly_camera_controller, &[]);
|
|
}
|
|
}
|