Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: layer detection api #217

Merged
merged 2 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions dotlottie-rs/src/dotlottie_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ impl DotLottieRuntime {
self.total_frames()
}

pub fn hit_check(&self, layer_name: &str, x: f32, y: f32) -> bool {
self.renderer.hit_check(layer_name, x, y).unwrap_or(false)
}

pub fn is_loaded(&self) -> bool {
self.is_loaded
}
Expand Down Expand Up @@ -1182,6 +1186,10 @@ impl DotLottiePlayerContainer {
}
}

pub fn hit_check(&self, layer_name: &str, x: f32, y: f32) -> bool {
self.runtime.read().unwrap().hit_check(layer_name, x, y)
}

pub fn markers(&self) -> Vec<Marker> {
self.runtime.read().unwrap().markers()
}
Expand Down Expand Up @@ -1229,6 +1237,10 @@ impl DotLottiePlayer {
self.state_machine.clone()
}

pub fn hit_check(&self, layer_name: &str, x: f32, y: f32) -> bool {
self.player.read().unwrap().hit_check(layer_name, x, y)
}

// If you are in an environment that does not support events
// Call isPlaying() to know if the state machine started playback within the first state
pub fn start_state_machine(&self) -> bool {
Expand Down
6 changes: 6 additions & 0 deletions dotlottie-rs/src/lottie_renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ impl LottieRenderer {

Ok(())
}

pub fn hit_check(&self, layer_name: &str, x: f32, y: f32) -> Result<bool, LottieRendererError> {
self.thorvg_animation
.hit_check(layer_name, x, y)
.map_err(LottieRendererError::ThorvgError)
}
}

fn hex_to_rgba(hex_color: u32) -> (u8, u8, u8, u8) {
Expand Down
33 changes: 33 additions & 0 deletions dotlottie-rs/src/thorvg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,39 @@ impl Animation {
Ok(())
}

pub fn hit_check(&self, layer_name: &str, x: f32, y: f32) -> Result<bool, TvgError> {
let paint = self.raw_paint;
let layer_name_cstr = CString::new(layer_name).expect("Failed to create CString");
let layer_id = unsafe { tvg_accessor_generate_id(layer_name_cstr.as_ptr()) };
let layer = unsafe { tvg_picture_get_paint(paint, layer_id) };

if !layer.is_null() {
let mut px: f32 = -1.0;
let mut py: f32 = -1.0;
let mut pw: f32 = -1.0;
let mut ph: f32 = -1.0;

let bounds = unsafe {
tvg_paint_get_bounds(
layer,
&mut px as *mut f32,
&mut py as *mut f32,
&mut pw as *mut f32,
&mut ph as *mut f32,
true,
)
};

convert_tvg_result(bounds, "tvg_paint_get_bounds")?;

if x >= px && x <= px + pw && y >= py && y <= py + ph {
return Ok(true);
}
}

Ok(false)
}

pub fn get_size(&self) -> Result<(f32, f32), TvgError> {
let mut width = 0.0;
let mut height = 0.0;
Expand Down
68 changes: 54 additions & 14 deletions examples/demo-state-machine/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use dotlottie_player_core::events::Event;
use dotlottie_player_core::{Config, DotLottiePlayer, Observer, StateMachineObserver};
use minifb::{Key, KeyRepeat, Window, WindowOptions};
use minifb::{Key, KeyRepeat, MouseButton, MouseMode, Window, WindowOptions};
use std::fs::{self, File};
use std::io::Read;
use std::sync::{Arc, RwLock};
use std::thread;
use std::{env, time::Instant};
use sysinfo::System;

pub const WIDTH: usize = 500;
pub const HEIGHT: usize = 500;
pub const WIDTH: usize = 1000;
pub const HEIGHT: usize = 1000;

struct DummyObserver2;

Expand Down Expand Up @@ -99,13 +99,15 @@ impl StateMachineObserver for SMObserver {
struct Timer {
last_update: Instant,
prev_frame: f32,
first: bool,
}

impl Timer {
fn new() -> Self {
Self {
last_update: Instant::now(),
prev_frame: 0.0,
first: false,
}
}

Expand All @@ -115,8 +117,9 @@ impl Timer {
// println!("next_frame: {}", next_frame);
let updated = animation.set_frame(next_frame);

if updated || next_frame != self.prev_frame {
if next_frame != self.prev_frame || !self.first {
animation.render();
self.first = true;
}

self.last_update = Instant::now(); // Reset the timer
Expand All @@ -137,12 +140,12 @@ fn main() {

let lottie_player: DotLottiePlayer = DotLottiePlayer::new(Config {
loop_animation: true,
background_color: 0x00000000,
background_color: 0xffffffff,
..Config::default()
});

let mut markers = File::open("src/star-rating.lottie").expect("no file found");
let metadatamarkers = fs::metadata("src/star-rating.lottie").expect("unable to read metadata");
let mut markers = File::open("src/locker.lottie").expect("no file found");
let metadatamarkers = fs::metadata("src/locker.lottie").expect("unable to read metadata");
let mut markers_buffer = vec![0; metadatamarkers.len() as usize];
markers.read(&mut markers_buffer).expect("buffer overflow");

Expand Down Expand Up @@ -180,28 +183,65 @@ fn main() {

let mut cpu_memory_monitor_timer = Instant::now();

let message: String = fs::read_to_string("src/global_state_sm.json").unwrap();
let message: String = fs::read_to_string("src/pigeon_fsm.json").unwrap();

// lottie_player.load_state_machine("pigeon_fsm");
let r = lottie_player.load_state_machine_data(&message);
// let r = lottie_player.load_state_machine_data(&message);

println!("Load state machine data -> {}", r);
// println!("Load state machine data -> {}", r);

let sSm = lottie_player.start_state_machine();

println!("Start state machine -> {}", sSm);
lottie_player.start_state_machine();

println!("is_playing: {}", lottie_player.is_playing());

lottie_player.render();

lottie_player.state_machine_subscribe(observer3.clone());
// lottie_player.state_machine_subscribe(observer3.clone());

let locked_player = Arc::new(RwLock::new(lottie_player));

let mut pushed = 0.0;

while window.is_open() && !window.is_key_down(Key::Escape) {
let left_down = window.get_mouse_down(MouseButton::Left);
// println!("is left down? {}", left_down);

if left_down {
let mut mx = 0.0;
let mut my = 0.0;
window.get_mouse_pos(MouseMode::Clamp).map(|mouse| {
// println!("x {} y {}", mouse.0, mouse.1);
mx = mouse.0;
my = mouse.1;
});

let p = &mut *locked_player.write().unwrap();
if p.hit_check("pad1", mx, my) {
// println!("hit");
let mut c = p.config();

c.segment = vec![0.0, 20.0];
c.loop_animation = false;
p.set_config(c);

p.play();
} else {
println!("not hit");
}
if p.hit_check("bar", mx, my) {
// println!("hit");
let mut c = p.config();

c.segment = vec![56.0, 82.0];
c.loop_animation = false;
p.set_config(c);

p.play();
} else {
println!("not hit");
}
}

timer.tick(&*locked_player.read().unwrap());

if window.is_key_down(Key::S) {
Expand Down
Loading
Loading