Skip to content

Commit

Permalink
wip: multi animation support
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelOsborne committed Jan 17, 2024
1 parent 8511f93 commit 76f5dc8
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 72 deletions.
4 changes: 3 additions & 1 deletion dotlottie-ffi/src/dotlottie_player.udl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ interface DotLottiePlayer {
boolean set_frame(f32 no);
boolean render();
boolean resize(u32 width, u32 height);
boolean load_dotlottie([ByRef] bytes file_data);
boolean load_dotlottie([ByRef] bytes file_data, u32 width, u32 height);
boolean next_animation(u32 width, u32 height);
boolean previous_animation(u32 width, u32 height);
void clear();
};
147 changes: 81 additions & 66 deletions dotlottie-fms/src/dolottie_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub struct DotLottieManager {
manifest: Manifest,
zip_data: Vec<u8>,
animation_settings_cache: HashMap<String, ManifestAnimation>,
animation_data_cache: HashMap<String, String>,
}

impl DotLottieManager {
Expand All @@ -29,57 +30,20 @@ impl DotLottieManager {
manifest,
zip_data: dotlottie,
animation_settings_cache: HashMap::new(),
animation_data_cache: HashMap::new(),
}
} else {
DotLottieManager {
current_animation_id: String::new(),
manifest: Manifest::new(),
zip_data: vec![],
animation_settings_cache: HashMap::new(),
animation_data_cache: HashMap::new(),
}
}

// // Initialize the manager with the dotLottie file
// let manifest = get_manifest(&dotlottie).unwrap();
// let mut id = String::new();

// if let Some(first_animation) = &manifest.active_animation_id {
// id = first_animation.clone();
// } else if let Ok(animations) = manifest.animations.lock() {
// id = animations.index(0).id.clone();
// } else {
// panic!("No animations found in dotLottie file");
// }

// DotLottieManager {
// current_animation_id: String::new(),
// manifest: Manifest::new(),
// zip_data: vec![],
// animation_settings_cache: HashMap::new(),
// }
}

// pub fn new() -> Self {
// Initialize the manager with the dotLottie file
// let manifest = get_manifest(&dotlottie).unwrap();
// let mut id = String::new();

// if let Some(first_animation) = &manifest.active_animation_id {
// id = first_animation.clone();
// } else if let Ok(animations) = manifest.animations.lock() {
// id = animations.index(0).id.clone();
// } else {
// panic!("No animations found in dotLottie file");
// }
// DotLottieManager {
// current_animation_id: String::new(),
// manifest: Manifest::new(),
// zip_data: vec![],
// animation_settings_cache: HashMap::new(),
// }
// }

