2023-07-21 09:50:06 +00:00
|
|
|
/**
|
|
|
|
* bt_task.cpp
|
|
|
|
* =============================================================================
|
2024-03-04 20:36:16 +00:00
|
|
|
* Copyright 2021-2024 Serhii Snitsaruk
|
2023-07-21 09:50:06 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
* =============================================================================
|
|
|
|
*/
|
2022-08-28 10:54:34 +00:00
|
|
|
|
|
|
|
#include "bt_task.h"
|
2024-01-06 20:04:34 +00:00
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
#include "../../blackboard/blackboard.h"
|
|
|
|
#include "../../util/limbo_string_names.h"
|
|
|
|
#include "../../util/limbo_utility.h"
|
2024-05-14 09:39:32 +00:00
|
|
|
#include "../behavior_tree.h"
|
2023-08-19 10:19:58 +00:00
|
|
|
#include "bt_comment.h"
|
2023-07-20 16:35:36 +00:00
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
#ifdef LIMBOAI_MODULE
|
2022-12-15 07:26:52 +00:00
|
|
|
#include "core/error/error_macros.h"
|
|
|
|
#include "core/io/resource.h"
|
|
|
|
#include "core/object/class_db.h"
|
|
|
|
#include "core/object/object.h"
|
|
|
|
#include "core/object/ref_counted.h"
|
|
|
|
#include "core/object/script_language.h"
|
|
|
|
#include "core/string/ustring.h"
|
|
|
|
#include "core/templates/hash_map.h"
|
|
|
|
#include "core/variant/variant.h"
|
2024-01-06 20:04:34 +00:00
|
|
|
#endif // LIMBOAI_MODULE
|
|
|
|
|
|
|
|
#ifdef LIMBOAI_GDEXTENSION
|
2024-01-09 20:47:22 +00:00
|
|
|
#include "godot_cpp/classes/global_constants.hpp"
|
|
|
|
#include "godot_cpp/core/class_db.hpp"
|
|
|
|
#include "godot_cpp/variant/dictionary.hpp"
|
|
|
|
#include "godot_cpp/variant/string_name.hpp"
|
|
|
|
#include "godot_cpp/variant/typed_array.hpp"
|
|
|
|
#include "godot_cpp/variant/utility_functions.hpp"
|
|
|
|
#include "godot_cpp/variant/variant.hpp"
|
2024-01-06 20:04:34 +00:00
|
|
|
#include <godot_cpp/classes/ref.hpp>
|
2024-01-13 16:10:42 +00:00
|
|
|
#include <godot_cpp/classes/script.hpp>
|
2024-01-06 20:04:34 +00:00
|
|
|
#endif // LIMBOAI_GDEXTENSION
|
2022-08-28 10:54:34 +00:00
|
|
|
|
2023-09-19 11:43:26 +00:00
|
|
|
void BT::_bind_methods() {
|
|
|
|
BIND_ENUM_CONSTANT(FRESH);
|
|
|
|
BIND_ENUM_CONSTANT(RUNNING);
|
|
|
|
BIND_ENUM_CONSTANT(FAILURE);
|
|
|
|
BIND_ENUM_CONSTANT(SUCCESS);
|
|
|
|
}
|
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
String BTTask::_generate_name() {
|
2024-01-13 12:35:16 +00:00
|
|
|
String ret;
|
|
|
|
|
|
|
|
// Generate name based on script path.
|
|
|
|
Ref<Script> sc = GET_SCRIPT(this);
|
|
|
|
if (sc.is_valid() && sc->get_path().is_absolute_path()) {
|
|
|
|
ret = sc->get_path().get_basename().get_file().to_pascal_case();
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2024-01-06 20:04:34 +00:00
|
|
|
|
2024-01-13 12:35:16 +00:00
|
|
|
// Generate name based on core class name.
|
|
|
|
if (ret.is_empty()) {
|
|
|
|
ret = get_class();
|
2024-01-06 20:04:34 +00:00
|
|
|
}
|
2024-01-13 12:35:16 +00:00
|
|
|
|
|
|
|
return ret.trim_prefix("BT");
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Array BTTask::_get_children() const {
|
|
|
|
Array arr;
|
|
|
|
int num_children = get_child_count();
|
|
|
|
arr.resize(num_children);
|
|
|
|
for (int i = 0; i < num_children; i++) {
|
|
|
|
arr[i] = get_child(i).ptr();
|
|
|
|
}
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BTTask::_set_children(Array p_children) {
|
|
|
|
const int num_children = p_children.size();
|
2024-02-08 16:10:31 +00:00
|
|
|
int num_null = 0;
|
|
|
|
|
|
|
|
data.children.clear();
|
2023-07-20 18:10:02 +00:00
|
|
|
data.children.resize(num_children);
|
2024-02-08 16:10:31 +00:00
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
for (int i = 0; i < num_children; i++) {
|
2024-02-08 16:10:31 +00:00
|
|
|
Ref<BTTask> task = p_children[i];
|
|
|
|
if (task.is_null()) {
|
|
|
|
ERR_PRINT("Invalid BTTask reference.");
|
|
|
|
num_null += 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (task->data.parent != nullptr && task->data.parent != this) {
|
|
|
|
task = task->clone();
|
|
|
|
if (task.is_null()) {
|
|
|
|
// * BTComment::clone() returns nullptr at runtime - we omit those.
|
|
|
|
num_null += 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int idx = i - num_null;
|
|
|
|
task->data.parent = this;
|
|
|
|
task->data.index = idx;
|
|
|
|
data.children.set(idx, task);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_null > 0) {
|
|
|
|
data.children.resize(num_children - num_null);
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 15:46:26 +00:00
|
|
|
void BTTask::set_display_collapsed(bool p_display_collapsed) {
|
|
|
|
data.display_collapsed = p_display_collapsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BTTask::is_displayed_collapsed() const {
|
|
|
|
return data.display_collapsed;
|
|
|
|
}
|
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
String BTTask::get_task_name() {
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.custom_name.is_empty()) {
|
2024-01-13 12:35:16 +00:00
|
|
|
#ifdef LIMBOAI_MODULE
|
|
|
|
if (get_script_instance() && get_script_instance()->has_method(LW_NAME(_generate_name))) {
|
|
|
|
if (unlikely(!get_script_instance()->get_script()->is_tool())) {
|
|
|
|
ERR_PRINT(vformat("BTTask: Task script should be a \"tool\" script!"));
|
|
|
|
} else {
|
|
|
|
return get_script_instance()->call(LimboStringNames::get_singleton()->_generate_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return _generate_name();
|
2024-01-13 16:10:42 +00:00
|
|
|
#elif LIMBOAI_GDEXTENSION
|
2024-02-10 14:05:50 +00:00
|
|
|
Ref<Script> task_script = get_script();
|
|
|
|
if (task_script.is_valid() && task_script->is_tool()) {
|
|
|
|
Variant call_result;
|
|
|
|
VCALL_OR_NATIVE_V(_generate_name, Variant, call_result);
|
|
|
|
ERR_FAIL_COND_V(call_result.get_type() == Variant::NIL, _generate_name());
|
|
|
|
String task_name = call_result;
|
|
|
|
ERR_FAIL_COND_V(task_name.is_empty(), _generate_name());
|
|
|
|
return task_name;
|
|
|
|
} else {
|
|
|
|
return _generate_name();
|
|
|
|
}
|
2024-01-13 12:35:16 +00:00
|
|
|
#endif
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-07-20 18:10:02 +00:00
|
|
|
return data.custom_name;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ref<BTTask> BTTask::get_root() const {
|
|
|
|
const BTTask *task = this;
|
|
|
|
while (!task->is_root()) {
|
2023-07-20 18:10:02 +00:00
|
|
|
task = task->data.parent;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
return Ref<BTTask>(task);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BTTask::set_custom_name(const String &p_name) {
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.custom_name != p_name) {
|
|
|
|
data.custom_name = p_name;
|
2022-08-28 10:54:34 +00:00
|
|
|
emit_changed();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-05-01 21:20:17 +00:00
|
|
|
void BTTask::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard, Node *p_scene_root) {
|
|
|
|
ERR_FAIL_NULL(p_agent);
|
|
|
|
ERR_FAIL_NULL(p_blackboard);
|
|
|
|
ERR_FAIL_NULL(p_scene_root);
|
2023-07-20 18:10:02 +00:00
|
|
|
data.agent = p_agent;
|
|
|
|
data.blackboard = p_blackboard;
|
2024-05-01 21:20:17 +00:00
|
|
|
data.scene_root = p_scene_root;
|
2023-07-20 18:10:02 +00:00
|
|
|
for (int i = 0; i < data.children.size(); i++) {
|
2024-05-01 21:20:17 +00:00
|
|
|
get_child(i)->initialize(p_agent, p_blackboard, p_scene_root);
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2022-12-15 07:26:52 +00:00
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
VCALL_OR_NATIVE(_setup);
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ref<BTTask> BTTask::clone() const {
|
2022-09-02 22:08:10 +00:00
|
|
|
Ref<BTTask> inst = duplicate(false);
|
2024-02-08 16:10:31 +00:00
|
|
|
|
|
|
|
// * Children are duplicated via children property. See _set_children().
|
2022-10-21 14:15:13 +00:00
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
#ifdef LIMBOAI_MODULE
|
2022-10-21 14:15:13 +00:00
|
|
|
// Make BBParam properties unique.
|
|
|
|
List<PropertyInfo> props;
|
|
|
|
inst->get_property_list(&props);
|
2022-12-15 07:26:52 +00:00
|
|
|
HashMap<Ref<Resource>, Ref<Resource>> duplicates;
|
2022-10-21 14:15:13 +00:00
|
|
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
|
|
|
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Variant v = inst->get(E->get().name);
|
|
|
|
|
2022-12-15 07:26:52 +00:00
|
|
|
if (v.is_ref_counted()) {
|
|
|
|
Ref<RefCounted> ref = v;
|
2022-10-21 14:15:13 +00:00
|
|
|
if (ref.is_valid()) {
|
2022-12-15 07:26:52 +00:00
|
|
|
Ref<Resource> res = ref;
|
2022-10-21 14:15:13 +00:00
|
|
|
if (res.is_valid() && res->is_class("BBParam")) {
|
|
|
|
if (!duplicates.has(res)) {
|
|
|
|
duplicates[res] = res->duplicate();
|
|
|
|
}
|
|
|
|
res = duplicates[res];
|
|
|
|
inst->set(E->get().name, res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-13 16:10:42 +00:00
|
|
|
#elif LIMBOAI_GDEXTENSION
|
2024-01-06 20:04:34 +00:00
|
|
|
// Make BBParam properties unique.
|
|
|
|
TypedArray<Dictionary> props = inst->get_property_list();
|
|
|
|
HashMap<Ref<Resource>, Ref<Resource>> duplicates;
|
|
|
|
for (int i = 0; i < props.size(); i++) {
|
|
|
|
Dictionary prop = props[i];
|
|
|
|
if (!(int(prop["usage"]) & PROPERTY_USAGE_STORAGE)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringName prop_name = prop["name"];
|
|
|
|
Variant v = inst->get(prop_name);
|
|
|
|
|
|
|
|
if (v.get_type() == Variant::OBJECT && int(prop["hint"]) == PROPERTY_HINT_RESOURCE_TYPE) {
|
|
|
|
Ref<RefCounted> ref = v;
|
|
|
|
if (ref.is_valid()) {
|
|
|
|
Ref<Resource> res = ref;
|
|
|
|
if (res.is_valid() && res->is_class("BBParam")) {
|
|
|
|
if (!duplicates.has(res)) {
|
|
|
|
duplicates[res] = res->duplicate();
|
|
|
|
}
|
|
|
|
res = duplicates[res];
|
|
|
|
inst->set(prop_name, res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-13 16:10:42 +00:00
|
|
|
#endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION
|
2022-10-21 14:15:13 +00:00
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
return inst;
|
|
|
|
}
|
|
|
|
|
2023-09-19 11:43:26 +00:00
|
|
|
BT::Status BTTask::execute(double p_delta) {
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.status != RUNNING) {
|
2023-04-14 08:16:26 +00:00
|
|
|
// Reset children status.
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.status != FRESH) {
|
2023-04-14 08:16:26 +00:00
|
|
|
for (int i = 0; i < get_child_count(); i++) {
|
2023-10-26 14:20:33 +00:00
|
|
|
data.children.get(i)->abort();
|
2023-04-14 08:16:26 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-06 20:04:34 +00:00
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
VCALL_OR_NATIVE(_enter);
|
2023-04-14 08:16:26 +00:00
|
|
|
} else {
|
2023-07-20 18:10:02 +00:00
|
|
|
data.elapsed += p_delta;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2022-08-31 15:05:25 +00:00
|
|
|
|
2024-01-17 21:46:48 +00:00
|
|
|
VCALL_OR_NATIVE_ARGS_V(_tick, Status, data.status, p_delta);
|
2022-08-28 10:54:34 +00:00
|
|
|
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.status != RUNNING) {
|
2024-01-13 16:10:42 +00:00
|
|
|
VCALL_OR_NATIVE(_exit);
|
2023-07-20 18:10:02 +00:00
|
|
|
data.elapsed = 0.0;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-07-20 18:10:02 +00:00
|
|
|
return data.status;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
2023-10-26 14:20:33 +00:00
|
|
|
void BTTask::abort() {
|
2023-07-20 18:10:02 +00:00
|
|
|
for (int i = 0; i < data.children.size(); i++) {
|
2023-10-26 14:20:33 +00:00
|
|
|
get_child(i)->abort();
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.status == RUNNING) {
|
2024-01-13 16:10:42 +00:00
|
|
|
VCALL_OR_NATIVE(_exit);
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-07-20 18:10:02 +00:00
|
|
|
data.status = FRESH;
|
|
|
|
data.elapsed = 0.0;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
2023-08-19 10:19:58 +00:00
|
|
|
int BTTask::get_child_count_excluding_comments() const {
|
|
|
|
int count = 0;
|
|
|
|
for (int i = 0; i < data.children.size(); i++) {
|
2024-01-06 23:47:46 +00:00
|
|
|
if (!IS_CLASS(data.children[i], BTComment)) {
|
2024-01-06 20:04:34 +00:00
|
|
|
count += 1;
|
|
|
|
}
|
2023-08-19 10:19:58 +00:00
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
void BTTask::add_child(Ref<BTTask> p_child) {
|
2022-08-30 16:48:49 +00:00
|
|
|
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
2023-07-20 18:10:02 +00:00
|
|
|
p_child->data.parent = this;
|
2023-11-22 12:05:55 +00:00
|
|
|
p_child->data.index = data.children.size();
|
2023-07-20 18:10:02 +00:00
|
|
|
data.children.push_back(p_child);
|
2022-08-28 10:54:34 +00:00
|
|
|
emit_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BTTask::add_child_at_index(Ref<BTTask> p_child, int p_idx) {
|
2022-08-30 16:48:49 +00:00
|
|
|
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
2023-07-20 18:10:02 +00:00
|
|
|
if (p_idx < 0 || p_idx > data.children.size()) {
|
|
|
|
p_idx = data.children.size();
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-07-20 18:10:02 +00:00
|
|
|
p_child->data.parent = this;
|
2023-11-22 12:05:55 +00:00
|
|
|
p_child->data.index = p_idx;
|
2024-02-08 16:10:31 +00:00
|
|
|
data.children.insert(p_idx, p_child);
|
2023-11-22 12:05:55 +00:00
|
|
|
for (int i = p_idx + 1; i < data.children.size(); i++) {
|
|
|
|
get_child(i)->data.index = i;
|
|
|
|
}
|
2022-08-28 10:54:34 +00:00
|
|
|
emit_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BTTask::remove_child(Ref<BTTask> p_child) {
|
2023-07-20 18:10:02 +00:00
|
|
|
int idx = data.children.find(p_child);
|
2023-11-22 12:05:55 +00:00
|
|
|
ERR_FAIL_COND_MSG(idx == -1, "p_child not found!");
|
|
|
|
data.children.remove_at(idx);
|
|
|
|
p_child->data.parent = nullptr;
|
|
|
|
p_child->data.index = -1;
|
|
|
|
for (int i = idx; i < data.children.size(); i++) {
|
|
|
|
get_child(i)->data.index = i;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
2023-11-22 12:05:55 +00:00
|
|
|
emit_changed();
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
2022-09-21 14:13:17 +00:00
|
|
|
void BTTask::remove_child_at_index(int p_idx) {
|
|
|
|
ERR_FAIL_INDEX(p_idx, get_child_count());
|
2023-11-22 12:05:55 +00:00
|
|
|
data.children[p_idx]->data.parent = nullptr;
|
|
|
|
data.children[p_idx]->data.index = -1;
|
2023-07-20 18:10:02 +00:00
|
|
|
data.children.remove_at(p_idx);
|
2023-11-22 12:05:55 +00:00
|
|
|
for (int i = p_idx; i < data.children.size(); i++) {
|
|
|
|
get_child(i)->data.index = i;
|
|
|
|
}
|
|
|
|
emit_changed();
|
2022-09-21 14:13:17 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 15:00:20 +00:00
|
|
|
bool BTTask::is_descendant_of(const Ref<BTTask> &p_task) const {
|
|
|
|
const BTTask *task = this;
|
|
|
|
while (task != nullptr) {
|
2023-07-20 18:10:02 +00:00
|
|
|
task = task->data.parent;
|
2022-09-03 15:00:20 +00:00
|
|
|
if (task == p_task.ptr()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
Ref<BTTask> BTTask::next_sibling() const {
|
2023-07-20 18:10:02 +00:00
|
|
|
if (data.parent != nullptr) {
|
2023-11-22 12:05:55 +00:00
|
|
|
if (get_index() != -1 && data.parent->get_child_count() > (get_index() + 1)) {
|
|
|
|
return data.parent->get_child(get_index() + 1);
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ref<BTTask>();
|
|
|
|
}
|
|
|
|
|
2024-01-13 16:10:42 +00:00
|
|
|
PackedStringArray BTTask::_get_configuration_warnings() {
|
|
|
|
return PackedStringArray();
|
|
|
|
}
|
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
PackedStringArray BTTask::get_configuration_warnings() {
|
2023-08-15 15:05:30 +00:00
|
|
|
PackedStringArray ret;
|
2022-12-15 07:26:52 +00:00
|
|
|
|
2023-08-15 15:05:30 +00:00
|
|
|
PackedStringArray warnings;
|
2024-02-10 14:05:50 +00:00
|
|
|
Ref<Script> task_script = get_script();
|
|
|
|
if (task_script.is_valid() && task_script->is_tool()) {
|
|
|
|
VCALL_V(_get_configuration_warnings, warnings); // Get script warnings.
|
|
|
|
}
|
2024-01-06 20:04:34 +00:00
|
|
|
ret.append_array(warnings);
|
2024-01-17 21:46:48 +00:00
|
|
|
ret.append_array(_get_configuration_warnings());
|
2022-12-15 07:26:52 +00:00
|
|
|
|
2023-08-15 15:05:30 +00:00
|
|
|
return ret;
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
void BTTask::print_tree(int p_initial_tabs) {
|
2022-08-28 10:54:34 +00:00
|
|
|
String tabs = "--";
|
|
|
|
for (int i = 0; i < p_initial_tabs; i++) {
|
|
|
|
tabs += "--";
|
|
|
|
}
|
2024-01-06 20:04:34 +00:00
|
|
|
|
2024-01-09 12:34:24 +00:00
|
|
|
PRINT_LINE(vformat("%s Name: %s Instance: %s", tabs, get_task_name(), Ref<BTTask>(this)));
|
2024-01-06 20:04:34 +00:00
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
for (int i = 0; i < get_child_count(); i++) {
|
|
|
|
get_child(i)->print_tree(p_initial_tabs + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-14 09:39:32 +00:00
|
|
|
Ref<BehaviorTree> BTTask::editor_get_behavior_tree() {
|
|
|
|
BTTask *task = this;
|
|
|
|
while (task->data.behavior_tree.is_null() && task->get_parent().is_valid()) {
|
|
|
|
task = task->data.parent;
|
|
|
|
}
|
|
|
|
return task->data.behavior_tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BTTask::editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt) {
|
|
|
|
data.behavior_tree = p_bt;
|
|
|
|
}
|
|
|
|
|
2022-08-28 10:54:34 +00:00
|
|
|
void BTTask::_bind_methods() {
|
2022-12-17 07:33:18 +00:00
|
|
|
// Public Methods.
|
|
|
|
ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_root"), &BTTask::get_root);
|
2024-05-01 23:27:14 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("initialize", "agent", "blackboard", "scene_root"), &BTTask::initialize);
|
2022-12-17 07:33:18 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("clone"), &BTTask::clone);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("execute", "delta"), &BTTask::execute);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_child", "idx"), &BTTask::get_child);
|
2022-12-17 07:33:18 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_child_count"), &BTTask::get_child_count);
|
2023-08-19 10:19:58 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_child_count_excluding_comments"), &BTTask::get_child_count_excluding_comments);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("add_child", "task"), &BTTask::add_child);
|
|
|
|
ClassDB::bind_method(D_METHOD("add_child_at_index", "task", "idx"), &BTTask::add_child_at_index);
|
|
|
|
ClassDB::bind_method(D_METHOD("remove_child", "task"), &BTTask::remove_child);
|
|
|
|
ClassDB::bind_method(D_METHOD("remove_child_at_index", "idx"), &BTTask::remove_child_at_index);
|
|
|
|
ClassDB::bind_method(D_METHOD("has_child", "task"), &BTTask::has_child);
|
|
|
|
ClassDB::bind_method(D_METHOD("is_descendant_of", "task"), &BTTask::is_descendant_of);
|
2023-11-22 12:05:55 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_index"), &BTTask::get_index);
|
2022-12-17 07:33:18 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("next_sibling"), &BTTask::next_sibling);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("print_tree", "initial_tabs"), &BTTask::print_tree, Variant(0));
|
2022-12-17 07:33:18 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name);
|
2023-10-26 14:20:33 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("abort"), &BTTask::abort);
|
2024-05-14 09:39:32 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("editor_get_behavior_tree"), &BTTask::editor_get_behavior_tree);
|
2022-10-24 22:47:22 +00:00
|
|
|
|
2022-12-17 07:33:18 +00:00
|
|
|
// Properties, setters and getters.
|
2022-08-28 10:54:34 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("set_agent", "agent"), &BTTask::set_agent);
|
2024-05-01 21:20:17 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_scene_root"), &BTTask::get_scene_root);
|
2022-11-02 16:47:07 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("_get_children"), &BTTask::_get_children);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("_set_children", "children"), &BTTask::_set_children);
|
2022-08-28 10:54:34 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_parent"), &BTTask::get_parent);
|
2022-10-24 22:47:22 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_status"), &BTTask::get_status);
|
2023-04-14 08:16:26 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_elapsed_time"), &BTTask::get_elapsed_time);
|
2023-10-26 14:20:33 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("get_custom_name"), &BTTask::get_custom_name);
|
2024-03-04 20:36:16 +00:00
|
|
|
ClassDB::bind_method(D_METHOD("set_custom_name", "name"), &BTTask::set_custom_name);
|
2022-10-24 22:47:22 +00:00
|
|
|
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name");
|
2023-07-27 11:52:29 +00:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_agent", "get_agent");
|
2024-05-01 21:20:17 +00:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_NODE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_scene_root");
|
2023-07-27 11:52:29 +00:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", PROPERTY_USAGE_NONE), "", "get_blackboard");
|
2022-12-15 07:26:52 +00:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_children", "_get_children");
|
2023-07-27 11:52:29 +00:00
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "status", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_status");
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "elapsed_time", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_elapsed_time");
|
2022-08-28 10:54:34 +00:00
|
|
|
|
2024-01-06 20:04:34 +00:00
|
|
|
#ifdef LIMBOAI_MODULE
|
2022-12-15 07:26:52 +00:00
|
|
|
GDVIRTUAL_BIND(_setup);
|
|
|
|
GDVIRTUAL_BIND(_enter);
|
|
|
|
GDVIRTUAL_BIND(_exit);
|
2024-03-04 20:36:16 +00:00
|
|
|
GDVIRTUAL_BIND(_tick, "delta");
|
2022-12-15 07:26:52 +00:00
|
|
|
GDVIRTUAL_BIND(_generate_name);
|
2024-01-13 16:10:42 +00:00
|
|
|
GDVIRTUAL_BIND(_get_configuration_warnings);
|
|
|
|
#elif LIMBOAI_GDEXTENSION
|
2024-01-17 21:46:48 +00:00
|
|
|
// TODO: Registering virtual functions is not available in godot-cpp...
|
2024-01-06 20:04:34 +00:00
|
|
|
#endif
|
2022-08-28 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BTTask::BTTask() {
|
2022-08-30 16:48:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BTTask::~BTTask() {
|
|
|
|
for (int i = 0; i < get_child_count(); i++) {
|
|
|
|
ERR_FAIL_COND(!get_child(i).is_valid());
|
2023-07-20 18:10:02 +00:00
|
|
|
get_child(i)->data.parent = nullptr;
|
2022-08-30 16:48:49 +00:00
|
|
|
get_child(i).unref();
|
|
|
|
}
|
2022-11-02 16:47:07 +00:00
|
|
|
}
|