1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// NOTE: this is inspired from the `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;
const LINE_TO_PIXEL_RATIO: f32 = 0.1;
pub struct OrbitCamera {
pub zoom: f32,
pub center: Vec3,
pub pan_sensitivity: f32,
pub zoom_sensitivity: f32,
pub pan_button: MouseButton,
pub enabled: bool,
}
impl Default for OrbitCamera {
fn default() -> Self {
OrbitCamera {
zoom: 100.0,
center: Vec3::ZERO,
pan_sensitivity: 1.0,
zoom_sensitivity: 0.8,
pan_button: MouseButton::Right,
enabled: true,
}
}
}
// Adapted from the 3D orbit camera from bevy-orbit-controls
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 {
transform.translation = camera.center;
transform.scale = Vec3::new(1.0 / camera.zoom, 1.0 / camera.zoom, 1.0);
}
}
}
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, _, _) in query.iter_mut() {
if !camera.enabled {
continue;
}
if mouse_button_input.pressed(camera.pan_button) {
let delta = delta * camera.pan_sensitivity;
camera.center += Vec3::new(-delta.x, delta.y, 0.0);
}
}
}
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.zoom *= 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());
}
}
|