// NOTE: this is mostly taken from the `iMplode-nZ/bevy-orbit-controls` projects but // with some modifications like Panning, and 2D support. // Most of these modifications have been contributed upstream. use bevy::input::mouse::MouseMotion; use bevy::input::mouse::MouseScrollUnit::{Line, Pixel}; use bevy::input::mouse::MouseWheel; use bevy::prelude::*; use bevy::render::camera::Camera; use std::ops::RangeInclusive; const LINE_TO_PIXEL_RATIO: f32 = 0.1; #[derive(Component)] pub struct OrbitCamera { pub x: f32, pub y: f32, pub pitch_range: RangeInclusive, pub distance: f32, pub center: Vec3, pub rotate_sensitivity: f32, pub pan_sensitivity: f32, pub zoom_sensitivity: f32, pub rotate_button: MouseButton, pub pan_button: MouseButton, pub enabled: bool, } impl Default for OrbitCamera { fn default() -> Self { OrbitCamera { x: 0.0, y: std::f32::consts::FRAC_PI_2, pitch_range: 0.01..=3.13, distance: 5.0, center: Vec3::ZERO, rotate_sensitivity: 1.0, pan_sensitivity: 1.0, zoom_sensitivity: 0.8, rotate_button: MouseButton::Left, pan_button: MouseButton::Right, enabled: true, } } } pub struct OrbitCameraPlugin; impl OrbitCameraPlugin { #[allow(clippy::type_complexity)] fn update_transform_system( mut query: Query<(&OrbitCamera, &mut Transform), (Changed, With)>, ) { for (camera, mut transform) in query.iter_mut() { let rot = Quat::from_axis_angle(Vec3::Y, camera.x) * Quat::from_axis_angle(-Vec3::X, camera.y); transform.translation = (rot * Vec3::Y) * camera.distance + camera.center; transform.look_at(camera.center, Vec3::Y); } } fn mouse_motion_system( time: Res