Skip to content

Commit

Permalink
add state transition signals to AnimationNodeStateMachinePlayback
Browse files Browse the repository at this point in the history
  • Loading branch information
TheOrioli committed Feb 7, 2022
1 parent be1adf4 commit da2b578
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
47 changes: 47 additions & 0 deletions doc/classes/AnimationNodeStateMachinePlayback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@
stateMachine.Travel("some_state");
[/csharp]
[/codeblocks]

State transitions emit signals, in a specific order:
- [signal state_exit] emits when a state is exited
- [signal state_changed] emits before the new state is entered
- [signal state_enter] emits when the new state is entered
[codeblocks]
[gdscript]
var state_machine: AnimationNodeStateMachinePlayback = $AnimationTree.get("parameters/playback")
state_machine.state_changed.connect(on_state_changed)

func on_state_changed(prev: String, next: String) -> void:
print(prev, " -> ", next)
[/gdscript]
[csharp]
public override void _Ready()
{
var stateMachine = GetNode<AnimationTree>("AnimationTree").Get("parameters/playback") as AnimationNodeStateMachinePlayback;
stateMachine.Connect("state_changed", new Callable(this, nameof(OnStateChanged)));
}

private void OnStateChanged(string previous, string next)
{
GD.Print(previous, " -> ", next);
}
[/csharp]
[/codeblocks]
</description>
<tutorials>
<link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link>
Expand Down Expand Up @@ -74,4 +100,25 @@
<members>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="true" />
</members>
<signals>
<signal name="state_changed">
<argument index="0" name="previous_state" type="String" />
<argument index="1" name="next_state" type="String" />
<description>
Notified when a state transition occurs. Emitted before [signal state_enter]. Not emitted for the first state.
</description>
</signal>
<signal name="state_enter">
<argument index="0" name="state" type="String" />
<description>
Notifies when a state is entered.
</description>
</signal>
<signal name="state_exit">
<argument index="0" name="state" type="String" />
<description>
Notifies when a state is exited.
</description>
</signal>
</signals>
</class>
22 changes: 20 additions & 2 deletions scene/animation/animation_node_state_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include "animation_node_state_machine.h"

#include "scene/scene_string_names.h"

/////////////////////////////////////////////////

void AnimationNodeStateMachineTransition::set_switch_mode(SwitchMode p_mode) {
Expand Down Expand Up @@ -323,6 +325,11 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (!_travel(p_state_machine, start_request)) {
// can't travel, then teleport
path.clear();
if (current != StringName()){
emit_signal(SNAME("state_exit"), current);
emit_signal(SNAME("state_changed"), current, start_request);
}
emit_signal(SNAME("state_enter"), start_request);
current = start_request;
}
start_request = StringName(); //clear start request
Expand All @@ -331,6 +338,11 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
// teleport to start
if (p_state_machine->states.has(start_request)) {
path.clear();
if (current != StringName()){
emit_signal(SNAME("state_exit"), current);
emit_signal(SNAME("state_changed"), current, start_request);
}
emit_signal(SNAME("state_enter"), start_request);
current = start_request;
playing = true;
play_start = true;
Expand All @@ -349,7 +361,6 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (p_state_machine->start_node != StringName() && p_seek && p_time == 0) {
current = p_state_machine->start_node;
}

len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, 1.0, AnimationNode::FILTER_IGNORE, false);
pos_current = 0;
loops_current = 0;
Expand Down Expand Up @@ -452,7 +463,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}

if (goto_next) { //loops should be used because fade time may be too small or zero and animation may have looped

emit_signal(SNAME("state_exit"), current);
if (next_xfade) {
//time to fade, baby
fading_from = current;
Expand All @@ -466,7 +477,10 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (path.size()) { //if it came from path, remove path
path.remove_at(0);
}
emit_signal(SNAME("state_changed"), current, next);

current = next;
emit_signal(SNAME("state_enter"), current);
if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) {
len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, 0, AnimationNode::FILTER_IGNORE, false);
pos_current = MIN(pos_current, len_current);
Expand Down Expand Up @@ -499,6 +513,10 @@ void AnimationNodeStateMachinePlayback::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_current_play_position"), &AnimationNodeStateMachinePlayback::get_current_play_pos);
ClassDB::bind_method(D_METHOD("get_current_length"), &AnimationNodeStateMachinePlayback::get_current_length);
ClassDB::bind_method(D_METHOD("get_travel_path"), &AnimationNodeStateMachinePlayback::get_travel_path);

ADD_SIGNAL(MethodInfo("state_enter", PropertyInfo(Variant::STRING, "state")));
ADD_SIGNAL(MethodInfo("state_changed", PropertyInfo(Variant::STRING, "previous_state"), PropertyInfo(Variant::STRING, "next_state")));
ADD_SIGNAL(MethodInfo("state_exit", PropertyInfo(Variant::STRING, "state")));
}

AnimationNodeStateMachinePlayback::AnimationNodeStateMachinePlayback() {
Expand Down
1 change: 1 addition & 0 deletions scene/scene_string_names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,5 @@ SceneStringNames::SceneStringNames() {
use_in_baked_light = StaticCString::create("use_in_baked_light");
use_dynamic_gi = StaticCString::create("use_dynamic_gi");
#endif

}
1 change: 1 addition & 0 deletions scene/scene_string_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class SceneStringNames {
StringName use_in_baked_light;
StringName use_dynamic_gi;
#endif

};

#endif // SCENE_STRING_NAMES_H

0 comments on commit da2b578

Please sign in to comment.