pub fn init(dotlottie: Vec<u8>) -> Self {
pub fn init(&mut self, dotlottie: Vec<u8>) {
// Initialize the manager with the dotLottie file
let manifest = get_manifest(&dotlottie).unwrap();
let mut id = String::new();
Expand All @@ -92,49 +56,75 @@ impl DotLottieManager {
panic!("No animations found in dotLottie file");
}

DotLottieManager {
current_animation_id: id,
manifest,
zip_data: dotlottie,
animation_settings_cache: HashMap::new(),
}
self.current_animation_id = id;
self.manifest = manifest;
self.zip_data = dotlottie;
}

/// Advances to the next animation and returns it's animation data as a string.
pub fn next_animation(&mut self) -> Result<String, DotLottieError> {
let mut i = 0;
let mut new_current_animation_id = self.current_animation_id.clone();
let animations = self.manifest.animations.lock().unwrap();

if let Ok(animations) = self.manifest.animations.lock() {
for anim in animations.iter() {
if anim.id == self.current_animation_id {
// return Result::Ok(true);
if i + 1 < animations.len() {
self.current_animation_id = animations[i + 1].id.clone();
}
// match animations {
// Ok(animations) => {
for anim in animations.iter() {
println!("Animation ID {}", anim.id);

if anim.id == self.current_animation_id {
// return Result::Ok(true);
if i + 1 < animations.len() {
self.current_animation_id = animations[i + 1].id.clone();

new_current_animation_id = animations[i + 1].id.clone();
std::mem::drop(animations);

println!("Found next animation : {}", new_current_animation_id);

return self.get_animation(&new_current_animation_id);
}
i += 1;
}
i += 1;
}

self.get_animation(&self.current_animation_id)
std::mem::drop(animations);

let current_animation_id = self.current_animation_id.clone();

return self.get_animation(&current_animation_id);
}

/// Reverses to the previous animation and returns it's animation data as a string.
pub fn previous_animation(&mut self) -> Result<String, DotLottieError> {
if let Ok(animations) = self.manifest.animations.lock() {
let mut i = animations.len();
let mut new_current_animation_id = self.current_animation_id.clone();
let animations = self.manifest.animations.lock().unwrap();
let mut i = 0;

for anim in animations.iter() {
if anim.id == self.current_animation_id {
if i - 1 > 0 {
self.current_animation_id = animations[i + 1].id.clone();
}
for anim in animations.iter() {
println!("Animation ID {}", anim.id);

if anim.id == self.current_animation_id {
// return Result::Ok(true);
if i > 0 {
self.current_animation_id = animations[i - 1].id.clone();

new_current_animation_id = animations[i - 1].id.clone();
std::mem::drop(animations);

println!("Found next animation : {}", new_current_animation_id);

return self.get_animation(&new_current_animation_id);
}
i -= 1;
}
i += 1;
}
std::mem::drop(animations);

self.get_animation(&self.current_animation_id)
let current_animation_id = self.current_animation_id.clone();

println!("PREVIOUS ANIMATION ID {}", current_animation_id);
self.get_animation(&current_animation_id)
}

/// Returns the playback settings for the animation with the given ID.
Expand Down Expand Up @@ -177,6 +167,12 @@ impl DotLottieManager {
return Result::Err(DotLottieError::MutexLockError);
}

pub fn get_current_animation(&mut self) -> Result<String, DotLottieError> {
let current_animation_id = self.current_animation_id.clone();

self.get_animation(&current_animation_id)
}

pub fn current_animation_playback_settings(
&mut self,
) -> Result<ManifestAnimation, DotLottieError> {
Expand All @@ -185,8 +181,27 @@ impl DotLottieManager {
self.get_playback_settings(&animation_id)
}

pub fn get_animation(&self, animation_id: &str) -> Result<String, DotLottieError> {
crate::get_animation(&self.zip_data, animation_id)
/// Returns the animation data for the animation with the given ID.
/// Memoizes the animation data in a HashMap for faster access.
pub fn get_animation(&mut self, animation_id: &str) -> Result<String, DotLottieError> {
if let Some(animation) = self.animation_data_cache.get(animation_id) {
let cloned_animation = animation.clone(); // Clone the value

return Result::Ok(cloned_animation);
} else {
let animation = crate::get_animation(&self.zip_data, animation_id);

if let Ok(animation) = animation {
self.animation_data_cache
.insert(animation_id.to_string().clone(), animation.clone());

return Result::Ok(animation);
} else {
return Result::Err(DotLottieError::AnimationNotFound {
animation_id: animation_id.to_string(),
});
}
}
}

pub fn get_animations(&self) -> Result<Vec<Animation>, DotLottieError> {
Expand Down
10 changes: 10 additions & 0 deletions dotlottie-fms/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,13 @@ pub fn get_manifest(bytes: &Vec<u8>) -> Result<Manifest, DotLottieError> {

Ok(manifest)
}

/// Get the width and height of a dotLottie file.
pub fn get_width_height(animation_data: &str) -> (u32, u32) {
let lottie_animation: Value = serde_json::from_str(animation_data).unwrap();

let width = lottie_animation["w"].as_u64().unwrap() as u32;
let height = lottie_animation["h"].as_u64().unwrap() as u32;

(width, height)
}
89 changes: 84 additions & 5 deletions dotlottie-rs/src/dotlottie_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,27 @@ impl DotLottieRuntime {
}
}

pub fn load_dotlottie(&self, file_data: &Vec<u8>) -> bool {
let animations = dotlottie_fms::get_animations(&file_data);
pub fn load_dotlottie(&self, file_data: &Vec<u8>, width: u32, height: u32) -> bool {
self.dotlottie_manager
.write()
.unwrap()
.init(file_data.clone());

// let animations = self.dotlottie_manager.read().unwrap().get_animations();

let first_animation = self
.dotlottie_manager
.write()
.unwrap()
.get_current_animation();

match animations {
match first_animation {
Ok(animation_data) => {
let first_animation = &animation_data[0];
// let (width, height) = get_width_height(&animation_data);

return self.load_animation(&first_animation.animation_data, 512, 512);
println!("{}", animation_data);

return self.load_animation(&animation_data, width, height);
}
Err(error) => {
// Handle the error case
Expand All @@ -146,6 +159,72 @@ impl DotLottieRuntime {
}
}

pub fn next_animation(&self, width: u32, height: u32) -> bool {
let animation_data = self.dotlottie_manager.write().unwrap().next_animation();

match animation_data {
Ok(animation_data) => {
// let (width, height) = get_width_height(&animsation_data);

self.clear();
let mut canvas = self.canvas.write().unwrap();
*canvas = thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0);

let mut animation = self.animation.write().unwrap();
*animation = thorvg::Animation::new();

let mut buffer_lock = self.buffer.lock().unwrap();
*buffer_lock = vec![];

std::mem::drop(buffer_lock);
std::mem::drop(canvas);
std::mem::drop(animation);

return self.load_animation(&animation_data, width, height);
}
Err(error) => {
// Handle the error case
eprintln!("Error: {:?}", error);

return false;
// Perform error handling or return early, depending on your needs
}
}
}

pub fn previous_animation(&self, width: u32, height: u32) -> bool {
let animation_data = self.dotlottie_manager.write().unwrap().previous_animation();

match animation_data {
Ok(animation_data) => {
// let (width, height) = get_width_height(&animsation_data);

self.clear();
let mut canvas = self.canvas.write().unwrap();
*canvas = thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0);

let mut animation = self.animation.write().unwrap();
*animation = thorvg::Animation::new();

let mut buffer_lock = self.buffer.lock().unwrap();
*buffer_lock = vec![];

std::mem::drop(buffer_lock);
std::mem::drop(canvas);
std::mem::drop(animation);

return self.load_animation(&animation_data, width, height);
}
Err(error) => {
// Handle the error case
eprintln!("Error: {:?}", error);

return false;
// Perform error handling or return early, depending on your needs
}
}
}

pub fn request_frame(&mut self) -> f32 {
if !self.is_loaded || !self.is_playing() {
return self.current_frame();
Expand Down

0 comments on commit 76f5dc8

Please sign in to comment.