Skip to content

Commit

Permalink
feat: added crate to manage .lotties (#23)
Browse files Browse the repository at this point in the history
* feat: added crate to manage .lotties

* feat: added dotlottie_manager

* wip: multi animation support

* chore: debug for ashraf

* chore: clean up

* chore: removed log

* feat: added playback setting loading

* fix: comments

* feat: added manifest(), emscripten bindings + udl bindings

* fix: bindings

* chore: 🤖 fix emscripten target for fms crate

* fix: bindings

* fix: 🐛 emscripten-bindings

* chore: 🤖 skip .d.ts generation

* chore: 🤖 update emscripten-bindings for load_dotlottie_data

* feat: 🎸 add manifest_string

* fix: 🐛 panic when call manifest for a lottie json

* chore: 🤖 fix typo

* chore: 🤖 uncomment ts gen

---------

Co-authored-by: Abdelrahman Ashraf <a.theashraf@gmail.com>
  • Loading branch information
samuelOsborne and theashraf authored Jan 22, 2024
1 parent 8d88861 commit 68201b4
Show file tree
Hide file tree
Showing 30 changed files with 1,367 additions and 14 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"rust-analyzer.linkedProjects": [
"./dotlottie-rs/Cargo.toml",
"./dotlottie-ffi/Cargo.toml",
"./dotlottie-fms/Cargo.toml",
"./demo-player/Cargo.toml"
],
"C_Cpp.errorSquiggles": "disabled"
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ cpp_link_args = [
'-sDYNAMIC_EXECUTION=0',
'--no-entry',
'--strip-all',
'--minify=0',
'--embind-emit-tsd=${WASM_MODULE}.d.ts']
'--embind-emit-tsd=${WASM_MODULE}.d.ts',
'--minify=0']

[host_machine]
system = '$(SYSTEM)'
Expand Down
Binary file added demo-player/src/emoji.lottie
Binary file not shown.
24 changes: 21 additions & 3 deletions demo-player/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fs::{self, File};
use std::io::Read;
use std::{env, path, time::Instant};

use dotlottie_player_core::{Config, DotLottiePlayer, Mode};
Expand All @@ -20,7 +22,7 @@ impl Timer {
fn tick(&mut self, animation: &mut DotLottiePlayer) {
let next_frame = animation.request_frame();

println!("next_frame: {}", next_frame);
// println!("next_frame: {}", next_frame);
animation.set_frame(next_frame);
animation.render();

Expand Down Expand Up @@ -53,14 +55,30 @@ fn main() {
segments: vec![10.0, 45.0],
background_color: 0xffffffff,
});
lottie_player.load_animation_path(path.to_str().unwrap(), WIDTH as u32, HEIGHT as u32);
// lottie_player.set_background_color(0x00ffffff);

// read dotlottie in to vec<u8>
let mut f = File::open("src/cartoon.json").expect("no file found");
let metadata = fs::metadata("src/cartoon.json").expect("unable to read metadata");

let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer).expect("buffer overflow");

let string = String::from_utf8(buffer.clone()).unwrap();
lottie_player.load_animation_data(string.as_str(), WIDTH as u32, HEIGHT as u32);
println!("{:?}", Some(lottie_player.manifest()));

// lottie_player.load_dotlottie_data(&buffer, WIDTH as u32, HEIGHT as u32);
// lottie_player.load_animation("confused", WIDTH as u32, HEIGHT as u32);

let mut timer = Timer::new();

while window.is_open() && !window.is_key_down(Key::Escape) {
timer.tick(&mut lottie_player);

// if window.is_key_down(Key::Space) {
// lottie_player.next_animation(WIDTH as u32, HEIGHT as u32);
// }

let (buffer_ptr, buffer_len) = (lottie_player.buffer_ptr(), lottie_player.buffer_len());

let buffer =
Expand Down
1 change: 1 addition & 0 deletions dotlottie-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ path = "uniffi-bindgen.rs"
uniffi = { version = "0.25.3", features = ["cli"] }
# Core runtime
dotlottie_player = { path = "../dotlottie-rs" }
dotlottie_fms = { path = "../dotlottie-fms" }

[build-dependencies]
uniffi = { version = "0.25.3", features = ["build"] }
Expand Down
43 changes: 43 additions & 0 deletions dotlottie-ffi/emscripten_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ val buffer(DotLottiePlayer &player)
return val(typed_memory_view(buffer_len, reinterpret_cast<uint8_t *>(buffer_ptr)));
}

bool load_dotlottie_data(DotLottiePlayer &player, std::string data, uint32_t width, uint32_t height)
{
std::vector<char> data_vector(data.begin(), data.end());

return player.load_dotlottie_data(data_vector, width, height);
}

