1use bevy::input::mouse::MouseMotion;
2use bevy::prelude::*;
3
4#[derive(Component)]
5pub struct Flycam {
6 pub yaw: f32,
7 pub pitch: f32,
8 pub speed: f32,
9 pub mouse_sensitivity: f32,
10}
11
12#[derive(Component)]
13pub struct ProbePovCamera;
14
15#[derive(Resource, Default)]
16pub struct PovState {
17 pub use_probe: bool,
18}
19
20#[derive(Component)]
21pub struct UiOverlayCamera;
22
23pub fn setup_camera(mut commands: Commands) {
24 let transform = Transform::from_xyz(-6.0, 4.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y);
25 let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
26
27 commands.spawn((
28 Camera3d::default(),
29 Camera::default(),
30 transform,
31 Flycam {
32 yaw,
33 pitch,
34 speed: 5.0,
35 mouse_sensitivity: 0.0025,
36 },
37 ));
38
39 commands.spawn((
41 UiOverlayCamera,
42 Camera2d,
43 Camera {
44 is_active: true,
45 order: 10,
46 ..default()
47 },
48 ));
49}
50
51pub fn camera_controller(
52 time: Res<Time>,
53 keys: Res<ButtonInput<KeyCode>>,
54 mouse_buttons: Res<ButtonInput<MouseButton>>,
55 mut mouse_motion: MessageReader<MouseMotion>,
56 mut query: Query<(&mut Transform, &mut Flycam)>,
57) {
58 let dt = time.delta_secs();
59
60 for (mut transform, mut cam) in &mut query {
61 if mouse_buttons.pressed(MouseButton::Right) {
62 let mut delta = Vec2::ZERO;
63 for ev in mouse_motion.read() {
64 delta += ev.delta;
65 }
66 cam.yaw -= delta.x * cam.mouse_sensitivity;
67 cam.pitch -= delta.y * cam.mouse_sensitivity;
68 cam.pitch = cam.pitch.clamp(-1.54, 1.54);
69 } else {
70 mouse_motion.clear();
72 }
73
74 let yaw = cam.yaw;
75 let pitch = cam.pitch;
76 let rot = Quat::from_euler(EulerRot::YXZ, yaw, pitch, 0.0);
77 let forward = rot * -Vec3::Z;
80 let right = rot * Vec3::X;
81 let up = rot * Vec3::Y;
82
83 let mut velocity = Vec3::ZERO;
84 if keys.pressed(KeyCode::KeyW) || keys.pressed(KeyCode::ArrowUp) {
85 velocity += forward;
86 }
87 if keys.pressed(KeyCode::KeyS) || keys.pressed(KeyCode::ArrowDown) {
88 velocity -= forward;
89 }
90 if keys.pressed(KeyCode::KeyD) || keys.pressed(KeyCode::ArrowRight) {
91 velocity += right;
92 }
93 if keys.pressed(KeyCode::KeyA) || keys.pressed(KeyCode::ArrowLeft) {
94 velocity -= right;
95 }
96 if keys.pressed(KeyCode::Space) {
97 velocity += up;
98 }
99 if keys.pressed(KeyCode::ShiftLeft) {
100 velocity -= up;
101 }
102
103 if velocity.length_squared() > 0.0 {
104 transform.translation += velocity.normalize() * cam.speed * dt;
105 }
106
107 transform.rotation = rot;
108 }
109}
110
111pub fn pov_toggle_system(
112 keys: Res<ButtonInput<KeyCode>>,
113 mut state: ResMut<PovState>,
114 mut free_cams: Query<&mut Camera, (With<Flycam>, Without<ProbePovCamera>)>,
115 mut probe_cams: Query<&mut Camera, With<ProbePovCamera>>,
116) {
117 if !keys.just_pressed(KeyCode::KeyC) {
118 return;
119 }
120
121 state.use_probe = !state.use_probe;
122 let use_probe = state.use_probe;
123 let use_free = !use_probe;
124
125 for mut cam in &mut free_cams {
126 cam.is_active = use_free;
127 }
128 for mut cam in &mut probe_cams {
129 cam.is_active = use_probe;
130 }
131}