diff options
Diffstat (limited to 'src/event_filter.rs')
-rw-r--r-- | src/event_filter.rs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/event_filter.rs b/src/event_filter.rs new file mode 100644 index 0000000..9eb4620 --- /dev/null +++ b/src/event_filter.rs @@ -0,0 +1,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 + } + } +} |