|
|
|
|
@ -60,12 +60,82 @@ pub fn camera_free_look( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Update the current camera state's internal yaw and pitch.
|
|
|
|
|
let delta = accumulated_mouse_motion.delta * camera.sensitivity; |
|
|
|
|
let motion = accumulated_mouse_motion.delta * camera.sensitivity; |
|
|
|
|
let (min, max) = camera.pitch_limit.clone().into_inner(); |
|
|
|
|
camera.yaw = (camera.yaw - delta.x).rem_euclid(TAU); // keep within 0°..360°
|
|
|
|
|
camera.pitch = (camera.pitch - delta.y).clamp(min, max); |
|
|
|
|
camera.yaw = (camera.yaw - motion.x).rem_euclid(TAU); // keep within 0°..360°
|
|
|
|
|
camera.pitch = (camera.pitch - motion.y).clamp(min, max); |
|
|
|
|
|
|
|
|
|
// Override the camera transform's rotation.
|
|
|
|
|
transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, camera.yaw, camera.pitch); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: Make it possible to attach this to any entity, such as the player,
|
|
|
|
|
// with the camera being a child. This will require the noclip system
|
|
|
|
|
// to know which entity is the camera.
|
|
|
|
|
|
|
|
|
|
#[derive(Component, Debug)] |
|
|
|
|
pub struct CameraNoClip { |
|
|
|
|
/// The speed at which the camera moves.
|
|
|
|
|
pub speed: f32, |
|
|
|
|
|
|
|
|
|
/// [`KeyCode`] for forward (relative to camera) translation.
|
|
|
|
|
pub key_forward: KeyCode, |
|
|
|
|
/// [`KeyCode`] for backward (relative to camera) translation.
|
|
|
|
|
pub key_back: KeyCode, |
|
|
|
|
/// [`KeyCode`] for right (relative to camera) translation.
|
|
|
|
|
pub key_right: KeyCode, |
|
|
|
|
/// [`KeyCode`] for left (relative to camera) translation.
|
|
|
|
|
pub key_left: KeyCode, |
|
|
|
|
/// [`KeyCode`] for up (global +Y) translation.
|
|
|
|
|
pub key_up: KeyCode, |
|
|
|
|
/// [`KeyCode`] for down (global -Y) translation.
|
|
|
|
|
pub key_down: KeyCode, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Default for CameraNoClip { |
|
|
|
|
fn default() -> Self { |
|
|
|
|
Self { |
|
|
|
|
speed: 5.0, |
|
|
|
|
key_forward: KeyCode::KeyW, |
|
|
|
|
key_back: KeyCode::KeyS, |
|
|
|
|
key_right: KeyCode::KeyD, |
|
|
|
|
key_left: KeyCode::KeyA, |
|
|
|
|
key_up: KeyCode::Space, |
|
|
|
|
key_down: KeyCode::ShiftLeft, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn noclip_controller( |
|
|
|
|
time: Res<Time<Real>>, |
|
|
|
|
cursor: Single<&mut CursorOptions>, |
|
|
|
|
key_input: Res<ButtonInput<KeyCode>>, |
|
|
|
|
camera: Single<(&mut Transform, &mut CameraNoClip)>, |
|
|
|
|
) { |
|
|
|
|
let (mut transform, noclip) = camera.into_inner(); |
|
|
|
|
if cursor.grab_mode != CursorGrabMode::Locked { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[rustfmt::skip] |
|
|
|
|
let movement = { |
|
|
|
|
let mut movement = Vec3::ZERO; |
|
|
|
|
if key_input.pressed(noclip.key_forward) { movement.z += 1.0; } |
|
|
|
|
if key_input.pressed(noclip.key_back ) { movement.z -= 1.0; } |
|
|
|
|
if key_input.pressed(noclip.key_right ) { movement.x += 1.0; } |
|
|
|
|
if key_input.pressed(noclip.key_left ) { movement.x -= 1.0; } |
|
|
|
|
if key_input.pressed(noclip.key_up ) { movement.y += 1.0; } |
|
|
|
|
if key_input.pressed(noclip.key_down ) { movement.y -= 1.0; } |
|
|
|
|
movement.clamp_length_max(1.0) * noclip.speed |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if movement != Vec3::ZERO { |
|
|
|
|
let dt = time.delta_secs(); |
|
|
|
|
let forward = transform.forward(); |
|
|
|
|
let right = transform.right(); |
|
|
|
|
transform.translation += movement.x * dt * right; |
|
|
|
|
transform.translation += movement.y * dt * Vec3::Y; |
|
|
|
|
transform.translation += movement.z * dt * forward; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|