avian3d-sandbox/src/camera.rs

98 lines
2.8 KiB
Rust

use bevy::{prelude::*, utils::HashSet};
use crate::bike::CyberBikeBody;
#[derive(Component)]
pub struct CyberCameras;
#[derive(Debug, Resource)]
pub struct DebugCamOffset {
pub rot: f32,
pub dist: f32,
pub alt: f32,
}
impl Default for DebugCamOffset {
fn default() -> Self {
DebugCamOffset {
rot: 60.0,
dist: 10.0,
alt: 4.0,
}
}
}
fn spawn_camera(mut commands: Commands) {
commands
.spawn(Camera3dBundle::default())
.insert(CyberCameras);
}
fn update_camera_pos(mut offset: ResMut<DebugCamOffset>, mut keys: ResMut<ButtonInput<KeyCode>>) {
let keyset: HashSet<_> = keys.get_pressed().collect();
let shifted = keyset.contains(&KeyCode::ShiftLeft) || keyset.contains(&KeyCode::ShiftRight);
for key in keyset {
match key {
KeyCode::ArrowLeft => offset.rot -= 5.0,
KeyCode::ArrowRight => offset.rot += 5.0,
KeyCode::ArrowUp => {
if shifted {
bevy::log::info!("up, shifted");
offset.alt += 0.5;
} else {
bevy::log::info!("up");
offset.dist -= 0.5;
}
}
KeyCode::ArrowDown => {
if shifted {
bevy::log::info!("down, shifted");
offset.alt -= 0.5;
} else {
bevy::log::info!("down");
offset.dist += 0.5;
}
}
_ => continue,
}
}
let just_released: HashSet<_> = keys.get_just_released().cloned().collect();
if !just_released.is_empty() {
let released_shift = just_released.contains(&KeyCode::ShiftLeft)
|| just_released.contains(&KeyCode::ShiftRight);
keys.reset_all();
if !released_shift && shifted {
keys.press(KeyCode::ShiftLeft);
}
}
}
fn follow_bike(
mut camera: Query<&mut Transform, (With<CyberCameras>, Without<CyberBikeBody>)>,
bike: Query<&Transform, (With<CyberBikeBody>, Without<CyberCameras>)>,
offset: Res<DebugCamOffset>,
) {
let bike_xform = *bike.single();
let up = Vec3::Y;
let mut ncx = Transform::from_translation(bike_xform.translation);
ncx.rotate(Quat::from_axis_angle(up, offset.rot.to_radians()));
ncx.translation += ncx.forward() * offset.dist;
ncx.translation += ncx.up() * offset.alt;
ncx.look_at(bike_xform.translation, up);
let mut cam_xform = camera.single_mut();
*cam_xform = ncx;
}
pub struct CamPlug;
impl Plugin for CamPlug {
fn build(&self, app: &mut App) {
app.insert_resource(DebugCamOffset::default())
.add_systems(Startup, spawn_camera)
.add_systems(Update, (follow_bike, update_camera_pos));
}
}