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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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 x: f32,
pub y: f32,
pub distance: f32,
pub center: Vec3,
pub rotate_sensitivity: f32,
pub zoom_sensitivity: f32,
}
impl Default for OrbitCamera {
fn default() -> Self {
OrbitCamera {
x: 0.0,
y: 0.0,
distance: 5.0,
center: Vec3::ZERO,
rotate_sensitivity: 1.0,
zoom_sensitivity: 0.8,
}
}
}
impl OrbitCamera {
pub fn new(dist: f32, center: Vec3) -> OrbitCamera {
OrbitCamera {
x: 0.0,
y: 0.0,
distance: dist,
center,
rotate_sensitivity: 1.0,
zoom_sensitivity: 0.8,
}
}
}
pub struct OrbitCameraPlugin;
impl OrbitCameraPlugin {
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, mut transform, _) in query.iter_mut() {
if mouse_button_input.pressed(MouseButton::Left) {
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(0.01).min(3.13);
let rot = Quat::from_axis_angle(Vec3::Y, camera.x)
* Quat::from_axis_angle(-Vec3::X, camera.y);
transform.translation =
(rot * Vec3::new(0.0, 1.0, 0.0)) * camera.distance + camera.center;
transform.look_at(camera.center, Vec3::Y);
}
}
}
fn zoom_system(
mut mouse_wheel_events: EventReader<MouseWheel>,
mut query: Query<(&mut OrbitCamera, &mut Transform, &mut 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, mut transform, _) in query.iter_mut() {
camera.distance *= camera.zoom_sensitivity.powf(total);
let translation = &mut transform.translation;
*translation =
(*translation - camera.center).normalize() * camera.distance + camera.center;
}
}
}
impl Plugin for OrbitCameraPlugin {
fn build(&self, app: &mut AppBuilder) {
app
.add_system(Self::mouse_motion_system.system())
.add_system(Self::zoom_system.system());
}
}