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
|
use crate::cirque::TouchData;
use core::{
cmp,
ops::Sub,
};
#[derive(Copy, Clone, Debug)]
pub struct Point<T>(pub T, pub T);
impl<T> Point<T>
where
T: Sub<Output = T>,
{
pub fn delta(self, p: Point<T>) -> Point<T> {
Point(p.0 - self.0, p.1 - self.1)
}
}
impl Point<isize> {
pub fn scale(self) -> Self {
Point(self.0 >> 2, self.1 >> 2)
}
}
impl From<&TouchData> for Point<isize> {
fn from(td: &TouchData) -> Self {
Self(td.x as _, td.y as _)
}
}
impl From<Point<isize>> for Point<i8> {
fn from(p: Point<isize>) -> Self {
Point(
cmp::min(i8::MAX as isize, cmp::max(p.0, i8::MIN as isize)) as i8,
cmp::min(i8::MAX as isize, cmp::max(p.1, i8::MIN as isize)) as i8,
)
}
}
pub struct AbsToRel {
last_touch: Point<isize>,
is_collecting: bool,
}
impl AbsToRel {
pub fn new() -> Self {
Self {
last_touch: Point(0, 0),
is_collecting: false,
}
}
pub fn update(&mut self, td: &TouchData) -> Option<Point<i8>> {
let p: Point<isize> = td.into();
let p = p.scale();
let res = self.last_touch.delta(p);
self.last_touch = p;
if self.is_collecting && td.is_pressed {
Some(res.into())
} else {
self.is_collecting = td.is_pressed;
None
}
}
}
pub struct TrackBall(Point<i8>, i8, u32);
impl TrackBall
where
{
pub fn new(friction: i8) -> Self {
Self(Point(i8::default(), i8::default()), friction, 0)
}
pub fn update(&mut self, point: Option<Point<i8>>, elapsed: u32) -> Point<i8> {
if let Some(p) = point {
self.0 = p;
self.2 = 0;
} else {
let elapsed = elapsed + self.2;
// TODO: configure time divisor
let decel: i8 = self.1.saturating_mul((elapsed >> 15).try_into().unwrap_or(i8::MAX));
let rem = elapsed & (1 << 15) - 1;
self.2 = rem;
if decel > 0 {
let x = Self::abs_add(self.0.0, decel);
let y = Self::abs_add(self.0.1, decel);
self.0 = Point(x, y);
}
}
self.0
}
fn abs_add(speed: i8, decel: i8) -> i8 {
if speed > decel {
speed - decel
} else if speed < -decel {
speed + decel
} else {
0
}
}
}
|