Guarded Transitions

Guarded transitions allow you to transition to the next state only if a condition is met. Guarded transitions depend on the context properties of the state machine. Learn more about context here.

Quick start:

addStateMachine({
descriptor: {
...
},
states: [
...
],
transitions: [
{
type: "Transition",
from_state: 0,
to_state: 1,
string_event: {
value: "explosion"
},
guards: [
{
type: "Numeric",
context_key: "counter_0",
condition_type: "Equal",
compare_to: 5.0
}
]
},
...
],
context_variables: [
{
type: "Numeric",
key: "counter_0",
value: 0
},
]
})

Definition

  1. Transition guards are available for string, bool and float types. You can define this in the type with either:
  • String
  • Boolean
  • Numeric
  1. context_key define which value inside the context to compare to.

  2. condition_type define which type of comparaison you need:

    • Equal
    • NotEqual
    • GreaterThan
    • GreaterThanOrEqual
    • LessThan
    • LessThanOrEqual
  3. compare_to define the value to compare against the value contained inside the context

Usage inside of players

Manual control of context variables

Currently you have to manually set the context values, later on this will be accomplished within ListenerActions. For example if you currently need a counter and transition if the button is pressed 3 times, you will have to manually increment the context value yourself. This is how you can accomplish this:

State machine definition:

async function createAnimationWithStateMachine() {
const dotLottie = new DotLottie();
await dotLottie
.addAnimation({
id: 'animation',
url: '',
})
.addStateMachine({
descriptor: {
id: 'button_press',
initial: 0,
},
states: [
{
name: "button_initial",
type: "PlaybackState",
mode: "Forward",
speed: 1,
use_frame_interpolation: true,
autoplay: true,
loop: false,
},
{
name: "button_pressed",
type: "PlaybackState",
mode: "Forward",
speed: 1,
use_frame_interpolation: true,
autoplay: true,
loop: false,
},
{
name: "confetti",
type: "PlaybackState",
mode: "Forward",
autoplay: true,
speed: 0.5,
loop: false,
},
],
transitions: [
{
type: "Transition",
from_state: 0,
to_state: 1,
on_pointer_down_event: {},
},
{
type: "Transition",
from_state: 1,
to_state: 0,
on_complete_event: {},
},
{
type: "Transition",
from_state: 0,
to_state: 3,
on_pointer_down_event: {},
guards: [
{
type: "Numeric",
context_key: "counter_0",
condition_type: "Equal",
compare_to: 3.0
}
]
},
{
type: "Transition",
from_state: 3,
to_state: 0,
on_complete_event: {},
},
],
listeners: [
{
type: "PointerDown"
}
],
context_variables: [
{
type: "Numeric",
key: "counter_0",
value: 0
},
]
})
.build()
.then((value) => {
return value.toArrayBuffer();
})
.then((value) => {
fs.writeFileSync('button.lottie', Buffer.from(value));
});
}

Once we’ve created our .lottie and loaded it inside a player we need to add a click listener and set the numeric context on each click. The following code is pseudocode on how to achieve this:

dotlottiePlayer.loadStateMachine("button_press");
dotlottiePlayer.startStateMachine();
var counter = 0;
dotlottiePlayer.addClickListener( () => {
counter += 1;
dotlottiePlayer.tmp_set_state_machine_context("counter_0", counter);
dotlottiePlayer.post_event(Event::OnPointerDown{x:0,y:0})
} );

The way you get a hold of the dotLottie player reference will vary depending on your platform, however the method names are the same. For setting numeric, string and bool context use these methods:

  • tmp_set_state_machine_context(key: string, value: f32) for the numeric context
  • tmp_set_state_machine_string_context(key: string, value: string) for the string context
  • tmp_set_state_machine_bool_context(key: string, value: bool) for the bool context