// flying camera that you can control with mouse, I still didn't find a good crate for it // maybe switch to smooth-bevy-cameras, but still needs a custom controller use std::f32::consts::PI; use bevy::input::gamepad::GamepadEvent; use bevy::input::mouse::{MouseMotion, MouseWheel}; use bevy::prelude::*; use bevy_inspector_egui::bevy_egui::EguiContexts; pub struct OrbitCameraPlugin; impl Plugin for OrbitCameraPlugin { fn build(&self, app: &mut App) { app.register_type::(); app.add_systems(Update, apply_camera_controls); app.add_systems(Update, update_camera.after(apply_camera_controls)); } } #[derive(Bundle, Default)] pub struct OrbitCameraBundle { pub orbit_camera: OrbitCamera, pub camera3d: Camera3dBundle, } #[derive(Debug, Component, Reflect)] pub struct OrbitCamera { pub zoom_sensitivity: f32, pub rotate_sensitivity: f32, pub pan_sensitivity: f32, pub gimbal_x: f32, pub gimbal_y: f32, pub distance: f32, pub min_distance: f32, pub max_distance: f32, pub min_y_angle: f32, pub max_y_angle: f32, pub target: Vec3, pub active: bool, pub last_rotation: Quat, } impl Default for OrbitCamera { fn default() -> Self { Self { zoom_sensitivity: 0.1, rotate_sensitivity: 0.003, pan_sensitivity: 0.001, gimbal_x: 60f32.to_radians(), gimbal_y: 20f32.to_radians(), distance: 3., min_distance: 0., max_distance: f32::INFINITY, min_y_angle: 0.02, max_y_angle: PI / 2.2, target: Vec3::ZERO, active: true, last_rotation: Quat::IDENTITY, } } } #[derive(Default)] // We want to allow the camera to be controlled from all gamepads, // so we can't use Res> specific to a gamepad. // This state is derived from latest event of each gamepad, and is // zeroed out when any gamepad disconnects. struct GamepadState { left_stick_x: f32, right_stick_x: f32, left_stick_y: f32, right_stick_y: f32, left_trigger: f32, right_trigger: f32, } #[allow(clippy::too_many_arguments)] fn apply_camera_controls( mut scroll_events: EventReader, mut move_events: EventReader, mut gamepad_events: EventReader, mut gamepad_state: Local, time: Res