Merge branch 'animation-tasks'
This commit is contained in:
commit
51fb7b83ae
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* bt_await_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 "bt_await_animation.h"
|
||||
|
||||
//**** Setters / Getters
|
||||
|
||||
void BTAwaitAnimation::set_animation_player(Ref<BBNode> 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 BTAwaitAnimation::set_animation_name(StringName p_animation_name) {
|
||||
animation_name = p_animation_name;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTAwaitAnimation::set_max_time(double p_max_time) {
|
||||
max_time = p_max_time;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
//**** Task Implementation
|
||||
|
||||
String BTAwaitAnimation::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";
|
||||
}
|
||||
}
|
||||
if (animation_name == StringName()) {
|
||||
warning += "Animation Name is required in order to wait for the animation to finish.\n";
|
||||
}
|
||||
if (max_time <= 0.0) {
|
||||
warning += "Max time should be greater than 0.0.\n";
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
String BTAwaitAnimation::_generate_name() const {
|
||||
return "AwaitAnimation" +
|
||||
(animation_name != StringName() ? vformat(" \"%s\"", animation_name) : " ???") +
|
||||
vformat(" max_time: %ss", Math::snapped(max_time, 0.001));
|
||||
}
|
||||
|
||||
void BTAwaitAnimation::_setup() {
|
||||
setup_failed = true;
|
||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTAwaitAnimation: AnimationPlayer parameter is not set.");
|
||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTAwaitAnimation: Failed to get AnimationPlayer.");
|
||||
ERR_FAIL_COND_MSG(animation_name == StringName(), "BTAwaitAnimation: Animation Name is not set.");
|
||||
ERR_FAIL_COND_MSG(!animation_player->has_animation(animation_name), vformat("BTAwaitAnimation: Animation not found: %s", animation_name));
|
||||
setup_failed = false;
|
||||
}
|
||||
|
||||
int BTAwaitAnimation::_tick(double p_delta) {
|
||||
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTAwaitAnimation: _setup() failed - returning FAILURE.");
|
||||
|
||||
// ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127
|
||||
if (animation_player->is_playing() && animation_player->get_assigned_animation() == animation_name) {
|
||||
if (get_elapsed_time() < max_time) {
|
||||
return RUNNING;
|
||||
} else if (max_time > 0.0) {
|
||||
WARN_PRINT(vformat("BTAwaitAnimation: Waiting time for the \"%s\" animation exceeded the allocated %s sec.", animation_name, max_time));
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//**** Godot
|
||||
|
||||
void BTAwaitAnimation::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_animation_player", "p_anim_player"), &BTAwaitAnimation::set_animation_player);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_player"), &BTAwaitAnimation::get_animation_player);
|
||||
ClassDB::bind_method(D_METHOD("set_animation_name", "p_anim_name"), &BTAwaitAnimation::set_animation_name);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_name"), &BTAwaitAnimation::get_animation_name);
|
||||
ClassDB::bind_method(D_METHOD("set_max_time", "p_time_sec"), &BTAwaitAnimation::set_max_time);
|
||||
ClassDB::bind_method(D_METHOD("get_max_time"), &BTAwaitAnimation::get_max_time);
|
||||
|
||||
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");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_time", PROPERTY_HINT_RANGE, "0.0,100.0"), "set_max_time", "get_max_time");
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* bt_await_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_AWAIT_ANIMATION_H
|
||||
#define BT_AWAIT_ANIMATION_H
|
||||
|
||||
#include "bt_action.h"
|
||||
|
||||
#include "modules/limboai/blackboard/bb_param/bb_node.h"
|
||||
|
||||
#include "scene/animation/animation_player.h"
|
||||
|
||||
class BTAwaitAnimation : public BTAction {
|
||||
GDCLASS(BTAwaitAnimation, BTAction);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
StringName animation_name;
|
||||
double max_time = 1.0;
|
||||
|
||||
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<BBNode> p_animation_player);
|
||||
Ref<BBNode> get_animation_player() const { return animation_player_param; }
|
||||
|
||||
void set_animation_name(StringName p_animation_name);
|
||||
StringName get_animation_name() const { return animation_name; }
|
||||
|
||||
void set_max_time(double p_max_time);
|
||||
double get_max_time() const { return max_time; }
|
||||
|
||||
virtual String get_configuration_warning() const override;
|
||||
};
|
||||
|
||||
#endif // BT_AWAIT_ANIMATION
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* bt_pause_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 "bt_pause_animation.h"
|
||||
|
||||
//**** Setters / Getters
|
||||
|
||||
void BTPauseAnimation::set_animation_player(Ref<BBNode> 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")));
|
||||
}
|
||||
}
|
||||
|
||||
//**** Task Implementation
|
||||
|
||||
String BTPauseAnimation::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 BTPauseAnimation::_generate_name() const {
|
||||
return "PauseAnimation";
|
||||
}
|
||||
|
||||
void BTPauseAnimation::_setup() {
|
||||
setup_failed = true;
|
||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPauseAnimation: AnimationPlayer parameter is not set.");
|
||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPauseAnimation: Failed to get AnimationPlayer.");
|
||||
setup_failed = false;
|
||||
}
|
||||
|
||||
int BTPauseAnimation::_tick(double p_delta) {
|
||||
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPauseAnimation: _setup() failed - returning FAILURE.");
|
||||
animation_player->pause();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//**** Godot
|
||||
|
||||
void BTPauseAnimation::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_animation_player", "p_anim_player"), &BTPauseAnimation::set_animation_player);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_player"), &BTPauseAnimation::get_animation_player);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_player", PROPERTY_HINT_RESOURCE_TYPE, "BBNode"), "set_animation_player", "get_animation_player");
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* bt_pause_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_PAUSE_ANIMATION_H
|
||||
#define BT_PAUSE_ANIMATION_H
|
||||
|
||||
#include "bt_action.h"
|
||||
|
||||
#include "modules/limboai/blackboard/bb_param/bb_node.h"
|
||||
|
||||
#include "scene/animation/animation_player.h"
|
||||
|
||||
class BTPauseAnimation : public BTAction {
|
||||
GDCLASS(BTPauseAnimation, BTAction);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
|
||||
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<BBNode> p_animation_player);
|
||||
Ref<BBNode> get_animation_player() const { return animation_player_param; }
|
||||
|
||||
virtual String get_configuration_warning() const override;
|
||||
};
|
||||
|
||||
#endif // BT_PAUSE_ANIMATION
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* bt_play_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 "bt_play_animation.h"
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
|
||||
//**** Setters / Getters
|
||||
|
||||
void BTPlayAnimation::set_animation_player(Ref<BBNode> 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 BTPlayAnimation::set_animation_name(StringName p_animation_name) {
|
||||
animation_name = p_animation_name;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTPlayAnimation::set_await_completion(double p_await_completion) {
|
||||
await_completion = p_await_completion;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTPlayAnimation::set_blend(double p_blend) {
|
||||
blend = p_blend;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTPlayAnimation::set_speed(double p_speed) {
|
||||
speed = p_speed;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BTPlayAnimation::set_from_end(bool p_from_end) {
|
||||
from_end = p_from_end;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
//**** Task Implementation
|
||||
|
||||
String BTPlayAnimation::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";
|
||||
}
|
||||
}
|
||||
if (animation_name == StringName() && await_completion > 0.0) {
|
||||
warning += "Animation Name is required in order to wait for the animation to finish.\n";
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
String BTPlayAnimation::_generate_name() const {
|
||||
return "PlayAnimation" +
|
||||
(animation_name != StringName() ? vformat(" \"%s\"", animation_name) : "") +
|
||||
(blend >= 0.0 ? vformat(" blend: %ss", Math::snapped(blend, 0.001)) : "") +
|
||||
(speed != 1.0 ? vformat(" speed: %s", Math::snapped(speed, 0.001)) : "") +
|
||||
(from_end != false ? vformat(" from_end: %s", from_end) : "") +
|
||||
(await_completion > 0.0 ? vformat(" await_completion: %ss", Math::snapped(await_completion, 0.001)) : "");
|
||||
}
|
||||
|
||||
void BTPlayAnimation::_setup() {
|
||||
setup_failed = true;
|
||||
ERR_FAIL_COND_MSG(animation_player_param.is_null(), "BTPlayAnimation: AnimationPlayer parameter is not set.");
|
||||
animation_player = Object::cast_to<AnimationPlayer>(animation_player_param->get_value(get_agent(), get_blackboard()));
|
||||
ERR_FAIL_COND_MSG(animation_player == nullptr, "BTPlayAnimation: Failed to get AnimationPlayer.");
|
||||
ERR_FAIL_COND_MSG(animation_name != StringName() && !animation_player->has_animation(animation_name), vformat("BTPlayAnimation: Animation not found: %s", animation_name));
|
||||
if (animation_name == StringName() && await_completion > 0.0) {
|
||||
WARN_PRINT("BTPlayAnimation: Animation Name is required in order to wait for the animation to finish.");
|
||||
}
|
||||
setup_failed = false;
|
||||
}
|
||||
|
||||
void BTPlayAnimation::_enter() {
|
||||
if (!setup_failed) {
|
||||
animation_player->play(animation_name, blend, speed, from_end);
|
||||
}
|
||||
}
|
||||
|
||||
int BTPlayAnimation::_tick(double p_delta) {
|
||||
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPlayAnimation: _setup() failed - returning FAILURE.");
|
||||
|
||||
// ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127
|
||||
if (animation_player->is_playing() && animation_player->get_assigned_animation() == animation_name) {
|
||||
if (get_elapsed_time() < await_completion) {
|
||||
return RUNNING;
|
||||
} else if (await_completion > 0.0) {
|
||||
WARN_PRINT(vformat("BTPlayAnimation: Waiting time for the \"%s\" animation exceeded the allocated %s sec.", animation_name, await_completion));
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//**** Godot
|
||||
|
||||
void BTPlayAnimation::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_animation_player", "p_anim_player"), &BTPlayAnimation::set_animation_player);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_player"), &BTPlayAnimation::get_animation_player);
|
||||
ClassDB::bind_method(D_METHOD("set_animation_name", "p_anim_name"), &BTPlayAnimation::set_animation_name);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_name"), &BTPlayAnimation::get_animation_name);
|
||||
ClassDB::bind_method(D_METHOD("set_await_completion", "p_time_sec"), &BTPlayAnimation::set_await_completion);
|
||||
ClassDB::bind_method(D_METHOD("get_await_completion"), &BTPlayAnimation::get_await_completion);
|
||||
ClassDB::bind_method(D_METHOD("set_blend", "p_blend"), &BTPlayAnimation::set_blend);
|
||||
ClassDB::bind_method(D_METHOD("get_blend"), &BTPlayAnimation::get_blend);
|
||||
ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &BTPlayAnimation::set_speed);
|
||||
ClassDB::bind_method(D_METHOD("get_speed"), &BTPlayAnimation::get_speed);
|
||||
ClassDB::bind_method(D_METHOD("set_from_end", "p_from_end"), &BTPlayAnimation::set_from_end);
|
||||
ClassDB::bind_method(D_METHOD("get_from_end"), &BTPlayAnimation::get_from_end);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "await_completion", PROPERTY_HINT_RANGE, "0.0,100.0"), "set_await_completion", "get_await_completion");
|
||||
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");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "blend"), "set_blend", "get_blend");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed"), "set_speed", "get_speed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_end"), "set_from_end", "get_from_end");
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* bt_play_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_PLAY_ANIMATION_H
|
||||
#define BT_PLAY_ANIMATION_H
|
||||
|
||||
#include "bt_action.h"
|
||||
|
||||
#include "modules/limboai/blackboard/bb_param/bb_node.h"
|
||||
|
||||
#include "scene/animation/animation_player.h"
|
||||
|
||||
class BTPlayAnimation : public BTAction {
|
||||
GDCLASS(BTPlayAnimation, BTAction);
|
||||
|
||||
private:
|
||||
Ref<BBNode> animation_player_param;
|
||||
StringName animation_name;
|
||||
double await_completion = 0.0;
|
||||
double blend = -1.0;
|
||||
double speed = 1.0;
|
||||
bool from_end = false;
|
||||
|
||||
AnimationPlayer *animation_player = nullptr;
|
||||
bool setup_failed = false;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual String _generate_name() const override;
|
||||
virtual void _setup() override;
|
||||
virtual void _enter() override;
|
||||
virtual int _tick(double p_delta) override;
|
||||
|
||||
public:
|
||||
void set_animation_player(Ref<BBNode> p_animation_player);
|
||||
Ref<BBNode> get_animation_player() const { return animation_player_param; }
|
||||
|
||||
void set_animation_name(StringName p_animation_name);
|
||||
StringName get_animation_name() const { return animation_name; }
|
||||
|
||||
void set_await_completion(double p_await_completion);
|
||||
double get_await_completion() const { return await_completion; }
|
||||
|
||||
void set_blend(double p_blend);
|
||||
double get_blend() const { return blend; }
|
||||
|
||||
void set_speed(double p_speed);
|
||||
double get_speed() const { return speed; }
|
||||
|
||||
void set_from_end(bool p_from_end);
|
||||
bool get_from_end() const { return from_end; }
|
||||
|
||||
virtual String get_configuration_warning() const override;
|
||||
};
|
||||
|
||||
#endif // BT_PLAY_ANIMATION
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* 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<BBNode> 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();
|
||||
}
|
||||
|
||||
void BTStopAnimation::set_keep_state(bool p_keep_state) {
|
||||
keep_state = p_keep_state;
|
||||
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 {
|
||||
return "StopAnimation" +
|
||||
(animation_name != StringName() ? vformat(" \"%s\"", animation_name) : "") +
|
||||
(keep_state ? " keep_state: true" : "");
|
||||
}
|
||||
|
||||
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<AnimationPlayer>(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(keep_state);
|
||||
}
|
||||
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);
|
||||
ClassDB::bind_method(D_METHOD("set_keep_state", "p_keep_state"), &BTStopAnimation::set_keep_state);
|
||||
ClassDB::bind_method(D_METHOD("get_keep_state"), &BTStopAnimation::get_keep_state);
|
||||
|
||||
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");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_state"), "set_keep_state", "get_keep_state");
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* 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<BBNode> animation_player_param;
|
||||
StringName animation_name;
|
||||
bool keep_state = false;
|
||||
|
||||
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<BBNode> p_animation_player);
|
||||
Ref<BBNode> get_animation_player() const { return animation_player_param; }
|
||||
|
||||
void set_animation_name(StringName p_animation_name);
|
||||
StringName get_animation_name() const { return animation_name; }
|
||||
|
||||
void set_keep_state(bool p_keep_state);
|
||||
bool get_keep_state() const { return keep_state; }
|
||||
|
||||
virtual String get_configuration_warning() const override;
|
||||
};
|
||||
|
||||
#endif // BT_STOP_ANIMATION
|
|
@ -60,6 +60,7 @@ def get_doc_classes():
|
|||
"BTAction",
|
||||
"BTAlwaysFail",
|
||||
"BTAlwaysSucceed",
|
||||
"BTAwaitAnimation",
|
||||
"BTCheckAgentProperty",
|
||||
"BTCheckTrigger",
|
||||
"BTCheckVar",
|
||||
|
@ -76,6 +77,8 @@ def get_doc_classes():
|
|||
"BTInvert",
|
||||
"BTNewScope",
|
||||
"BTParallel",
|
||||
"BTPauseAnimation",
|
||||
"BTPlayAnimation",
|
||||
"BTPlayer",
|
||||
"BTProbability",
|
||||
"BTRandomSelector",
|
||||
|
@ -90,6 +93,7 @@ def get_doc_classes():
|
|||
"BTSetAgentProperty",
|
||||
"BTSetVar",
|
||||
"BTState",
|
||||
"BTStopAnimation",
|
||||
"BTSubtree",
|
||||
"BTTask",
|
||||
"BTTimeLimit",
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
#*
|
||||
#* play_animation.gd
|
||||
#* =============================================================================
|
||||
#* 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.
|
||||
#* =============================================================================
|
||||
#*
|
||||
|
||||
@tool
|
||||
extends BTAction
|
||||
|
||||
@export var animation_name: String
|
||||
@export var animation_player: NodePath
|
||||
|
||||
var _player: AnimationPlayer
|
||||
var _finished: bool
|
||||
|
||||
|
||||
func _generate_name() -> String:
|
||||
return "PlayAnimation \"%s\"" % animation_name
|
||||
|
||||
|
||||
func _setup() -> void:
|
||||
_player = agent.get_node(animation_player)
|
||||
|
||||
|
||||
func _enter() -> void:
|
||||
if _player.has_animation(animation_name):
|
||||
_finished = false
|
||||
_player.play(animation_name)
|
||||
_player.animation_finished.connect(_on_animation_finished, CONNECT_ONE_SHOT)
|
||||
else:
|
||||
_finished = true
|
||||
|
||||
|
||||
func _tick(_delta: float) -> int:
|
||||
if _finished:
|
||||
return SUCCESS
|
||||
return RUNNING
|
||||
|
||||
|
||||
func _on_animation_finished(_anim):
|
||||
_finished = true
|
|
@ -1,31 +0,0 @@
|
|||
#*
|
||||
#* start_animation.gd
|
||||
#* =============================================================================
|
||||
#* 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.
|
||||
#* =============================================================================
|
||||
#*
|
||||
|
||||
@tool
|
||||
extends BTAction
|
||||
|
||||
@export var animation_name: String
|
||||
@export var animation_player: NodePath
|
||||
|
||||
var _player: AnimationPlayer
|
||||
|
||||
|
||||
func _generate_name() -> String:
|
||||
return "StartAnimation \"%s\"" % animation_name
|
||||
|
||||
|
||||
func _setup() -> void:
|
||||
_player = agent.get_node(animation_player)
|
||||
|
||||
|
||||
func _tick(p_delta: float) -> int:
|
||||
_player.play(animation_name)
|
||||
return SUCCESS
|
|
@ -1,7 +1,6 @@
|
|||
[gd_resource type="BehaviorTree" load_steps=10 format=3 uid="uid://cjkqi41oagagd"]
|
||||
|
||||
[ext_resource type="Script" path="res://ai/tasks/arrive_pos.gd" id="1_rhs33"]
|
||||
[ext_resource type="Script" path="res://ai/tasks/play_animation.gd" id="2_dg0ss"]
|
||||
|
||||
[sub_resource type="BTAction" id="BTAction_3xal7"]
|
||||
script = ExtResource("1_rhs33")
|
||||
|
@ -9,16 +8,20 @@ target_position_var = "wp"
|
|||
speed_var = "speed"
|
||||
tolerance = 50.0
|
||||
|
||||
[sub_resource type="BTAction" id="BTAction_yq1vl"]
|
||||
script = ExtResource("2_dg0ss")
|
||||
animation_name = "bounce"
|
||||
animation_player = NodePath("AnimationPlayer")
|
||||
[sub_resource type="BBNode" id="BBNode_0t2vk"]
|
||||
resource_name = "AnimationPlayer"
|
||||
saved_value = NodePath("AnimationPlayer")
|
||||
|
||||
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_s01ov"]
|
||||
await_completion = 1.0
|
||||
animation_player = SubResource("BBNode_0t2vk")
|
||||
animation_name = &"bounce"
|
||||
|
||||
[sub_resource type="BTWait" id="BTWait_qs55a"]
|
||||
duration = 0.1
|
||||
|
||||
[sub_resource type="BTSequence" id="BTSequence_a2ng0"]
|
||||
children = [SubResource("BTAction_3xal7"), SubResource("BTAction_yq1vl"), SubResource("BTWait_qs55a")]
|
||||
children = [SubResource("BTAction_3xal7"), SubResource("BTPlayAnimation_s01ov"), SubResource("BTWait_qs55a")]
|
||||
|
||||
[sub_resource type="BTForEach" id="BTForEach_0cp04"]
|
||||
children = [SubResource("BTSequence_a2ng0")]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BTAwaitAnimation" inherits="BTAction" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
BT action that waits for an animation to finish playing.
|
||||
</brief_description>
|
||||
<description>
|
||||
BTAwaitAnimation waits for an animation on the specified [AnimationPlayer] node to finish playing and returns [code]SUCCESS[/code].
|
||||
Returns [code]SUCCESS[/code] if the specified animation finished playing or if the specified animation is not currently playing.
|
||||
Returns [code]FAILURE[/code] if the specified animation doesn't exist or the action failed to get [AnimationPlayer] instance.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="animation_name" type="StringName" setter="set_animation_name" getter="get_animation_name" default="&""">
|
||||
Animation's key within the [AnimationPlayer] node.
|
||||
</member>
|
||||
<member name="animation_player" type="BBNode" setter="set_animation_player" getter="get_animation_player">
|
||||
Parameter that specifies the [AnimationPlayer] node.
|
||||
</member>
|
||||
<member name="max_time" type="float" setter="set_max_time" getter="get_max_time" default="1.0">
|
||||
Maximum duration to wait for the animation to finish (in seconds).
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BTPauseAnimation" inherits="BTAction" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
BT action that pauses playback of an animation on the specified [AnimationPlayer] node.
|
||||
</brief_description>
|
||||
<description>
|
||||
BTPauseAnimation action pauses playback of an animation on the specified [AnimationPlayer] node and returns [code]SUCCESS[/code].
|
||||
Returns [code]FAILURE[/code] if the action fails to acquire [AnimationPlayer] node.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="animation_player" type="BBNode" setter="set_animation_player" getter="get_animation_player">
|
||||
Parameter that specifies the [AnimationPlayer] node.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BTPlayAnimation" inherits="BTAction" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
BT action that plays an animation on the specified [AnimationPlayer] node.
|
||||
</brief_description>
|
||||
<description>
|
||||
BTPlayAnimation action plays an animation on the specified [AnimationPlayer] node. If the [member await_completion] is greater than [code]0[/code], the action will wait for the animation to complete, with a maximum waiting time equal to [member await_completion].
|
||||
Returns [code]SUCCESS[/code] if the animation finishes playing or if the elapsed time exceeds [member await_completion]. When [member await_completion] is set to [code]0[/code], BTPlayAnimation doesn't wait for the animation to finish and immediately returns [code]SUCCESS[/code].
|
||||
Returns [code]RUNNING[/code] if the animation is still playing and the elapsed time is less than [member await_completion].
|
||||
Returns [code]FAILURE[/code] if the action fails to play the requested animation.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="animation_name" type="StringName" setter="set_animation_name" getter="get_animation_name" default="&""">
|
||||
Animation's key within the [AnimationPlayer] node. If empty, BTPlayAnimation will resume the last played animation if [AnimationPlayer] was paused.
|
||||
</member>
|
||||
<member name="animation_player" type="BBNode" setter="set_animation_player" getter="get_animation_player">
|
||||
Parameter that specifies the [AnimationPlayer] node.
|
||||
</member>
|
||||
<member name="await_completion" type="float" setter="set_await_completion" getter="get_await_completion" default="0.0">
|
||||
Duration to wait for the animation to finish (in seconds).
|
||||
</member>
|
||||
<member name="blend" type="float" setter="set_blend" getter="get_blend" default="-1.0">
|
||||
Custom blend time (in seconds).
|
||||
</member>
|
||||
<member name="from_end" type="bool" setter="set_from_end" getter="get_from_end" default="false">
|
||||
Play animation from the end. Used in combination with negative [member speed] to play animation in reverse.
|
||||
</member>
|
||||
<member name="speed" type="float" setter="set_speed" getter="get_speed" default="1.0">
|
||||
Custom playback speed scaling ratio.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BTStopAnimation" inherits="BTAction" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
BT action that stops playback of an animation on the specified [AnimationPlayer] node.
|
||||
</brief_description>
|
||||
<description>
|
||||
BTStopAnimation action stops playback of an animation on the specified [AnimationPlayer] node and returns [code]SUCCESS[/code]. If [member animation_name] is set, it will only stop playback if the specified animation is currently playing.
|
||||
Returns [code]FAILURE[/code] if the action fails to acquire [AnimationPlayer] node.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="animation_name" type="StringName" setter="set_animation_name" getter="get_animation_name" default="&""">
|
||||
Animation's key within the [AnimationPlayer] node. If not empty, BTStopAnimation will only stop playback if the specified animation is currently playing.
|
||||
</member>
|
||||
<member name="animation_player" type="BBNode" setter="set_animation_player" getter="get_animation_player">
|
||||
Parameter that specifies the [AnimationPlayer] node.
|
||||
</member>
|
||||
<member name="keep_state" type="bool" setter="set_keep_state" getter="get_keep_state" default="false">
|
||||
If [code]true[/code], the animation state is not updated visually.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m13 1h2v2h-2z"/><path d="m13 13h2v2h-2z"/><path d="m13 5h2v2h-2z"/><path d="m13 9h2v2h-2z"/><path d="m1 9h2v2h-2z"/><path d="m1 1h2v2h-2z"/><path d="m1 13h2v2h-2z"/><path d="m1 5h2v2h-2z"/><path d="m11.5 12.6c0-.14 0-.31-.02-.5-.02-.26-.09-.56-.19-.87-.01-.03-.02-.06-.03-.09-.03-.08-.05-.16-.09-.25-.18-.46-.44-.91-.85-1.27-1.14-1-2.51-1.58-1.07-2.69s2.07-2.11 2.07-2.85c0-.44 0-1.08 0-1.08h-6.64v1.08c0 .73.63 1.73 2.07 2.85s.07 1.69-1.07 2.69c-.41.36-.68.81-.86 1.27-.04.09-.06.17-.09.25-.01.03-.02.06-.03.09-.1.31-.16.61-.19.87-.02.2-.02.36-.02.5v.4h7c.01 0 .01-.15.01-.4z"/></g></svg>
|
After Width: | Height: | Size: 710 B |
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m13 1h2v2h-2z"/><path d="m13 13h2v2h-2z"/><path d="m13 5h2v2h-2z"/><path d="m13 9h2v2h-2z"/><path d="m1 9h2v2h-2z"/><path d="m1 1h2v2h-2z"/><path d="m1 13h2v2h-2z"/><path d="m1 5h2v2h-2z"/><path d="m5 5h2v6h-2z"/><path d="m9 5h2v6h-2z"/></g></svg>
|
After Width: | Height: | Size: 368 B |
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m13 1h2v2h-2z"/><path d="m13 13h2v2h-2z"/><path d="m13 5h2v2h-2z"/><path d="m13 9h2v2h-2z"/><path d="m5 4.5v3.5 3.5l3-1.75 3-1.75-3-1.75z"/><path d="m1 9h2v2h-2z"/><path d="m1 1h2v2h-2z"/><path d="m1 13h2v2h-2z"/><path d="m1 5h2v2h-2z"/></g></svg>
|
After Width: | Height: | Size: 368 B |
|
@ -0,0 +1 @@
|
|||
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m13 1h2v2h-2z"/><path d="m13 13h2v2h-2z"/><path d="m13 5h2v2h-2z"/><path d="m13 9h2v2h-2z"/><path d="m1 9h2v2h-2z"/><path d="m1 1h2v2h-2z"/><path d="m1 13h2v2h-2z"/><path d="m1 5h2v2h-2z"/><path d="m5 5h6v6h-6z"/></g></svg>
|
After Width: | Height: | Size: 344 B |
|
@ -45,11 +45,15 @@
|
|||
#include "blackboard/bb_param/bb_vector4i.h"
|
||||
#include "blackboard/blackboard.h"
|
||||
#include "bt/actions/bt_action.h"
|
||||
#include "bt/actions/bt_await_animation.h"
|
||||
#include "bt/actions/bt_console_print.h"
|
||||
#include "bt/actions/bt_fail.h"
|
||||
#include "bt/actions/bt_pause_animation.h"
|
||||
#include "bt/actions/bt_play_animation.h"
|
||||
#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"
|
||||
|
@ -139,12 +143,16 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
|||
GDREGISTER_CLASS(BTForEach);
|
||||
|
||||
GDREGISTER_CLASS(BTAction);
|
||||
GDREGISTER_CLASS(BTAwaitAnimation);
|
||||
GDREGISTER_CLASS(BTConsolePrint);
|
||||
GDREGISTER_CLASS(BTFail);
|
||||
GDREGISTER_CLASS(BTNewScope);
|
||||
GDREGISTER_CLASS(BTPauseAnimation);
|
||||
GDREGISTER_CLASS(BTPlayAnimation);
|
||||
GDREGISTER_CLASS(BTRandomWait);
|
||||
GDREGISTER_CLASS(BTSetAgentProperty);
|
||||
GDREGISTER_CLASS(BTSetVar);
|
||||
GDREGISTER_CLASS(BTStopAnimation);
|
||||
GDREGISTER_CLASS(BTSubtree);
|
||||
GDREGISTER_CLASS(BTWait);
|
||||
GDREGISTER_CLASS(BTWaitTicks);
|
||||
|
|
Loading…
Reference in New Issue