fixes to camera orbit

This commit is contained in:
2024-10-29 20:52:53 -04:00
parent 9120c70b80
commit 3e12fcadbc
6 changed files with 194 additions and 90 deletions

View File

@@ -2,11 +2,11 @@ use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAn
use bevy::core_pipeline::prepass::DepthPrepass;
use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
use bevy::prelude::*;
use bevy::window::CursorGrabMode;
use shared::states::MenuState;
use shared::sets::GameplaySet;
use shared::tags::MainCamera;
use world_generation::hex_utils::HexCoord;
use world_generation::prelude::Map;
use world_generation::states::GeneratorState;
use super::components::*;
@@ -15,11 +15,15 @@ pub struct PhosCameraPlugin;
impl Plugin for PhosCameraPlugin {
fn build(&self, app: &mut App) {
app.register_type::<PhosCamera>();
app.register_type::<PhosOrbitCamera>();
app.add_systems(PreStartup, setup);
app.add_systems(Update, rts_camera_system.run_if(in_state(MenuState::InGame)));
app.add_systems(PostUpdate, limit_camera_bounds.run_if(in_state(MenuState::InGame)));
// app.add_systems(Update, rts_camera_system.in_set(GameplaySet));
// app.add_systems(PostUpdate, limit_camera_bounds.in_set(GameplaySet));
app.add_systems(Update, orbit_camera_upate.in_set(GameplaySet));
app.add_systems(Update, init_bounds.run_if(in_state(GeneratorState::SpawnMap)));
//Free Cam
//app.add_systems(Update, (grab_mouse, (update_camera, update_camera_mouse).chain()));
@@ -27,6 +31,22 @@ impl Plugin for PhosCameraPlugin {
}
}
fn init_bounds(
mut commands: Commands,
mut cam: Query<(&mut Transform, Entity), With<PhosCamera>>,
heightmap: Res<Map>,
) {
let (mut cam_t, cam_entity) = cam.single_mut();
cam_t.translation = heightmap.get_center();
commands
.entity(cam_entity)
.insert(CameraBounds::from_size(heightmap.get_world_size()))
.insert(PhosOrbitCamera {
target: heightmap.get_center_with_height(),
..Default::default()
});
}
fn setup(mut commands: Commands, mut msaa: ResMut<Msaa>) {
commands
.spawn((
@@ -37,93 +57,108 @@ fn setup(mut commands: Commands, mut msaa: ResMut<Msaa>) {
PhosCamera::default(),
MainCamera,
DepthPrepass,
PhosCameraTargets::default(),
PhosOrbitCamera::default(),
))
.insert(TemporalAntiAliasBundle::default());
*msaa = Msaa::Off;
}
fn update_camera(
mut cam_query: Query<(&PhosCamera, &mut Transform)>,
keyboard_input: Res<ButtonInput<KeyCode>>,
fn orbit_camera_upate(
mut cam_query: Query<(&mut Transform, &PhosCamera, &mut PhosOrbitCamera, &CameraBounds)>,
mut wheel: EventReader<MouseWheel>,
mut mouse_motion: EventReader<MouseMotion>,
mouse: Res<ButtonInput<MouseButton>>,
key: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
windows: Query<&Window>,
map: Res<Map>,
#[cfg(debug_assertions)] mut gizmos: Gizmos,
) {
let window = windows.single();
if window.cursor.grab_mode != CursorGrabMode::Locked {
return;
}
let (cam, mut transform) = cam_query.single_mut();
let (mut transform, config, mut orbit, bounds) = cam_query.single_mut();
let mut move_vec = Vec3::ZERO;
if keyboard_input.pressed(KeyCode::KeyA) {
move_vec += Vec3::NEG_X;
}
if keyboard_input.pressed(KeyCode::KeyD) {
move_vec += Vec3::X;
}
if keyboard_input.pressed(KeyCode::KeyW) {
move_vec += Vec3::NEG_Z;
}
if keyboard_input.pressed(KeyCode::KeyS) {
move_vec += Vec3::Z;
}
let target = orbit.target;
let mut cam_pos = target;
let rot = transform.rotation;
move_vec = (rot * move_vec.normalize_or_zero()) * cam.speed * time.delta_seconds();
//Apply Camera Dist
cam_pos -= orbit.forward * orbit.distance;
if keyboard_input.pressed(KeyCode::ShiftLeft) {
move_vec += Vec3::from(transform.down());
}
if keyboard_input.pressed(KeyCode::Space) {
move_vec += Vec3::from(transform.up());
}
transform.translation += move_vec.normalize_or_zero() * cam.speed * time.delta_seconds();
}
fn update_camera_mouse(
mut cam_query: Query<&mut Transform, With<PhosCamera>>,
mut mouse_move: EventReader<MouseMotion>,
time: Res<Time>,
windows: Query<&Window>,
) {
let window = windows.single();
if window.cursor.grab_mode != CursorGrabMode::Locked {
return;
}
let mut transform = cam_query.single_mut();
for ev in mouse_move.read() {
let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
match window.cursor.grab_mode {
CursorGrabMode::None => (),
_ => {
// Using smallest of height or width ensures equal vertical and horizontal sensitivity
pitch -= ev.delta.y.to_radians() * time.delta_seconds() * 5.;
yaw -= ev.delta.x.to_radians() * time.delta_seconds() * 5.;
}
if mouse.pressed(MouseButton::Middle) {
let mut orbit_move = Vec2::ZERO;
for e in mouse_motion.read() {
orbit_move += e.delta;
}
pitch = pitch.clamp(-1.54, 1.54);
// Order is important to prevent unintended roll
transform.rotation = Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
orbit_move *= f32::to_radians(config.speed) * time.delta_seconds();
let rot_y = Quat::from_axis_angle(Vec3::Y, orbit_move.x);
let right = orbit.forward.cross(Vec3::Y).normalize();
let rot_x = Quat::from_axis_angle(right, orbit_move.y);
orbit.forward = rot_x * rot_y * orbit.forward;
orbit.forward.y = orbit.forward.y.clamp(-1.0, 0.0);
orbit.forward = orbit.forward.normalize();
}
}
fn grab_mouse(mut windows: Query<&mut Window>, mouse: Res<ButtonInput<MouseButton>>, key: Res<ButtonInput<KeyCode>>) {
let mut window = windows.single_mut();
if mouse.just_pressed(MouseButton::Middle) {
window.cursor.visible = false;
window.cursor.grab_mode = CursorGrabMode::Locked;
if key.pressed(KeyCode::KeyE) {
let rot = Quat::from_axis_angle(Vec3::Y, f32::to_radians(config.speed) * time.delta_seconds());
orbit.forward = rot * orbit.forward;
} else if key.pressed(KeyCode::KeyQ) {
let rot = Quat::from_axis_angle(Vec3::Y, f32::to_radians(-config.speed) * time.delta_seconds());
orbit.forward = rot * orbit.forward;
}
if key.just_pressed(KeyCode::Escape) {
window.cursor.visible = true;
window.cursor.grab_mode = CursorGrabMode::None;
let mut cam_move = Vec3::ZERO;
if key.pressed(KeyCode::KeyA) {
cam_move.x = 1.;
} else if key.pressed(KeyCode::KeyD) {
cam_move.x = -1.;
}
if key.pressed(KeyCode::KeyW) {
cam_move.z = 1.;
} else if key.pressed(KeyCode::KeyS) {
cam_move.z = -1.;
}
if key.pressed(KeyCode::ShiftLeft) {
cam_move *= 2.0;
}
if cam_move != Vec3::ZERO {
cam_move = cam_move.normalize();
let move_fwd = Vec3::new(orbit.forward.x, 0., orbit.forward.z).normalize();
let move_rot = Quat::from_rotation_arc(Vec3::NEG_Z, move_fwd);
#[cfg(debug_assertions)]
{
gizmos.arrow(orbit.target, orbit.target + move_fwd, LinearRgba::WHITE.with_alpha(0.5));
gizmos.arrow(orbit.target, orbit.target - (move_rot * cam_move), LinearRgba::BLUE);
}
orbit.target -= (move_rot * cam_move) * config.speed * time.delta_seconds();
orbit.target.y = sample_ground(orbit.target, &map);
orbit.target.x = orbit.target.x.clamp(bounds.min.x, bounds.max.x);
orbit.target.z = orbit.target.z.clamp(bounds.min.y, bounds.max.y);
}
let mut scroll = 0.0;
for e in wheel.read() {
match e.unit {
MouseScrollUnit::Line => scroll += e.y * 5.,
MouseScrollUnit::Pixel => scroll += e.y,
}
}
orbit.distance -= scroll * time.delta_seconds() * config.zoom_speed;
orbit.distance = orbit.distance.clamp(config.min_height, config.max_height);
// let ground_below_cam = sample_ground(cam_pos, &map) + config.min_height;
// if cam_pos.y <= ground_below_cam {
// cam_pos.y = ground_below_cam;
// }
// if cam_pos.y < target.y {
// cam_pos.y = target.y;
// }
transform.translation = cam_pos;
transform.look_at(target, Vec3::Y);
}
fn rts_camera_system(