ltk/input/gesture/
fling.rsuse std::collections::VecDeque;
pub const FLING_VELOCITY: f32 = 500.0;
pub const FLING_MIN_TRAVEL: f32 = 24.0;
#[ derive( Debug, Clone, Default ) ]
pub struct FlingTracker
{
samples: VecDeque<( u32, f32 )>,
}
impl FlingTracker
{
const WINDOW_MS: u32 = 100;
pub fn clear( &mut self ) { self.samples.clear(); }
pub fn push( &mut self, time_ms: u32, pos: f32 )
{
self.samples.push_back( ( time_ms, pos ) );
while let Some( &( t, _ ) ) = self.samples.front()
{
if time_ms.wrapping_sub( t ) <= Self::WINDOW_MS { break; }
self.samples.pop_front();
}
}
pub fn velocity( &self ) -> f32
{
let ( Some( &( t0, p0 ) ), Some( &( t1, p1 ) ) ) = ( self.samples.front(), self.samples.back() ) else
{
return 0.0;
};
let dt = t1.wrapping_sub( t0 );
if dt < 8 { return 0.0; }
( p1 - p0 ) * 1000.0 / dt as f32
}
}
#[ cfg( test ) ]
mod tests
{
use super::*;
#[ test ]
fn measures_recent_speed()
{
let mut t = FlingTracker::default();
t.push( 0, 0.0 );
t.push( 20, 10.0 );
t.push( 40, 20.0 );
assert!( ( t.velocity() - 500.0 ).abs() < 1e-3 );
}
#[ test ]
fn forgets_a_rest_before_lifting()
{
let mut t = FlingTracker::default();
t.push( 0, 0.0 );
t.push( 20, 40.0 );
t.push( 300, 40.0 );
assert_eq!( t.velocity(), 0.0 );
}
}