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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Defines mutually exclusive camera input motions, and a place to store these input streams.
use std::time::Duration;
use bevy_math::{prelude::*, DVec2};
use bevy_reflect::prelude::*;
use super::smoothing::InputQueue;
/// Tracks the current exclusive motion type and input queue of the camera controller.
#[derive(Debug, Clone, Reflect)]
pub enum MotionInputs {
/// The camera can orbit and zoom
OrbitZoom {
/// A queue of screenspace orbiting inputs; usually the mouse drag vector.
screenspace_inputs: InputQueue<Vec2>,
/// A queue of zoom inputs.
zoom_inputs: InputQueue<f32>,
},
/// The camera can pan and zoom
PanZoom {
/// A queue of screenspace panning inputs; usually the mouse drag vector.
screenspace_inputs: InputQueue<Vec2>,
/// A queue of zoom inputs.
zoom_inputs: InputQueue<f32>,
},
/// The camera can only zoom
Zoom {
/// A queue of zoom inputs.
zoom_inputs: InputQueue<f32>,
},
}
impl MotionInputs {
/// The motion-conserving smoothed orbit velocity in screen space.
pub fn smooth_orbit_velocity(&self) -> DVec2 {
if let Self::OrbitZoom {
screenspace_inputs, ..
} = self
{
let value = screenspace_inputs
.latest_smoothed()
.unwrap_or(Vec2::ZERO)
.as_dvec2();
if value.is_finite() {
value
} else {
DVec2::ZERO
}
} else {
DVec2::ZERO
}
}
/// The motion-conserving smoothed pan velocity in screen space.
pub fn smooth_pan_velocity(&self) -> DVec2 {
if let Self::PanZoom {
screenspace_inputs, ..
} = self
{
let value = screenspace_inputs
.latest_smoothed()
.unwrap_or(Vec2::ZERO)
.as_dvec2();
if value.is_finite() {
value
} else {
DVec2::ZERO
}
} else {
DVec2::ZERO
}
}
/// Approximate orbit velocity over the last `window`. to use for momentum calculations.
pub fn orbit_momentum(&self, window: Duration) -> DVec2 {
if let Self::OrbitZoom {
screenspace_inputs, ..
} = self
{
let velocity = screenspace_inputs.average_smoothed_value(window).as_dvec2();
if !velocity.is_finite() {
DVec2::ZERO
} else {
velocity
}
} else {
DVec2::ZERO
}
}
/// Approximate pan velocity over the last `window`. to use for momentum calculations.
pub fn pan_momentum(&self, window: Duration) -> DVec2 {
if let Self::PanZoom {
screenspace_inputs, ..
} = self
{
let velocity = screenspace_inputs.average_smoothed_value(window).as_dvec2();
if !velocity.is_finite() {
DVec2::ZERO
} else {
velocity
}
} else {
DVec2::ZERO
}
}
/// Motion-conserving smoothed zoom input velocity.
pub fn smooth_zoom_velocity(&self) -> f64 {
let velocity = self.zoom_inputs().latest_smoothed().unwrap_or(0.0) as f64;
if !velocity.is_finite() {
0.0
} else {
velocity
}
}
/// Get a reference to the queue of zoom inputs.
pub fn zoom_inputs(&self) -> &InputQueue<f32> {
match self {
MotionInputs::OrbitZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::PanZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::Zoom { zoom_inputs } => zoom_inputs,
}
}
/// Get a mutable reference to the queue of zoom inputs.
pub fn zoom_inputs_mut(&mut self) -> &mut InputQueue<f32> {
match self {
MotionInputs::OrbitZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::PanZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::Zoom { zoom_inputs } => zoom_inputs,
}
}
/// Approximate smoothed absolute value of the zoom velocity over the last `window`.
pub fn zoom_velocity_abs(&self, window: Duration) -> f64 {
let zoom_inputs = match self {
MotionInputs::OrbitZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::PanZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::Zoom { zoom_inputs } => zoom_inputs,
};
let velocity = zoom_inputs.approx_smoothed(window, |v| {
*v = v.abs();
}) as f64;
if !velocity.is_finite() {
0.0
} else {
velocity
}
}
}