@@ -45,60 +45,52 @@ pub struct TweenCompleted {
45
45
#[ derive( Debug , Default , Clone , Copy ) ]
46
46
struct AnimClock {
47
47
elapsed : Duration ,
48
- total : Duration ,
48
+ duration : Duration ,
49
49
is_looping : bool ,
50
50
}
51
51
52
52
impl AnimClock {
53
53
fn new ( duration : Duration , is_looping : bool ) -> Self {
54
54
AnimClock {
55
55
elapsed : Duration :: ZERO ,
56
- total : duration,
56
+ duration,
57
57
is_looping,
58
58
}
59
59
}
60
60
61
- #[ allow( dead_code) ] // TEMP
62
- fn elapsed ( & self ) -> Duration {
63
- self . elapsed
64
- }
61
+ fn tick ( & mut self , duration : Duration ) -> u32 {
62
+ self . elapsed = self . elapsed . saturating_add ( duration) ;
65
63
66
- fn total ( & self ) -> Duration {
67
- self . total
68
- }
64
+ if self . elapsed < self . duration {
65
+ 0
66
+ } else if self . is_looping {
67
+ let elapsed = self . elapsed . as_nanos ( ) ;
68
+ let duration = self . duration . as_nanos ( ) ;
69
69
70
- fn tick ( & mut self , duration : Duration ) -> u32 {
71
- let new_elapsed = self . elapsed . saturating_add ( duration) ;
72
- let progress = new_elapsed. as_secs_f64 ( ) / self . total . as_secs_f64 ( ) ;
73
- let times_completed = progress as u32 ;
74
- let progress = if self . is_looping {
75
- progress. fract ( )
70
+ self . elapsed = Duration :: from_nanos ( ( elapsed % duration) as u64 ) ;
71
+ ( elapsed / duration) as u32
76
72
} else {
77
- progress. min ( 1. )
78
- } ;
79
- self . elapsed = self . total . mul_f64 ( progress) ;
80
- times_completed
73
+ self . elapsed = self . duration ;
74
+ 1
75
+ }
81
76
}
82
77
83
- fn set_progress ( & mut self , progress : f32 ) -> u32 {
84
- let progress = progress. max ( 0. ) ;
85
- let times_completed = progress as u32 ;
78
+ fn set_progress ( & mut self , progress : f32 ) {
86
79
let progress = if self . is_looping {
87
- progress. fract ( )
80
+ progress. max ( 0. ) . fract ( )
88
81
} else {
89
- progress. min ( 1. )
82
+ progress. clamp ( 0. , 1. )
90
83
} ;
91
- self . elapsed = self . total . mul_f32 ( progress ) ;
92
- times_completed
84
+
85
+ self . elapsed = self . duration . mul_f32 ( progress ) ;
93
86
}
94
87
95
88
fn progress ( & self ) -> f32 {
96
- //self.elapsed.div_duration_f32(self.total) // TODO: unstable
97
- ( self . elapsed . as_secs_f64 ( ) / self . total . as_secs_f64 ( ) ) as f32
89
+ self . elapsed . as_secs_f32 ( ) / self . duration . as_secs_f32 ( )
98
90
}
99
91
100
92
fn completed ( & self ) -> bool {
101
- self . elapsed >= self . total
93
+ self . elapsed >= self . duration
102
94
}
103
95
104
96
fn reset ( & mut self ) {
@@ -408,7 +400,7 @@ impl<T> Tween<T> {
408
400
409
401
impl < T > Tweenable < T > for Tween < T > {
410
402
fn duration ( & self ) -> Duration {
411
- self . clock . total ( )
403
+ self . clock . duration
412
404
}
413
405
414
406
fn is_looping ( & self ) -> bool {
@@ -808,6 +800,36 @@ mod tests {
808
800
last_reported_count : u32 ,
809
801
}
810
802
803
+ #[ test]
804
+ fn anim_clock_precision ( ) {
805
+ let duration = Duration :: from_millis ( 1 ) ;
806
+ let mut clock = AnimClock :: new ( duration, true ) ;
807
+
808
+ let test_ticks = [
809
+ Duration :: from_micros ( 123 ) ,
810
+ Duration :: from_millis ( 1 ) ,
811
+ Duration :: from_secs_f32 ( 1. / 24. ) ,
812
+ Duration :: from_secs_f32 ( 1. / 30. ) ,
813
+ Duration :: from_secs_f32 ( 1. / 60. ) ,
814
+ Duration :: from_secs_f32 ( 1. / 120. ) ,
815
+ Duration :: from_secs_f32 ( 1. / 144. ) ,
816
+ Duration :: from_secs_f32 ( 1. / 240. ) ,
817
+ ] ;
818
+
819
+ let mut times_completed = 0 ;
820
+ let mut total_duration = Duration :: ZERO ;
821
+ for i in 0 ..10_000_000 {
822
+ let tick = test_ticks[ i % test_ticks. len ( ) ] ;
823
+ times_completed += clock. tick ( tick) ;
824
+ total_duration += tick;
825
+ }
826
+
827
+ assert_eq ! (
828
+ ( total_duration. as_secs_f64( ) / duration. as_secs_f64( ) ) as u32 ,
829
+ times_completed
830
+ ) ;
831
+ }
832
+
811
833
/// Test ticking of a single tween in isolation.
812
834
#[ test]
813
835
fn tween_tick ( ) {
0 commit comments