Add BTPlayer and BehaviorTree classes, and fix leaking refs
This commit is contained in:
parent
6105c17f09
commit
a236aee22b
|
@ -0,0 +1,45 @@
|
||||||
|
/* behavior_tree.cpp */
|
||||||
|
|
||||||
|
#include "behavior_tree.h"
|
||||||
|
#include "core/class_db.h"
|
||||||
|
#include "core/list.h"
|
||||||
|
#include "core/object.h"
|
||||||
|
#include "core/variant.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
void BehaviorTree::init() {
|
||||||
|
List<BTTask *> stack;
|
||||||
|
BTTask *task = root_task.ptr();
|
||||||
|
while (task != nullptr) {
|
||||||
|
for (int i = 0; i < task->get_child_count(); i++) {
|
||||||
|
task->get_child(i)->_parent = task;
|
||||||
|
stack.push_back(task->get_child(i).ptr());
|
||||||
|
}
|
||||||
|
task = nullptr;
|
||||||
|
if (!stack.empty()) {
|
||||||
|
task = stack.front()->get();
|
||||||
|
stack.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<BehaviorTree> BehaviorTree::clone() const {
|
||||||
|
Ref<BehaviorTree> copy = duplicate(false);
|
||||||
|
copy->set_path("");
|
||||||
|
if (root_task.is_valid()) {
|
||||||
|
copy->root_task = root_task->clone();
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BehaviorTree::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("set_description", "p_value"), &BehaviorTree::set_description);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_root_task", "p_value"), &BehaviorTree::set_root_task);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_root_task);
|
||||||
|
ClassDB::bind_method(D_METHOD("init"), &BehaviorTree::init);
|
||||||
|
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_task", PROPERTY_HINT_RESOURCE_TYPE, "BTTask"), "set_root_task", "get_root_task");
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* behavior_tree.h */
|
||||||
|
|
||||||
|
#ifndef BEHAVIOR_TREE_H
|
||||||
|
#define BEHAVIOR_TREE_H
|
||||||
|
|
||||||
|
#include "core/object.h"
|
||||||
|
#include "core/resource.h"
|
||||||
|
|
||||||
|
#include "bt_task.h"
|
||||||
|
|
||||||
|
class BehaviorTree : public Resource {
|
||||||
|
GDCLASS(BehaviorTree, Resource);
|
||||||
|
|
||||||
|
private:
|
||||||
|
String description;
|
||||||
|
Ref<BTTask> root_task;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_description(String p_value) {
|
||||||
|
description = p_value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
String get_description() const { return description; }
|
||||||
|
|
||||||
|
void set_root_task(const Ref<BTTask> &p_value) {
|
||||||
|
root_task = p_value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
Ref<BTTask> get_root_task() const { return root_task; }
|
||||||
|
|
||||||
|
void init();
|
||||||
|
Ref<BehaviorTree> clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BEHAVIOR_TREE_H
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* bt_player.cpp */
|
||||||
|
|
||||||
|
#include "bt_player.h"
|
||||||
|
|
||||||
|
#include "../limbo_string_names.h"
|
||||||
|
#include "bt_task.h"
|
||||||
|
#include "core/class_db.h"
|
||||||
|
#include "core/engine.h"
|
||||||
|
#include "core/io/resource_loader.h"
|
||||||
|
#include "core/object.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(BTPlayer::UpdateMode);
|
||||||
|
|
||||||
|
void BTPlayer::_load_tree() {
|
||||||
|
_loaded_tree.unref();
|
||||||
|
_root_task.unref();
|
||||||
|
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer needs a valid behavior tree.");
|
||||||
|
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "Behavior tree has no valid root task.");
|
||||||
|
_loaded_tree = behavior_tree;
|
||||||
|
_root_task = _loaded_tree->get_root_task()->clone();
|
||||||
|
_root_task->initialize(get_owner(), blackboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||||
|
behavior_tree = p_tree;
|
||||||
|
if (Engine::get_singleton()->is_editor_hint() == false) {
|
||||||
|
_load_tree();
|
||||||
|
set_update_mode(update_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::set_update_mode(UpdateMode p_mode) {
|
||||||
|
update_mode = p_mode;
|
||||||
|
set_active(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::set_active(bool p_active) {
|
||||||
|
active = p_active;
|
||||||
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
set_process(update_mode == UpdateMode::IDLE);
|
||||||
|
set_physics_process(update_mode == UpdateMode::PHYSICS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::update(float p_delta) {
|
||||||
|
if (!_root_task.is_valid()) {
|
||||||
|
ERR_PRINT_ONCE(vformat("BTPlayer has no root task to update (owner: %s)", get_owner()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (active) {
|
||||||
|
int status = _root_task->execute(p_delta);
|
||||||
|
if (status == BTTask::SUCCESS || status == BTTask::FAILURE) {
|
||||||
|
set_active(auto_restart);
|
||||||
|
emit_signal(LimboStringNames::get_singleton()->behavior_tree_finished, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::restart() {
|
||||||
|
_root_task->cancel();
|
||||||
|
set_active(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::_notification(int p_notification) {
|
||||||
|
switch (p_notification) {
|
||||||
|
case NOTIFICATION_PROCESS: {
|
||||||
|
if (active) {
|
||||||
|
Variant time = get_process_delta_time();
|
||||||
|
update(time);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case NOTIFICATION_PHYSICS_PROCESS: {
|
||||||
|
if (active) {
|
||||||
|
Variant time = get_process_delta_time();
|
||||||
|
update(time);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case NOTIFICATION_READY: {
|
||||||
|
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
if (behavior_tree.is_valid()) {
|
||||||
|
_load_tree();
|
||||||
|
}
|
||||||
|
set_active(active);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTPlayer::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("set_behavior_tree", "p_path"), &BTPlayer::set_behavior_tree);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_behavior_tree"), &BTPlayer::get_behavior_tree);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_update_mode", "p_mode"), &BTPlayer::set_update_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_update_mode"), &BTPlayer::get_update_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_active", "p_active"), &BTPlayer::set_active);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_active"), &BTPlayer::get_active);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_auto_restart", "p_value"), &BTPlayer::set_auto_restart);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_auto_restart"), &BTPlayer::get_auto_restart);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("update", "p_delta"), &BTPlayer::update);
|
||||||
|
ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_restart"), "set_auto_restart", "get_auto_restart");
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(IDLE);
|
||||||
|
BIND_ENUM_CONSTANT(PHYSICS);
|
||||||
|
BIND_ENUM_CONSTANT(MANUAL);
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* bt_player.h */
|
||||||
|
|
||||||
|
#ifndef BT_PLAYER_H
|
||||||
|
#define BT_PLAYER_H
|
||||||
|
|
||||||
|
#include "core/object.h"
|
||||||
|
#include "scene/main/node.h"
|
||||||
|
|
||||||
|
#include "behavior_tree.h"
|
||||||
|
#include "bt_task.h"
|
||||||
|
#include <pulse/proplist.h>
|
||||||
|
|
||||||
|
class BTPlayer : public Node {
|
||||||
|
GDCLASS(BTPlayer, Node);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum UpdateMode : unsigned int {
|
||||||
|
IDLE, // automatically call update() during NOTIFICATION_PROCESS
|
||||||
|
PHYSICS, //# automatically call update() during NOTIFICATION_PHYSICS
|
||||||
|
MANUAL, // manually update state machine, user must call update(delta)
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<BehaviorTree> behavior_tree;
|
||||||
|
UpdateMode update_mode = UpdateMode::IDLE;
|
||||||
|
bool active = false;
|
||||||
|
bool auto_restart = false;
|
||||||
|
Dictionary blackboard;
|
||||||
|
|
||||||
|
Ref<BehaviorTree> _loaded_tree;
|
||||||
|
Ref<BTTask> _root_task;
|
||||||
|
|
||||||
|
void _load_tree();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
void _notification(int p_notification);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||||
|
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||||
|
|
||||||
|
void set_update_mode(UpdateMode p_mode);
|
||||||
|
UpdateMode get_update_mode() const { return update_mode; }
|
||||||
|
|
||||||
|
void set_active(bool p_active);
|
||||||
|
bool get_active() const { return active; }
|
||||||
|
|
||||||
|
void set_auto_restart(bool p_value) { auto_restart = p_value; }
|
||||||
|
bool get_auto_restart() const { return auto_restart; }
|
||||||
|
|
||||||
|
void update(float p_delta);
|
||||||
|
void restart();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BT_PLAYER_H
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
#include "bt_task.h"
|
#include "bt_task.h"
|
||||||
|
|
||||||
|
#include "../limbo_string_names.h"
|
||||||
|
#include "../limbo_utility.h"
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
#include "core/script_language.h"
|
#include "core/script_language.h"
|
||||||
#include "core/variant.h"
|
#include "core/variant.h"
|
||||||
#include "editor/editor_node.h"
|
#include "editor/editor_node.h"
|
||||||
|
#include <cstddef>
|
||||||
#include "../limbo_string_names.h"
|
|
||||||
#include "../limbo_utility.h"
|
|
||||||
|
|
||||||
String BTTask::_generate_name() const {
|
String BTTask::_generate_name() const {
|
||||||
if (get_script_instance()) {
|
if (get_script_instance()) {
|
||||||
|
@ -58,7 +58,7 @@ String BTTask::get_task_name() const {
|
||||||
Ref<BTTask> BTTask::get_root() const {
|
Ref<BTTask> BTTask::get_root() const {
|
||||||
const BTTask *task = this;
|
const BTTask *task = this;
|
||||||
while (!task->is_root()) {
|
while (!task->is_root()) {
|
||||||
task = task->get_parent().ptr();
|
task = task->_parent;
|
||||||
}
|
}
|
||||||
return Ref<BTTask>(task);
|
return Ref<BTTask>(task);
|
||||||
}
|
}
|
||||||
|
@ -86,11 +86,11 @@ void BTTask::initialize(Object *p_agent, Dictionary p_blackboard) {
|
||||||
|
|
||||||
Ref<BTTask> BTTask::clone() const {
|
Ref<BTTask> BTTask::clone() const {
|
||||||
Ref<BTTask> inst = duplicate(true);
|
Ref<BTTask> inst = duplicate(true);
|
||||||
inst.ptr()->_parent.unref();
|
inst->_parent = nullptr;
|
||||||
CRASH_COND(inst.ptr()->get_parent().is_valid());
|
CRASH_COND(inst->get_parent().is_valid());
|
||||||
for (int i = 0; i < _children.size(); i++) {
|
for (int i = 0; i < _children.size(); i++) {
|
||||||
Ref<BTTask> c = get_child(i)->clone();
|
Ref<BTTask> c = get_child(i)->clone();
|
||||||
c->_parent = inst;
|
c->_parent = inst.ptr();
|
||||||
inst->_children.set(i, c);
|
inst->_children.set(i, c);
|
||||||
}
|
}
|
||||||
return inst;
|
return inst;
|
||||||
|
@ -152,19 +152,19 @@ int BTTask::get_child_count() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTTask::add_child(Ref<BTTask> p_child) {
|
void BTTask::add_child(Ref<BTTask> p_child) {
|
||||||
ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!");
|
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
||||||
p_child->_parent = Ref<BTTask>(this);
|
p_child->_parent = this;
|
||||||
_children.push_back(p_child);
|
_children.push_back(p_child);
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTTask::add_child_at_index(Ref<BTTask> p_child, int p_idx) {
|
void BTTask::add_child_at_index(Ref<BTTask> p_child, int p_idx) {
|
||||||
ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!");
|
ERR_FAIL_COND_MSG(p_child->get_parent().is_valid(), "p_child already has a parent!");
|
||||||
if (p_idx < 0 || p_idx > _children.size()) {
|
if (p_idx < 0 || p_idx > _children.size()) {
|
||||||
p_idx = _children.size();
|
p_idx = _children.size();
|
||||||
}
|
}
|
||||||
_children.insert(p_idx, p_child);
|
_children.insert(p_idx, p_child);
|
||||||
p_child->_parent = Ref<BTTask>(this);
|
p_child->_parent = this;
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ void BTTask::remove_child(Ref<BTTask> p_child) {
|
||||||
ERR_FAIL_MSG("p_child not found!");
|
ERR_FAIL_MSG("p_child not found!");
|
||||||
} else {
|
} else {
|
||||||
_children.remove(idx);
|
_children.remove(idx);
|
||||||
p_child->_parent.unref();
|
p_child->_parent = nullptr;
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ int BTTask::get_child_index(const Ref<BTTask> &p_child) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BTTask> BTTask::next_sibling() const {
|
Ref<BTTask> BTTask::next_sibling() const {
|
||||||
if (_parent.is_valid()) {
|
if (_parent != nullptr) {
|
||||||
int idx = _parent->get_child_index(Ref<BTTask>(this));
|
int idx = _parent->get_child_index(Ref<BTTask>(this));
|
||||||
if (idx != -1 && _parent->get_child_count() > (idx + 1)) {
|
if (idx != -1 && _parent->get_child_count() > (idx + 1)) {
|
||||||
return _parent->get_child(idx + 1);
|
return _parent->get_child(idx + 1);
|
||||||
|
@ -276,7 +276,16 @@ void BTTask::_bind_methods() {
|
||||||
BTTask::BTTask() {
|
BTTask::BTTask() {
|
||||||
_custom_name = String();
|
_custom_name = String();
|
||||||
_agent = nullptr;
|
_agent = nullptr;
|
||||||
|
_parent = nullptr;
|
||||||
_blackboard = Dictionary();
|
_blackboard = Dictionary();
|
||||||
_children = Vector<Ref<BTTask>>();
|
_children = Vector<Ref<BTTask>>();
|
||||||
_status = FRESH;
|
_status = FRESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BTTask::~BTTask() {
|
||||||
|
for (int i = 0; i < get_child_count(); i++) {
|
||||||
|
ERR_FAIL_COND(!get_child(i).is_valid());
|
||||||
|
get_child(i)->_parent = nullptr;
|
||||||
|
get_child(i).unref();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
#include "core/ustring.h"
|
#include "core/ustring.h"
|
||||||
#include "core/vector.h"
|
#include "core/vector.h"
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
class BTTask : public Resource {
|
class BTTask : public Resource {
|
||||||
GDCLASS(BTTask, Resource);
|
GDCLASS(BTTask, Resource);
|
||||||
|
@ -21,18 +22,14 @@ public:
|
||||||
FAILURE,
|
FAILURE,
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
};
|
};
|
||||||
enum TaskType {
|
|
||||||
ACTION,
|
|
||||||
CONDITION,
|
|
||||||
COMPOSITE,
|
|
||||||
DECORATOR,
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class BehaviorTree;
|
||||||
|
|
||||||
String _custom_name;
|
String _custom_name;
|
||||||
Object *_agent;
|
Object *_agent;
|
||||||
Dictionary _blackboard;
|
Dictionary _blackboard;
|
||||||
Ref<BTTask> _parent;
|
BTTask *_parent;
|
||||||
Vector<Ref<BTTask>> _children;
|
Vector<Ref<BTTask>> _children;
|
||||||
int _status;
|
int _status;
|
||||||
|
|
||||||
|
@ -51,8 +48,8 @@ protected:
|
||||||
public:
|
public:
|
||||||
Object *get_agent() const { return _agent; };
|
Object *get_agent() const { return _agent; };
|
||||||
Dictionary get_blackboard() const { return _blackboard; };
|
Dictionary get_blackboard() const { return _blackboard; };
|
||||||
Ref<BTTask> get_parent() const { return _parent; };
|
Ref<BTTask> get_parent() const { return Ref<BTTask>(_parent); };
|
||||||
bool is_root() const { return _parent.is_null(); };
|
bool is_root() const { return _parent == nullptr; };
|
||||||
Ref<BTTask> get_root() const;
|
Ref<BTTask> get_root() const;
|
||||||
int get_status() const { return _status; };
|
int get_status() const { return _status; };
|
||||||
String get_custom_name() const { return _custom_name; };
|
String get_custom_name() const { return _custom_name; };
|
||||||
|
@ -76,6 +73,7 @@ public:
|
||||||
void print_tree(int p_initial_tabs = 0) const;
|
void print_tree(int p_initial_tabs = 0) const;
|
||||||
|
|
||||||
BTTask();
|
BTTask();
|
||||||
|
~BTTask();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BTTASK_H
|
#endif // BTTASK_H
|
|
@ -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="#cea4f1"><path d="m0 12h4v4h-4z"/><path d="m6 12h4v4h-4z"/><path d="m5 0h6v4h-6z"/><path d="m7.5 2.5h1v10h-1z"/><path d="m12 12h4v4h-4z"/><path d="m14.5 14h-1v-5.5h-11v3.86h-1v-4.86h13z"/></g></svg>
|
After Width: | Height: | Size: 301 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg enable-background="new 0 0 16 16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m16 10.03v-4h-6v1.5h-6.5v-3.53h2.5v-4h-6v4h2.5v10.5h.17.83 6.5v1.5h6v-4h-6v1.5h-6.5v-4.97h6.5v1.5z" fill="#cea4f1"/></svg>
|
After Width: | Height: | Size: 225 B |
|
@ -1,6 +1,7 @@
|
||||||
/* limbo_string_names.cpp */
|
/* limbo_string_names.cpp */
|
||||||
|
|
||||||
#include "limbo_string_names.h"
|
#include "limbo_string_names.h"
|
||||||
|
#include "core/string_name.h"
|
||||||
|
|
||||||
LimboStringNames *LimboStringNames::singleton = nullptr;
|
LimboStringNames *LimboStringNames::singleton = nullptr;
|
||||||
|
|
||||||
|
@ -10,4 +11,5 @@ LimboStringNames::LimboStringNames() {
|
||||||
_enter = StaticCString::create("_enter");
|
_enter = StaticCString::create("_enter");
|
||||||
_exit = StaticCString::create("_exit");
|
_exit = StaticCString::create("_exit");
|
||||||
_tick = StaticCString::create("_tick");
|
_tick = StaticCString::create("_tick");
|
||||||
|
behavior_tree_finished = StaticCString::create("behavior_tree_finished");
|
||||||
}
|
}
|
|
@ -28,6 +28,7 @@ public:
|
||||||
StringName _enter;
|
StringName _enter;
|
||||||
StringName _exit;
|
StringName _exit;
|
||||||
StringName _tick;
|
StringName _tick;
|
||||||
|
StringName behavior_tree_finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIMBO_STRING_NAMES_H
|
#endif // LIMBO_STRING_NAMES_H
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
|
|
||||||
|
#include "bt/behavior_tree.h"
|
||||||
#include "bt/bt_action.h"
|
#include "bt/bt_action.h"
|
||||||
#include "bt/bt_always_fail.h"
|
#include "bt/bt_always_fail.h"
|
||||||
#include "bt/bt_always_succeed.h"
|
#include "bt/bt_always_succeed.h"
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
#include "bt/bt_fail.h"
|
#include "bt/bt_fail.h"
|
||||||
#include "bt/bt_invert.h"
|
#include "bt/bt_invert.h"
|
||||||
#include "bt/bt_parallel.h"
|
#include "bt/bt_parallel.h"
|
||||||
|
#include "bt/bt_player.h"
|
||||||
#include "bt/bt_probability.h"
|
#include "bt/bt_probability.h"
|
||||||
#include "bt/bt_random_selector.h"
|
#include "bt/bt_random_selector.h"
|
||||||
#include "bt/bt_random_sequence.h"
|
#include "bt/bt_random_sequence.h"
|
||||||
|
@ -36,6 +38,8 @@
|
||||||
|
|
||||||
void register_limboai_types() {
|
void register_limboai_types() {
|
||||||
ClassDB::register_class<BTTask>();
|
ClassDB::register_class<BTTask>();
|
||||||
|
ClassDB::register_class<BehaviorTree>();
|
||||||
|
ClassDB::register_class<BTPlayer>();
|
||||||
|
|
||||||
ClassDB::register_class<BTComposite>();
|
ClassDB::register_class<BTComposite>();
|
||||||
ClassDB::register_class<BTDecorator>();
|
ClassDB::register_class<BTDecorator>();
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
extends KinematicBody2D
|
||||||
|
|
||||||
|
|
||||||
|
onready var bt_player: BTPlayer = $BTPlayer
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_configure_ai()
|
||||||
|
|
||||||
|
|
||||||
|
func _configure_ai() -> void:
|
||||||
|
var tree := BehaviorTree.new()
|
||||||
|
var seq := BTSequence.new()
|
||||||
|
var print_task := BTPrintLine.new("Hello world!")
|
||||||
|
seq.add_child(print_task)
|
||||||
|
tree.root_task = seq
|
||||||
|
bt_player.behavior_tree = tree
|
||||||
|
print("Assigning tree second time")
|
||||||
|
bt_player.behavior_tree = tree
|
|
@ -0,0 +1,9 @@
|
||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://Agent.gd" type="Script" id=2]
|
||||||
|
|
||||||
|
[node name="Agent" type="KinematicBody2D"]
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
|
||||||
|
[node name="BTPlayer" type="BTPlayer" parent="."]
|
||||||
|
active = true
|
|
@ -0,0 +1,7 @@
|
||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://Agent.tscn" type="PackedScene" id=1]
|
||||||
|
|
||||||
|
[node name="Test" type="Node2D"]
|
||||||
|
|
||||||
|
[node name="Agent" parent="." instance=ExtResource( 1 )]
|
|
@ -0,0 +1,14 @@
|
||||||
|
class_name BTPrintLine
|
||||||
|
extends BTTask
|
||||||
|
|
||||||
|
|
||||||
|
export var line: String
|
||||||
|
|
||||||
|
|
||||||
|
func _init(p_line: String = "") -> void:
|
||||||
|
line = p_line
|
||||||
|
|
||||||
|
|
||||||
|
func _tick(_delta: float) -> int:
|
||||||
|
print(line)
|
||||||
|
return SUCCESS
|
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_resource type="BehaviorTree" load_steps=2 format=2]
|
||||||
|
|
||||||
|
[sub_resource type="BTSequence" id=1]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
root_task = SubResource( 1 )
|
|
@ -0,0 +1,7 @@
|
||||||
|
[gd_resource type="Environment" load_steps=2 format=2]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSky" id=1]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
background_mode = 2
|
||||||
|
background_sky = SubResource( 1 )
|
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,35 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon.png"
|
||||||
|
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
process/invert_color=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=1.0
|
|
@ -0,0 +1,37 @@
|
||||||
|
; Engine configuration file.
|
||||||
|
; It's best edited using the editor UI and not directly,
|
||||||
|
; since the parameters that go here are not all obvious.
|
||||||
|
;
|
||||||
|
; Format:
|
||||||
|
; [section] ; section goes between []
|
||||||
|
; param=value ; assign values to parameters
|
||||||
|
|
||||||
|
config_version=4
|
||||||
|
|
||||||
|
_global_script_classes=[ {
|
||||||
|
"base": "BTTask",
|
||||||
|
"class": "BTPrintLine",
|
||||||
|
"language": "GDScript",
|
||||||
|
"path": "res://ai/tasks/BTPrintLine.gd"
|
||||||
|
} ]
|
||||||
|
_global_script_class_icons={
|
||||||
|
"BTPrintLine": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
[application]
|
||||||
|
|
||||||
|
config/name="LimboAI Test"
|
||||||
|
run/main_scene="res://Test.tscn"
|
||||||
|
config/icon="res://icon.png"
|
||||||
|
|
||||||
|
[gui]
|
||||||
|
|
||||||
|
common/drop_mouse_on_gui_input_disabled=true
|
||||||
|
|
||||||
|
[physics]
|
||||||
|
|
||||||
|
common/enable_pause_aware_picking=true
|
||||||
|
|
||||||
|
[rendering]
|
||||||
|
|
||||||
|
environment/default_environment="res://default_env.tres"
|
Loading…
Reference in New Issue