From 95daf7285fc780b37c1c1912dbeefafbe3673c87 Mon Sep 17 00:00:00 2001
From: "Silc Lizard (Tokage) Renew"
<61938263+TokageItLab@users.noreply.github.com>
Date: Thu, 13 Jul 2023 06:58:54 +0900
Subject: [PATCH] Implement LoopModeOverride to AnimationNodeAnimation
---
doc/classes/Animation.xml | 3 +++
doc/classes/AnimationNodeAnimation.xml | 21 +++++++++++++++++++++
scene/animation/animation_blend_tree.cpp | 18 ++++++++++++++++--
scene/animation/animation_blend_tree.h | 14 +++++++++-----
scene/resources/animation.cpp | 3 +++
scene/resources/animation.h | 1 +
6 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index d2b2c1fe4735..d116f8a126b1 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -660,6 +660,9 @@
Repeats playback and reverse playback at both ends of the animation.
+
+ Disables overriding loop mode if the overriding can be caused in the other class which uses animation.
+
This flag indicates that the animation proceeds without any looping.
diff --git a/doc/classes/AnimationNodeAnimation.xml b/doc/classes/AnimationNodeAnimation.xml
index d965d31b03d7..9ed579793443 100644
--- a/doc/classes/AnimationNodeAnimation.xml
+++ b/doc/classes/AnimationNodeAnimation.xml
@@ -5,6 +5,27 @@
A resource to add to an [AnimationNodeBlendTree]. Only has one output port using the [member animation] property. Used as an input for [AnimationNode]s that blend animations together.
+ The [AnimationNodeAnimation] has [code]loop_mode_override[/code] parameter to manage the looping state of each [AnimationNodeAnimation] for each [AnimationTree] as a node. See also [enum Animation.LoopMode].
+ [codeblocks]
+ [gdscript]
+ # Set loop mode override.
+ animation_tree.set("parameters/Animation/loop_mode_override", Animation.LOOP_LINEAR)
+ # Alternative syntax (same result as above).
+ animation_tree["parameters/Animation/loop_mode_override"] = Animation.LOOP_LINEAR
+
+ # Get loop mode override.
+ animation_tree.get("parameters/Animation/loop_mode_override")
+ # Alternative syntax (same result as above).
+ animation_tree["parameters/Animation/loop_mode_override"]
+ [/gdscript]
+ [csharp]
+ // Set loop mode override.
+ animationTree.Set("parameters/Animation/loop_mode_override", (int)Animation.LoopMode.Linear);
+
+ // Get loop mode override.
+ animationTree.Get("parameters/Animation/loop_mode_override");
+ [/csharp]
+ [/codeblocks]
$DOCS_URL/tutorials/animation/animation_tree.html
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 6a76b5ac168c..f8f73e541ca7 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -45,6 +45,15 @@ Vector (*AnimationNodeAnimation::get_editable_animation_list)() = nullpt
void AnimationNodeAnimation::get_parameter_list(List *r_list) const {
r_list->push_back(PropertyInfo(Variant::FLOAT, time, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
+ r_list->push_back(PropertyInfo(Variant::INT, loop_mode_override, PROPERTY_HINT_ENUM, "None,Linear,Pingpong,No Override"));
+}
+
+Variant AnimationNodeAnimation::get_parameter_default_value(const StringName &p_parameter) const {
+ if (p_parameter == loop_mode_override) {
+ return Animation::LOOP_NO_OVERRIDE;
+ } else {
+ return 0.0;
+ }
}
void AnimationNodeAnimation::_validate_property(PropertyInfo &p_property) const {
@@ -100,7 +109,12 @@ double AnimationNodeAnimation::_process(double p_time, bool p_seek, bool p_is_ex
}
bool is_looping = false;
- if (anim->get_loop_mode() == Animation::LOOP_PINGPONG) {
+ Animation::LoopMode loop_mode = anim->get_loop_mode();
+ Animation::LoopMode override = static_cast((int)get_parameter(loop_mode_override));
+ if (override != Animation::LOOP_NO_OVERRIDE) {
+ loop_mode = override;
+ }
+ if (loop_mode == Animation::LOOP_PINGPONG) {
if (!Math::is_zero_approx(anim_size)) {
if (prev_time >= 0 && cur_time < 0) {
backward = !backward;
@@ -113,7 +127,7 @@ double AnimationNodeAnimation::_process(double p_time, bool p_seek, bool p_is_ex
cur_time = Math::pingpong(cur_time, anim_size);
}
is_looping = true;
- } else if (anim->get_loop_mode() == Animation::LOOP_LINEAR) {
+ } else if (loop_mode == Animation::LOOP_LINEAR) {
if (!Math::is_zero_approx(anim_size)) {
if (prev_time >= 0 && cur_time < 0) {
looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index 2139af8a968c..88ede241a718 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -36,19 +36,23 @@
class AnimationNodeAnimation : public AnimationRootNode {
GDCLASS(AnimationNodeAnimation, AnimationRootNode);
+public:
+ enum PlayMode {
+ PLAY_MODE_FORWARD,
+ PLAY_MODE_BACKWARD
+ };
+
+private:
StringName animation;
StringName time = "time";
+ StringName loop_mode_override = "loop_mode_override";
uint64_t last_version = 0;
bool skip = false;
public:
- enum PlayMode {
- PLAY_MODE_FORWARD,
- PLAY_MODE_BACKWARD
- };
-
void get_parameter_list(List *r_list) const override;
+ virtual Variant get_parameter_default_value(const StringName &p_parameter) const override;
static Vector (*get_editable_animation_list)();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 1ab6e714a809..cacb653bc7d3 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -3123,6 +3123,8 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
from_time += CMP_EPSILON;
}
} break;
+ default: {
+ } break;
}
switch (t->type) {
case TYPE_POSITION_3D: {
@@ -3938,6 +3940,7 @@ void Animation::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_NONE);
BIND_ENUM_CONSTANT(LOOP_LINEAR);
BIND_ENUM_CONSTANT(LOOP_PINGPONG);
+ BIND_ENUM_CONSTANT(LOOP_NO_OVERRIDE);
BIND_ENUM_CONSTANT(LOOPED_FLAG_NONE);
BIND_ENUM_CONSTANT(LOOPED_FLAG_END);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index c128c14e4963..6e6ada7e3556 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -71,6 +71,7 @@ class Animation : public Resource {
LOOP_NONE,
LOOP_LINEAR,
LOOP_PINGPONG,
+ LOOP_NO_OVERRIDE,
};
enum LoopedFlag {