aboutsummaryrefslogtreecommitdiff
path: root/src_testbed/camera3d.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-06-02 17:15:46 +0200
committerGitHub <noreply@github.com>2021-06-02 17:15:46 +0200
commit6ba1c9dec184adcba2c68cc1851dc05587fd0bf0 (patch)
treeb672cfc4db1d2f426dad931d77098ecb4a600358 /src_testbed/camera3d.rs
parent3bac79ecacdeaa18de19127b7a6c82cbfab29d14 (diff)
parentbde6657287cd32a801abb996322c520673406418 (diff)
downloadrapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.tar.gz
rapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.tar.bz2
rapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.zip
Merge pull request #196 from dimforge/api_changes
More API changes
Diffstat (limited to 'src_testbed/camera3d.rs')
-rw-r--r--src_testbed/camera3d.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/src_testbed/camera3d.rs b/src_testbed/camera3d.rs
new file mode 100644
index 0000000..602ef31
--- /dev/null
+++ b/src_testbed/camera3d.rs
@@ -0,0 +1,121 @@
+// 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;
+
+pub struct OrbitCamera {
+ pub x: f32,
+ pub y: f32,
+ pub pitch_range: RangeInclusive<f32>,
+ 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 {
+ fn update_transform_system(
+ mut query: Query<(&OrbitCamera, &mut Transform), (Changed<OrbitCamera>, With<Camera>)>,
+ ) {
+ for (camera, mut transform) in query.iter_mut() {
+ if camera.enabled {
+ 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<Time>,
+ mut mouse_motion_events: EventReader<MouseMotion>,
+ mouse_button_input: Res<Input<MouseButton>>,
+ mut query: Query<(&mut OrbitCamera, &mut Transform, &mut Camera)>,
+ ) {
+ let mut delta = Vec2::ZERO;
+ for event in mouse_motion_events.iter() {
+ delta += event.delta;
+ }
+ for (mut camera, transform, _) in query.iter_mut() {
+ if !camera.enabled {
+ continue;
+ }
+
+ if mouse_button_input.pressed(camera.rotate_button) {
+ camera.x -= delta.x * camera.rotate_sensitivity * time.delta_seconds();
+ camera.y -= delta.y * camera.rotate_sensitivity * time.delta_seconds();
+ camera.y = camera
+ .y
+ .max(*camera.pitch_range.start())
+ .min(*camera.pitch_range.end());
+ }
+
+ if mouse_button_input.pressed(camera.pan_button) {
+ let right_dir = transform.rotation * -Vec3::X;
+ let up_dir = transform.rotation * Vec3::Y;
+ let pan_vector = (delta.x * right_dir + delta.y * up_dir)
+ * camera.pan_sensitivity
+ * time.delta_seconds();
+ camera.center += pan_vector;
+ }
+ }
+ }
+
+ fn zoom_system(
+ mut mouse_wheel_events: EventReader<MouseWheel>,
+ mut query: Query<&mut OrbitCamera, With<Camera>>,
+ ) {
+ let mut total = 0.0;
+ for event in mouse_wheel_events.iter() {
+ total += event.y
+ * match event.unit {
+ Line => 1.0,
+ Pixel => LINE_TO_PIXEL_RATIO,
+ };
+ }
+ for mut camera in query.iter_mut() {
+ if camera.enabled {
+ camera.distance *= camera.zoom_sensitivity.powf(total);
+ }
+ }
+ }
+}
+impl Plugin for OrbitCameraPlugin {
+ fn build(&self, app: &mut AppBuilder) {
+ app.add_system(Self::mouse_motion_system.system())
+ .add_system(Self::zoom_system.system())
+ .add_system(Self::update_transform_system.system());
+ }
+}