Skip to content

Commit

Permalink
feat: added load_state_machine_data (#190)
Browse files Browse the repository at this point in the history
fix: made clippy happy

chore: added fixture file

feat: added bindings
  • Loading branch information
samuelOsborne authored Jun 25, 2024
1 parent a81ca6f commit 9c11212
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 2 deletions.
4 changes: 2 additions & 2 deletions dotlottie-ffi/emscripten_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
.function("stateMachineFrameworkSetup", &DotLottiePlayer::state_machine_framework_setup)
.function("setStateMachineNumericContext", &DotLottiePlayer::set_state_machine_numeric_context)
.function("setStateMachineStringContext", &DotLottiePlayer::set_state_machine_string_context)
.function("setStateMachineBooleanContext", &DotLottiePlayer::set_state_machine_boolean_context);

.function("setStateMachineBooleanContext", &DotLottiePlayer::set_state_machine_boolean_context)
.function("loadStateMachineData", &DotLottiePlayer::load_state_machine_data);
// .function("state_machine_subscribe", &DotLottiePlayer::state_machine_subscribe)
// .function("state_machine_unsubscribe", &DotLottiePlayer::state_machine_unsubscribe)
}
1 change: 1 addition & 0 deletions dotlottie-ffi/src/dotlottie_player.udl
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,5 @@ interface DotLottiePlayer {
boolean set_state_machine_string_context([ByRef] string key, [ByRef] string value);
boolean set_state_machine_boolean_context([ByRef] string key, boolean value);
sequence<string> state_machine_framework_setup();
boolean load_state_machine_data([ByRef] string state_machine);
};
1 change: 1 addition & 0 deletions dotlottie-ffi/src/dotlottie_player_cpp.udl
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ interface DotLottiePlayer {
boolean stop_state_machine();
boolean post_serialized_event(string event);
sequence<string> state_machine_framework_setup();
boolean load_state_machine_data([ByRef] string state_machine);
};
28 changes: 28 additions & 0 deletions dotlottie-rs/src/dotlottie_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1781,6 +1781,34 @@ impl DotLottiePlayer {
self.player.write().unwrap().load_theme(theme_id)
}

pub fn load_state_machine_data(&self, state_machine: &str) -> bool {
let state_machine = StateMachine::new(state_machine, self.player.clone());

if state_machine.is_ok() {
match self.state_machine.try_write() {
Ok(mut sm) => {
sm.replace(state_machine.unwrap());
}
Err(_) => {
return false;
}
}

let player = self.player.try_write();

match player {
Ok(mut player) => {
player.state_machine = self.state_machine.clone();
}
Err(_) => {
return false;
}
}
}

false
}

pub fn load_state_machine(&self, state_machine_id: &str) -> bool {
let state_machine_string = self
.player
Expand Down
80 changes: 80 additions & 0 deletions dotlottie-rs/tests/fixtures/pigeon_fsm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"descriptor": {
"id": "multi_animation_slideshow",
"initial": 0
},
"states": [
{
"name": "pigeon",
"type": "PlaybackState",
"loop": true,
"autoplay": true,
"mode": "forward",
"speed": 1,
"marker": "bird",
"segment": [],
"frame_interpolation": true,
"entry_actions": [
{
"type": "LogAction",
"message": "Howdy partner!"
}
],
"exit_actions": [],
"reset_context": "*"
},
{
"name": "explosion",
"type": "PlaybackState",
"loop": false,
"autoplay": true,
"mode": "forward",
"speed": 0.5,
"marker": "explosion",
"segment": [],
"frame_interpolation": true,
"entry_actions": [],
"exit_actions": []
},
{
"name": "feather",
"type": "PlaybackState",
"loop": false,
"autoplay": true,
"mode": "forward",
"speed": 1,
"marker": "feather",
"segment": [],
"frame_interpolation": true,
"entry_actions": [],
"exit_actions": []
}
],
"transitions": [
{
"type": "Transition",
"from_state": 0,
"to_state": 1,
"on_pointer_down_event": {}
},
{
"type": "Transition",
"from_state": 1,
"to_state": 2,
"on_pointer_down_event": {}
},
{
"type": "Transition",
"from_state": 2,
"to_state": 0,
"on_pointer_down_event": {}
}
],
"listeners": [
{
"type": "PointerDown"
}
],
"context_variables": [
]
}
82 changes: 82 additions & 0 deletions dotlottie-rs/tests/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod tests {

use dotlottie_player_core::{
listeners::ListenerTrait,
states::StateTrait,
transitions::{Transition::Transition, TransitionTrait},
StateMachineObserver,
};
Expand Down Expand Up @@ -297,6 +298,87 @@ mod tests {
assert_eq!(*observer3.custom_data.read().unwrap(), "\"feather\"");
}

#[test]
fn state_machine_from_data_test() {
let pigeon_fsm = include_str!("fixtures/pigeon_fsm.json");

let player = DotLottiePlayer::new(Config::default());

player.load_dotlottie_data(include_bytes!("fixtures/exploding_pigeon.lottie"), 100, 100);

player.load_state_machine_data(pigeon_fsm);
player.start_state_machine();

match player.get_state_machine().read().unwrap().as_ref() {
Some(sm) => {
assert_eq!(sm.states.len(), 3);
}
None => {
panic!("State machine is not loaded");
}
}

match player.get_state_machine().read().unwrap().as_ref() {
Some(sm) => {
let cs = sm.get_current_state();

match cs {
Some(sm) => match sm.try_read() {
Ok(state) => {
assert_eq!(state.get_name(), "pigeon");
}
Err(_) => panic!("State is not readable"),
},
None => panic!("Failed to get current state"),
}
}
None => {
panic!("State machine is not loaded");
}
}

player.post_event(&Event::OnPointerDown { x: 0.0, y: 0.0 });

match player.get_state_machine().read().unwrap().as_ref() {
Some(sm) => {
let cs = sm.get_current_state();

match cs {
Some(sm) => match sm.try_read() {
Ok(state) => {
assert_eq!(state.get_name(), "explosion");
}
Err(_) => panic!("State is not readable"),
},
None => panic!("Failed to get current state"),
}
}
None => {
panic!("State machine is not loaded");
}
}
player.post_event(&Event::OnPointerDown { x: 0.0, y: 0.0 });

match player.get_state_machine().read().unwrap().as_ref() {
Some(sm) => {
let cs = sm.get_current_state();

match cs {
Some(sm) => match sm.try_read() {
Ok(state) => {
assert_eq!(state.get_name(), "feather");
}
Err(_) => panic!("State is not readable"),
},
None => panic!("Failed to get current state"),
}
}
None => {
panic!("State machine is not loaded");
}
}
}

#[test]
fn state_machine_listener_test() {
let player = DotLottiePlayer::new(Config::default());
Expand Down

0 comments on commit 9c11212

Please sign in to comment.