From abe1117055b6246e07d2f4b2a3a66351e6e2d3f6 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 14 Aug 2023 12:43:12 +0200 Subject: [PATCH] Add BTStopAnimation action --- bt/actions/bt_play_animation.h | 1 - bt/actions/bt_stop_animation.cpp | 86 ++++++++++++++++++++++++++++++++ bt/actions/bt_stop_animation.h | 48 ++++++++++++++++++ config.py | 1 + register_types.cpp | 2 + 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 bt/actions/bt_stop_animation.cpp create mode 100644 bt/actions/bt_stop_animation.h diff --git a/bt/actions/bt_play_animation.h b/bt/actions/bt_play_animation.h index e20f015..eb25908 100644 --- a/bt/actions/bt_play_animation.h +++ b/bt/actions/bt_play_animation.h @@ -16,7 +16,6 @@ #include "modules/limboai/blackboard/bb_param/bb_node.h" -#include "core/object/object.h" #include "scene/animation/animation_player.h" class BTPlayAnimation : public BTAction { diff --git a/bt/actions/bt_stop_animation.cpp b/bt/actions/bt_stop_animation.cpp new file mode 100644 index 0000000..f0d415e --- /dev/null +++ b/bt/actions/bt_stop_animation.cpp @@ -0,0 +1,86 @@ +/** + * bt_stop_animation.cpp + * ============================================================================= + * Copyright 2021-2023 Serhii Snitsaruk + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * ============================================================================= + */ + +#include "modules/limboai/bt/actions/bt_stop_animation.h" + +//**** Setters / Getters + +void BTStopAnimation::set_animation_player(Ref p_animation_player) { + animation_player_param = p_animation_player; + emit_changed(); + if (Engine::get_singleton()->is_editor_hint() && animation_player_param.is_valid()) { + animation_player_param->connect(SNAME("changed"), Callable(this, SNAME("emit_changed"))); + } +} + +void BTStopAnimation::set_animation_name(StringName p_animation_name) { + animation_name = p_animation_name; + emit_changed(); +} + +//**** Task Implementation + +String BTStopAnimation::get_configuration_warning() const { + String warning = BTAction::get_configuration_warning(); + if (!warning.is_empty()) { + warning += "\n"; + } + + if (animation_player_param.is_null()) { + warning += "Animation Player parameter is not set.\n"; + } else { + if (animation_player_param->get_value_source() == BBParam::SAVED_VALUE && animation_player_param->get_saved_value().is_zero()) { + warning += "Path to AnimationPlayer node is not set.\n"; + } else if (animation_player_param->get_value_source() == BBParam::BLACKBOARD_VAR && animation_player_param->get_variable().is_empty()) { + warning += "AnimationPlayer blackboard variable is not set.\n"; + } + } + + return warning; +} + +String BTStopAnimation::_generate_name() const { + if (animation_name == StringName() || animation_player_param.is_null()) { + return "StopAnimation"; + } + return vformat("StopAnimation \"%s\"", animation_name); +} + +void BTStopAnimation::_setup() { + setup_failed = true; + ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTStopAnimation: AnimationPlayer parameter is not set."); + animation_player = Object::cast_to(animation_player_param->get_value(get_agent(), get_blackboard())); + ERR_FAIL_COND_MSG(animation_player == nullptr, "BTStopAnimation: Failed to get AnimationPlayer."); + if (animation_name != StringName()) { + ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTStopAnimation: Animation not found: %s", animation_name)); + } + setup_failed = false; +} + +int BTStopAnimation::_tick(double p_delta) { + ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTStopAnimation: _setup() failed - returning FAILURE."); + if (animation_player->is_playing() && (animation_name == StringName() || animation_name == animation_player->get_assigned_animation())) { + animation_player->stop(); + } + return SUCCESS; +} + +//**** Godot + +void BTStopAnimation::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation_player", "p_anim_player"), &BTStopAnimation::set_animation_player); + ClassDB::bind_method(D_METHOD("get_animation_player"), &BTStopAnimation::get_animation_player); + ClassDB::bind_method(D_METHOD("set_animation_name", "p_anim_name"), &BTStopAnimation::set_animation_name); + ClassDB::bind_method(D_METHOD("get_animation_name"), &BTStopAnimation::get_animation_name); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_player", PROPERTY_HINT_RESOURCE_TYPE, "BBNode"), "set_animation_player", "get_animation_player"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation_name"), "set_animation_name", "get_animation_name"); +} diff --git a/bt/actions/bt_stop_animation.h b/bt/actions/bt_stop_animation.h new file mode 100644 index 0000000..2ec939c --- /dev/null +++ b/bt/actions/bt_stop_animation.h @@ -0,0 +1,48 @@ +/** + * bt_stop_animation.h + * ============================================================================= + * Copyright 2021-2023 Serhii Snitsaruk + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * ============================================================================= + */ + +#ifndef BT_STOP_ANIMATION_H +#define BT_STOP_ANIMATION_H + +#include "bt_action.h" + +#include "modules/limboai/blackboard/bb_param/bb_node.h" + +#include "scene/animation/animation_player.h" + +class BTStopAnimation : public BTAction { + GDCLASS(BTStopAnimation, BTAction); + +private: + Ref animation_player_param; + StringName animation_name; + + AnimationPlayer *animation_player = nullptr; + bool setup_failed = false; + +protected: + static void _bind_methods(); + + virtual String _generate_name() const override; + virtual void _setup() override; + virtual int _tick(double p_delta) override; + +public: + void set_animation_player(Ref p_animation_player); + Ref get_animation_player() const { return animation_player_param; } + + void set_animation_name(StringName p_animation_name); + StringName get_animation_name() const { return animation_name; } + + virtual String get_configuration_warning() const override; +}; + +#endif // BT_STOP_ANIMATION \ No newline at end of file diff --git a/config.py b/config.py index 416f191..f4db882 100644 --- a/config.py +++ b/config.py @@ -91,6 +91,7 @@ def get_doc_classes(): "BTSetAgentProperty", "BTSetVar", "BTState", + "BTStopAnimation", "BTSubtree", "BTTask", "BTTimeLimit", diff --git a/register_types.cpp b/register_types.cpp index f684233..3b8b8fe 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -51,6 +51,7 @@ #include "bt/actions/bt_random_wait.h" #include "bt/actions/bt_set_agent_property.h" #include "bt/actions/bt_set_var.h" +#include "bt/actions/bt_stop_animation.h" #include "bt/actions/bt_wait.h" #include "bt/actions/bt_wait_ticks.h" #include "bt/behavior_tree.h" @@ -147,6 +148,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(BTRandomWait); GDREGISTER_CLASS(BTSetAgentProperty); GDREGISTER_CLASS(BTSetVar); + GDREGISTER_CLASS(BTStopAnimation); GDREGISTER_CLASS(BTSubtree); GDREGISTER_CLASS(BTWait); GDREGISTER_CLASS(BTWaitTicks);