From 4fa4f472c4d5e79c9eb24ee729323ec5ae3525a0 Mon Sep 17 00:00:00 2001 From: Abdelrahman Ashraf Date: Sat, 13 Apr 2024 14:55:19 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20failed=20to=20reach=20end?= =?UTF-8?q?=20frame=20on=20frame=20interpolation=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dotlottie-rs/benches/benchmarks.rs | 1 - dotlottie-rs/src/dotlottie_player.rs | 32 ++++++--- dotlottie-rs/tests/autoplay.rs | 1 - dotlottie-rs/tests/events.rs | 12 ++-- dotlottie-rs/tests/markers.rs | 2 - dotlottie-rs/tests/play_mode.rs | 4 -- dotlottie-rs/tests/speed.rs | 98 +++++++++++++--------------- dotlottie-rs/tests/stop.rs | 8 --- 8 files changed, 75 insertions(+), 83 deletions(-) diff --git a/dotlottie-rs/benches/benchmarks.rs b/dotlottie-rs/benches/benchmarks.rs index 64ee3888..4291b2ba 100644 --- a/dotlottie-rs/benches/benchmarks.rs +++ b/dotlottie-rs/benches/benchmarks.rs @@ -43,7 +43,6 @@ fn animation_loop_benchmark(c: &mut Criterion) { let player = DotLottiePlayer::new(Config { autoplay: true, loop_animation: true, - use_frame_interpolation: false, ..Config::default() }); diff --git a/dotlottie-rs/src/dotlottie_player.rs b/dotlottie-rs/src/dotlottie_player.rs index 229a0b9e..13b2e842 100644 --- a/dotlottie-rs/src/dotlottie_player.rs +++ b/dotlottie-rs/src/dotlottie_player.rs @@ -83,6 +83,8 @@ impl Default for Config { } } +const FRAME_DIFF_THRESHOLD: f32 = 0.001; + struct DotLottieRuntime { renderer: LottieRenderer, playback_state: PlaybackState, @@ -274,21 +276,35 @@ impl DotLottieRuntime { let raw_next_frame = (elapsed_time / effective_duration) * effective_total_frames; // update the next frame based on the direction - let next_frame = match self.direction { + let mut next_frame = match self.direction { Direction::Forward => start_frame + raw_next_frame, Direction::Reverse => end_frame - raw_next_frame, }; - let next_frame = if self.config.use_frame_interpolation { - next_frame - } else { - next_frame.round() + if !self.config.use_frame_interpolation { + next_frame = next_frame.round(); + } + + /* + Note: + If we're close to the end frame, we should snap to it as tvg_set_frame ignore the frame which is 0.001 less than the current frame. + */ + match self.direction { + Direction::Forward => { + if (next_frame - end_frame).abs() < FRAME_DIFF_THRESHOLD { + next_frame = end_frame; + } + } + Direction::Reverse => { + if (next_frame - start_frame).abs() < FRAME_DIFF_THRESHOLD { + next_frame = start_frame + } + } }; - // to ensure the next_frame won't go beyond the start & end frames - let next_frame = next_frame.clamp(start_frame, end_frame); + next_frame = next_frame.clamp(start_frame, end_frame); - let next_frame = match self.config.mode { + next_frame = match self.config.mode { Mode::Forward => self.handle_forward_mode(next_frame, end_frame), Mode::Reverse => self.handle_reverse_mode(next_frame, start_frame), Mode::Bounce => self.handle_bounce_mode(next_frame, start_frame, end_frame), diff --git a/dotlottie-rs/tests/autoplay.rs b/dotlottie-rs/tests/autoplay.rs index ea661ae5..8b059a8f 100644 --- a/dotlottie-rs/tests/autoplay.rs +++ b/dotlottie-rs/tests/autoplay.rs @@ -30,7 +30,6 @@ mod tests { fn test_autoplay() { let player = DotLottiePlayer::new(Config { autoplay: true, - use_frame_interpolation: false, ..Config::default() }); diff --git a/dotlottie-rs/tests/events.rs b/dotlottie-rs/tests/events.rs index 0e7f7e79..f2d0a5d0 100644 --- a/dotlottie-rs/tests/events.rs +++ b/dotlottie-rs/tests/events.rs @@ -70,13 +70,11 @@ mod tests { #[test] fn test_subscribe_unsubscribe() { - let player = - DotLottiePlayer::new(Config { - autoplay: true, - loop_animation: true, - use_frame_interpolation: false, - ..Config::default() - }); + let player = DotLottiePlayer::new(Config { + autoplay: true, + loop_animation: true, + ..Config::default() + }); let events = Arc::new(Mutex::new(vec![])); let observer_events = Arc::clone(&events); diff --git a/dotlottie-rs/tests/markers.rs b/dotlottie-rs/tests/markers.rs index 6278d3f9..6ccb7e68 100644 --- a/dotlottie-rs/tests/markers.rs +++ b/dotlottie-rs/tests/markers.rs @@ -22,7 +22,6 @@ mod tests { fn test_markers() { let player = DotLottiePlayer::new(Config { autoplay: true, - use_frame_interpolation: false, ..Config::default() }); @@ -82,7 +81,6 @@ mod tests { fn test_set_marker() { let player = DotLottiePlayer::new(Config { autoplay: true, - use_frame_interpolation: false, ..Config::default() }); diff --git a/dotlottie-rs/tests/play_mode.rs b/dotlottie-rs/tests/play_mode.rs index d9d80817..8fc7bd26 100644 --- a/dotlottie-rs/tests/play_mode.rs +++ b/dotlottie-rs/tests/play_mode.rs @@ -84,7 +84,6 @@ mod play_mode_tests { let player = DotLottiePlayer::new(Config { mode: Mode::Forward, autoplay: true, - use_frame_interpolation: false, ..Config::default() }); @@ -133,7 +132,6 @@ mod play_mode_tests { let player = DotLottiePlayer::new(Config { mode: Mode::Reverse, autoplay: true, - use_frame_interpolation: false, ..Config::default() }); @@ -180,7 +178,6 @@ mod play_mode_tests { let player = DotLottiePlayer::new(Config { mode: Mode::Bounce, autoplay: true, - use_frame_interpolation: false, ..Config::default() }); @@ -247,7 +244,6 @@ mod play_mode_tests { let player = DotLottiePlayer::new(Config { mode: Mode::ReverseBounce, autoplay: true, - use_frame_interpolation: false, ..Config::default() }); diff --git a/dotlottie-rs/tests/speed.rs b/dotlottie-rs/tests/speed.rs index f888f8bf..000d587d 100644 --- a/dotlottie-rs/tests/speed.rs +++ b/dotlottie-rs/tests/speed.rs @@ -28,58 +28,52 @@ mod tests { #[test] fn test_playback_speed_accuracy() { - let configs: Vec<(Config, f32)> = - vec![ - // test with default config - ( - Config { - autoplay: true, - use_frame_interpolation: false, - ..Config::default() - }, - 1.0, - ), - // test with different speeds - ( - Config { - speed: 2.0, - autoplay: true, - use_frame_interpolation: false, - ..Config::default() - }, - 2.0, - ), - ( - Config { - speed: 0.5, - autoplay: true, - use_frame_interpolation: false, - ..Config::default() - }, - 0.5, - ), - // test with a segment - ( - Config { - speed: 2.0, - segment: vec![10.0, 30.0], - autoplay: true, - use_frame_interpolation: false, - ..Config::default() - }, - 2.0, - ), - ( - Config { - speed: 0.4, - autoplay: true, - segment: vec![10.0, 30.0], - use_frame_interpolation: false, - ..Config::default() - }, - 0.4, - ), - ]; + let configs: Vec<(Config, f32)> = vec![ + // test with default config + ( + Config { + autoplay: true, + ..Config::default() + }, + 1.0, + ), + // test with different speeds + ( + Config { + speed: 2.0, + autoplay: true, + ..Config::default() + }, + 2.0, + ), + ( + Config { + speed: 0.5, + autoplay: true, + ..Config::default() + }, + 0.5, + ), + // test with a segment + ( + Config { + speed: 2.0, + segment: vec![10.0, 30.0], + autoplay: true, + ..Config::default() + }, + 2.0, + ), + ( + Config { + speed: 0.4, + autoplay: true, + segment: vec![10.0, 30.0], + ..Config::default() + }, + 0.4, + ), + ]; for (config, expected_speed) in configs { let player = DotLottiePlayer::new(config); diff --git a/dotlottie-rs/tests/stop.rs b/dotlottie-rs/tests/stop.rs index 1aac947d..4b5c762c 100644 --- a/dotlottie-rs/tests/stop.rs +++ b/dotlottie-rs/tests/stop.rs @@ -13,53 +13,45 @@ mod tests { let configs: Vec = vec![ Config { autoplay: true, - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::Reverse, autoplay: true, - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::Bounce, autoplay: true, - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::ReverseBounce, autoplay: true, - use_frame_interpolation: false, ..Config::default() }, // test with different segments Config { autoplay: true, segment: vec![10.0, 30.0], - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::Reverse, autoplay: true, segment: vec![10.0, 30.0], - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::Bounce, autoplay: true, segment: vec![10.0, 30.0], - use_frame_interpolation: false, ..Config::default() }, Config { mode: Mode::ReverseBounce, autoplay: true, segment: vec![10.0, 30.0], - use_frame_interpolation: false, ..Config::default() }, ];