EMSCRIPTEN_BINDINGS(DotLottiePlayer)
{

Expand All @@ -32,6 +39,38 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
.field("segments", &Config::segments)
.field("backgroundColor", &Config::background_color);

// value_object<ManifestTheme>("ManifestTheme")
// .field("id", &ManifestTheme::id)
// .field("values", &ManifestTheme::values);

// value_object<ManifestThemes>("ManifestThemes")
// .field("value", &ManifestThemes::value);

// value_object<ManifestAnimation>("ManifestAnimation")
// .field("autoplay", &ManifestAnimation::autoplay)
// .field("defaultTheme", &ManifestAnimation::default_theme)
// .field("direction", &ManifestAnimation::direction)
// .field("hover", &ManifestAnimation::hover)
// .field("id", &ManifestAnimation::id)
// .field("intermission", &ManifestAnimation::intermission)
// .field("loop", &ManifestAnimation::loop)
// .field("loop_count", &ManifestAnimation::loop_count)
// .field("playMode", &ManifestAnimation::play_mode)
// .field("speed", &ManifestAnimation::speed)
// .field("themeColor", &ManifestAnimation::theme_color);

// value_object<Manifest>("Manifest")
// .field("active_animation_id", &Manifest::active_animation_id)
// .field("animations", &Manifest::animations)
// .field("author", &Manifest::author)
// .field("description", &Manifest::description)
// .field("generator", &Manifest::generator)
// .field("keywords", &Manifest::keywords)
// .field("revision", &Manifest::revision)
// .field("themes", &Manifest::themes)
// .field("states", &Manifest::states)
// .field("version", &Manifest::version);

class_<DotLottiePlayer>("DotLottiePlayer")
.constructor(&DotLottiePlayer::init, allow_raw_pointers())
.function("buffer", &buffer)
Expand All @@ -45,6 +84,10 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
.function("isStopped", &DotLottiePlayer::is_stopped)
.function("loadAnimationData", &DotLottiePlayer::load_animation_data, allow_raw_pointers())
.function("loadAnimationPath", &DotLottiePlayer::load_animation_path, allow_raw_pointers())
.function("loadDotLottieData", &load_dotlottie_data, allow_raw_pointers())
.function("loadAnimation", &DotLottiePlayer::load_animation, allow_raw_pointers())
// FIXME: .function("manifest", &DotLottiePlayer::manifest)
.function("manifestString", &DotLottiePlayer::manifest_string)
.function("loopCount", &DotLottiePlayer::loop_count)
.function("pause", &DotLottiePlayer::pause)
.function("play", &DotLottiePlayer::play)
Expand Down
40 changes: 40 additions & 0 deletions dotlottie-ffi/src/dotlottie_player.udl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,50 @@ dictionary Config {
u32 background_color;
};

dictionary ManifestTheme {
string id;
sequence<string> values;
};

dictionary ManifestThemes {
sequence<ManifestTheme>? value;
};

dictionary ManifestAnimation {
boolean? autoplay;
string? defaultTheme;
i8? direction;
boolean? hover;
string id;
u32? intermission;
boolean? loop;
u32? loop_count;
string? playMode;
u32? speed;
string? themeColor;
};

dictionary Manifest {
string? active_animation_id;
sequence<ManifestAnimation> animations;
string? author;
string? description;
string? generator;
string? keywords;
u32? revision;
ManifestThemes? themes;
sequence<string>? states;
string? version;
};

interface DotLottiePlayer {
constructor(Config config);
boolean load_animation_data([ByRef] string animation_data, u32 width, u32 height);
boolean load_animation_path([ByRef] string animation_path, u32 width, u32 height);
boolean load_dotlottie_data([ByRef] bytes file_data, u32 width, u32 height);
boolean load_animation([ByRef] string animation_id, u32 width, u32 height);
Manifest? manifest();
string manifest_string();
u64 buffer_ptr();
u64 buffer_len();
void set_config(Config config);
Expand Down
1 change: 1 addition & 0 deletions dotlottie-ffi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub use dotlottie_fms::*;
pub use dotlottie_player_core::*;

uniffi::include_scaffolding!("dotlottie_player");
7 changes: 7 additions & 0 deletions dotlottie-fms/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/uniffi-bindings
/build
/target
**/*.rs.bk
Cargo.lock
bin/
/artifacts
22 changes: 22 additions & 0 deletions dotlottie-fms/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "dotlottie_fms"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
name = "dotlottie_fms"

[dependencies]
zip = { version = "0.6.6", default-features = false, features = ["deflate"] }
thiserror = "1.0.48"
serde_json = "1.0.107"
serde = { version = "1.0.188", features = ["derive"] }
base64 = "0.21.4"
json = "0.12.4"
jzon = "0.12.5"


[build-dependencies]
lazy_static = "1.4.0"
42 changes: 42 additions & 0 deletions dotlottie-fms/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use lazy_static::lazy_static;
use std::env;

// Target triple for WASM
const WASM32_UNKNOWN_EMSCRIPTEN: &str = "wasm32-unknown-emscripten";

// Target-specifc build settings
struct BuildSettings {
link_args: Vec<String>,
}

fn is_wasm_build() -> bool {
match env::var("TARGET") {
Ok(target) => target == WASM32_UNKNOWN_EMSCRIPTEN,
Err(_) => panic!("TARGET environment variable not set"),
}
}

lazy_static! {
// Native library dependencies
static ref TARGET_BUILD_SETTINGS: BuildSettings = match is_wasm_build() {
true => BuildSettings{
link_args: vec![String::from("--no-entry"), String::from("-sERROR_ON_UNDEFINED_SYMBOLS=0")],
},
_ => BuildSettings{
link_args: vec![],
},
};
}

fn register_link_arg(arg: &String) {
println!("cargo:rustc-link-arg={}", arg);
}

fn apply_build_settings(build_settings: &BuildSettings) {
build_settings.link_args.iter().for_each(register_link_arg);
}

fn main() {
// Apply build settings
apply_build_settings(&TARGET_BUILD_SETTINGS);
}
5 changes: 5 additions & 0 deletions dotlottie-fms/src/animation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[derive(Debug)]
pub struct AnimationContainer {
pub id: String,
pub animation_data: String,
}
Loading

0 comments on commit 68201b4

Please sign in to comment.