Skip to content

Commit

Permalink
feat: 🎸 bounce modes
Browse files Browse the repository at this point in the history
  • Loading branch information
theashraf committed Jan 15, 2024
1 parent 67ae22d commit 0a8cb2d
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 65 deletions.
5 changes: 2 additions & 3 deletions demo-player/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::fs::read_to_string;
use std::{env, path, time::Instant};

use dotlottie_player_core::{Config, DotLottiePlayer, Mode};
Expand Down Expand Up @@ -46,9 +45,9 @@ fn main() {
path.push("src/cartoon.json");

let mut lottie_player: DotLottiePlayer = DotLottiePlayer::new(Config {
mode: Mode::Reverse,
mode: Mode::ReverseBounce,
loop_animation: true,
speed: 2.5,
speed: 1.0,
use_frame_interpolation: true,
autoplay: true,
});
Expand Down
8 changes: 7 additions & 1 deletion dotlottie-ffi/src/dotlottie_player.udl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ namespace dotlottie_player {
enum Mode {
"Forward",
"Reverse",
"Bounce",
"ForwardBounce",
"ReverseBounce"
};

enum Direction {
"Forward",
"Reverse"
};

dictionary Config {
boolean autoplay;
boolean loop_animation;
Expand Down Expand Up @@ -40,4 +45,5 @@ interface DotLottiePlayer {
boolean render();
boolean resize(u32 width, u32 height);
void clear();
Direction direction();
};
158 changes: 110 additions & 48 deletions dotlottie-rs/src/dotlottie_player.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{sync::RwLock, time::SystemTime};

use crate::LottieRenderer;
use crate::lottie_renderer::{LottieRenderer, LottieRendererError};

pub enum PlaybackState {
Playing,
Expand All @@ -12,10 +12,16 @@ pub enum PlaybackState {
pub enum Mode {
Forward,
Reverse,
Bounce,
ForwardBounce,
ReverseBounce,
}

#[derive(PartialEq, Clone, Copy)]
pub enum Direction {
Forward,
Reverse,
}

#[derive(Clone, Copy)]
pub struct Config {
pub mode: Mode,
Expand All @@ -32,20 +38,33 @@ struct DotLottieRuntime {
start_time: SystemTime,
loop_count: u32,
config: Config,
direction: Direction,
}

impl DotLottieRuntime {
pub fn new(config: Config) -> Self {
let direction = match config.mode {
Mode::Forward => Direction::Forward,
Mode::Reverse => Direction::Reverse,
Mode::ForwardBounce => Direction::Forward,
Mode::ReverseBounce => Direction::Reverse,
};

DotLottieRuntime {
renderer: LottieRenderer::new(),
playback_state: PlaybackState::Stopped,
is_loaded: false,
start_time: SystemTime::now(),
loop_count: 0,
config,
direction,
}
}

pub fn direction(&self) -> Direction {
self.direction
}

pub fn is_loaded(&self) -> bool {
self.is_loaded
}
Expand Down Expand Up @@ -94,14 +113,16 @@ impl DotLottieRuntime {
pub fn stop(&mut self) -> bool {
if self.is_loaded {
self.playback_state = PlaybackState::Stopped;
let start_frame = 0_f32;
let end_frame = self.total_frames() - 1.0;

match self.config.mode {
Mode::Forward => {
self.set_frame(0_f32);
Mode::Forward | Mode::ForwardBounce => {
self.set_frame(start_frame);
}
Mode::Reverse => {
self.set_frame(self.total_frames());
Mode::Reverse | Mode::ReverseBounce => {
self.set_frame(end_frame);
}
_ => {}
}

true
Expand Down Expand Up @@ -133,10 +154,10 @@ impl DotLottieRuntime {
raw_next_frame.round()
};

let next_frame = match self.config.mode {
Mode::Forward => next_frame,
Mode::Reverse => total_frames - next_frame,
_ => next_frame,
// update the next frame based on the direction
let next_frame = match self.direction {
Direction::Forward => next_frame,
Direction::Reverse => total_frames - next_frame,
};

let next_frame = match self.config.mode {
Expand Down Expand Up @@ -166,7 +187,54 @@ impl DotLottieRuntime {
next_frame
}
}
_ => next_frame,
Mode::ForwardBounce => match self.direction {
Direction::Forward => {
if next_frame >= total_frames {
self.direction = Direction::Reverse;
self.start_time = SystemTime::now();
total_frames
} else {
next_frame
}
}
Direction::Reverse => {
if next_frame <= 0.0 {
if self.config.loop_animation {
self.loop_count += 1;
self.direction = Direction::Forward;
self.start_time = SystemTime::now();
}

0.0
} else {
next_frame
}
}
},
Mode::ReverseBounce => match self.direction {
Direction::Reverse => {
if next_frame <= 0.0 {
self.direction = Direction::Forward;
self.start_time = SystemTime::now();
0.0
} else {
next_frame
}
}
Direction::Forward => {
if next_frame >= total_frames {
if self.config.loop_animation {
self.loop_count += 1;
self.direction = Direction::Reverse;
self.start_time = SystemTime::now();
}

total_frames
} else {
next_frame
}
}
},
};

next_frame
Expand Down Expand Up @@ -216,58 +284,48 @@ impl DotLottieRuntime {
self.config = config;
}

pub fn load_animation_path(&mut self, animation_path: &str, width: u32, height: u32) -> bool {
let loaded = self
.renderer
.load_path(animation_path, width, height)
.is_ok();

fn load_animation_common<F>(&mut self, loader: F, width: u32, height: u32) -> bool
where
F: FnOnce(&mut LottieRenderer, u32, u32) -> Result<(), LottieRendererError>,
{
let loaded = loader(&mut self.renderer, width, height).is_ok();
self.is_loaded = loaded;

let total_frames = self.total_frames();
let first_frame = 0_f32;
let end_frame = self.total_frames() - 1.0;

match self.config.mode {
Mode::Forward => {
self.set_frame(0_f32);
Mode::Forward | Mode::ForwardBounce => {
self.set_frame(first_frame);
self.direction = Direction::Forward;
}
Mode::Reverse => {
self.set_frame(total_frames);
Mode::Reverse | Mode::ReverseBounce => {
self.set_frame(end_frame);
self.direction = Direction::Reverse;
}
_ => {}
}

if self.config.autoplay && loaded {
return self.play();
self.play();
}

loaded
}

pub fn load_animation_data(&mut self, animation_data: &str, width: u32, height: u32) -> bool {
let loaded = self
.renderer
.load_data(animation_data, width, height, false)
.is_ok();

self.is_loaded = loaded;

let total_frames = self.total_frames();

match self.config.mode {
Mode::Forward => {
self.set_frame(0_f32);
}
Mode::Reverse => {
self.set_frame(total_frames);
}
_ => {}
}

if self.config.autoplay && loaded {
return self.play();
}
self.load_animation_common(
|renderer, w, h| renderer.load_data(animation_data, w, h, false),
width,
height,
)
}

loaded
pub fn load_animation_path(&mut self, animation_path: &str, width: u32, height: u32) -> bool {
self.load_animation_common(
|renderer, w, h| renderer.load_path(animation_path, w, h),
width,
height,
)
}

pub fn resize(&mut self, width: u32, height: u32) -> bool {
Expand Down Expand Up @@ -391,6 +449,10 @@ impl DotLottiePlayer {
pub fn config(&self) -> Config {
self.runtime.read().unwrap().config()
}

pub fn direction(&self) -> Direction {
self.runtime.read().unwrap().direction()
}
}

unsafe impl Send for DotLottiePlayer {}
Expand Down
13 changes: 0 additions & 13 deletions dotlottie-rs/src/main.rs

This file was deleted.

0 comments on commit 0a8cb2d

Please sign in to comment.