Add instancing to behavior tree
This commit is contained in:
parent
6cac198092
commit
7be7ca276d
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "behavior_tree.h"
|
#include "behavior_tree.h"
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
|
#include "core/error_macros.h"
|
||||||
#include "core/list.h"
|
#include "core/list.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
#include "core/variant.h"
|
#include "core/variant.h"
|
||||||
|
@ -32,6 +33,13 @@ Ref<BehaviorTree> BehaviorTree::clone() const {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<BTTask> BehaviorTree::instance(Object *p_agent, const Ref<Blackboard> &p_blackboard) const {
|
||||||
|
ERR_FAIL_COND_V_MSG(root_task == nullptr, memnew(BTTask), "Trying to instance a behavior tree with no valid root task.");
|
||||||
|
Ref<BTTask> inst = root_task->clone();
|
||||||
|
inst->initialize(p_agent, p_blackboard);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
void BehaviorTree::_bind_methods() {
|
void BehaviorTree::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_description", "p_value"), &BehaviorTree::set_description);
|
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("get_description"), &BehaviorTree::get_description);
|
||||||
|
@ -39,6 +47,7 @@ void BehaviorTree::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_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("init"), &BehaviorTree::init);
|
||||||
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
||||||
|
ClassDB::bind_method(D_METHOD("instance", "p_agent", "p_blackboard"), &BehaviorTree::instance);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
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");
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_task", PROPERTY_HINT_RESOURCE_TYPE, "BTTask"), "set_root_task", "get_root_task");
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
#ifndef BEHAVIOR_TREE_H
|
#ifndef BEHAVIOR_TREE_H
|
||||||
#define BEHAVIOR_TREE_H
|
#define BEHAVIOR_TREE_H
|
||||||
|
|
||||||
|
#include "bt_task.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
#include "core/resource.h"
|
#include "core/resource.h"
|
||||||
|
#include "modules/limboai/blackboard.h"
|
||||||
#include "bt_task.h"
|
|
||||||
|
|
||||||
class BehaviorTree : public Resource {
|
class BehaviorTree : public Resource {
|
||||||
GDCLASS(BehaviorTree, Resource);
|
GDCLASS(BehaviorTree, Resource);
|
||||||
|
@ -33,6 +33,7 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
Ref<BehaviorTree> clone() const;
|
Ref<BehaviorTree> clone() const;
|
||||||
|
Ref<BTTask> instance(Object *p_agent, const Ref<Blackboard> &p_blackboard) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BEHAVIOR_TREE_H
|
#endif // BEHAVIOR_TREE_H
|
|
@ -21,8 +21,7 @@ void BTPlayer::_load_tree() {
|
||||||
ERR_FAIL_COND_MSG(!behavior_tree.is_valid(), "BTPlayer needs a valid behavior tree.");
|
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.");
|
ERR_FAIL_COND_MSG(!behavior_tree->get_root_task().is_valid(), "Behavior tree has no valid root task.");
|
||||||
_loaded_tree = behavior_tree;
|
_loaded_tree = behavior_tree;
|
||||||
_root_task = _loaded_tree->get_root_task()->clone();
|
_root_task = _loaded_tree->instance(get_owner(), blackboard);
|
||||||
_root_task->initialize(get_owner(), blackboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||||
|
|
|
@ -93,7 +93,8 @@ void BTTask::initialize(Object *p_agent, const Ref<Blackboard> &p_blackboard) {
|
||||||
Ref<BTTask> BTTask::clone() const {
|
Ref<BTTask> BTTask::clone() const {
|
||||||
Ref<BTTask> inst = duplicate(false);
|
Ref<BTTask> inst = duplicate(false);
|
||||||
inst->parent = nullptr;
|
inst->parent = nullptr;
|
||||||
CRASH_COND(inst->get_parent().is_valid());
|
inst->agent = nullptr;
|
||||||
|
inst->blackboard.unref();
|
||||||
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.ptr();
|
c->parent = inst.ptr();
|
||||||
|
@ -186,6 +187,11 @@ void BTTask::remove_child(Ref<BTTask> p_child) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BTTask::remove_child_at_index(int p_idx) {
|
||||||
|
ERR_FAIL_INDEX(p_idx, get_child_count());
|
||||||
|
children.remove(p_idx);
|
||||||
|
}
|
||||||
|
|
||||||
bool BTTask::has_child(const Ref<BTTask> &p_child) const {
|
bool BTTask::has_child(const Ref<BTTask> &p_child) const {
|
||||||
return children.find(p_child) != -1;
|
return children.find(p_child) != -1;
|
||||||
}
|
}
|
||||||
|
@ -277,6 +283,7 @@ void BTTask::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("add_child", "p_child"), &BTTask::add_child);
|
ClassDB::bind_method(D_METHOD("add_child", "p_child"), &BTTask::add_child);
|
||||||
ClassDB::bind_method(D_METHOD("add_child_at_index", "p_child", "p_idx"), &BTTask::add_child_at_index);
|
ClassDB::bind_method(D_METHOD("add_child_at_index", "p_child", "p_idx"), &BTTask::add_child_at_index);
|
||||||
ClassDB::bind_method(D_METHOD("remove_child", "p_child"), &BTTask::remove_child);
|
ClassDB::bind_method(D_METHOD("remove_child", "p_child"), &BTTask::remove_child);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_child_at_index", "p_idx"), &BTTask::remove_child_at_index);
|
||||||
ClassDB::bind_method(D_METHOD("has_child", "p_child"), &BTTask::has_child);
|
ClassDB::bind_method(D_METHOD("has_child", "p_child"), &BTTask::has_child);
|
||||||
ClassDB::bind_method(D_METHOD("is_descendant_of", "p_task"), &BTTask::is_descendant_of);
|
ClassDB::bind_method(D_METHOD("is_descendant_of", "p_task"), &BTTask::is_descendant_of);
|
||||||
ClassDB::bind_method(D_METHOD("get_child_index", "p_child"), &BTTask::get_child_index);
|
ClassDB::bind_method(D_METHOD("get_child_index", "p_child"), &BTTask::get_child_index);
|
||||||
|
|
|
@ -57,8 +57,8 @@ public:
|
||||||
void set_custom_name(const String &p_name);
|
void set_custom_name(const String &p_name);
|
||||||
String get_task_name() const;
|
String get_task_name() const;
|
||||||
|
|
||||||
virtual void initialize(Object *p_agent, const Ref<Blackboard> &p_blackboard);
|
|
||||||
virtual Ref<BTTask> clone() const;
|
virtual Ref<BTTask> clone() const;
|
||||||
|
virtual void initialize(Object *p_agent, const Ref<Blackboard> &p_blackboard);
|
||||||
int execute(float p_delta);
|
int execute(float p_delta);
|
||||||
void cancel();
|
void cancel();
|
||||||
Ref<BTTask> get_child(int p_idx) const;
|
Ref<BTTask> get_child(int p_idx) const;
|
||||||
|
@ -66,6 +66,7 @@ public:
|
||||||
void add_child(Ref<BTTask> p_child);
|
void add_child(Ref<BTTask> p_child);
|
||||||
void add_child_at_index(Ref<BTTask> p_child, int p_idx);
|
void add_child_at_index(Ref<BTTask> p_child, int p_idx);
|
||||||
void remove_child(Ref<BTTask> p_child);
|
void remove_child(Ref<BTTask> p_child);
|
||||||
|
void remove_child_at_index(int p_idx);
|
||||||
bool has_child(const Ref<BTTask> &p_child) const;
|
bool has_child(const Ref<BTTask> &p_child) const;
|
||||||
bool is_descendant_of(const Ref<BTTask> &p_task) const;
|
bool is_descendant_of(const Ref<BTTask> &p_task) const;
|
||||||
int get_child_index(const Ref<BTTask> &p_child) const;
|
int get_child_index(const Ref<BTTask> &p_child) const;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "modules/limboai/bt/actions/bt_fail.h"
|
#include "modules/limboai/bt/actions/bt_fail.h"
|
||||||
#include "modules/limboai/bt/bt_task.h"
|
#include "modules/limboai/bt/bt_task.h"
|
||||||
#include "modules/limboai/bt/decorators/bt_decorator.h"
|
#include "modules/limboai/bt/decorators/bt_decorator.h"
|
||||||
|
#include "modules/limboai/bt/decorators/bt_new_scope.h"
|
||||||
|
|
||||||
String BTSubtree::_generate_name() const {
|
String BTSubtree::_generate_name() const {
|
||||||
String s;
|
String s;
|
||||||
|
@ -24,16 +25,18 @@ String BTSubtree::_generate_name() const {
|
||||||
return vformat("Subtree %s", s);
|
return vformat("Subtree %s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BTTask> BTSubtree::clone() const {
|
void BTSubtree::initialize(Object *p_agent, const Ref<Blackboard> &p_blackboard) {
|
||||||
Ref<BTTask> copy = BTDecorator::clone();
|
ERR_FAIL_COND_MSG(!subtree.is_valid(), "Subtree is not assigned.");
|
||||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
ERR_FAIL_COND_MSG(!subtree->get_root_task().is_valid(), "Subtree root task is not valid.");
|
||||||
ERR_FAIL_COND_V_MSG(!subtree.is_valid(), copy, "Subtree is not assigned.");
|
ERR_FAIL_COND_MSG(get_child_count() != 0, "Subtree task shouldn't have children during initialization.");
|
||||||
ERR_FAIL_COND_V_MSG(!subtree->get_root_task().is_valid(), copy, "Subtree root task is not valid.");
|
|
||||||
ERR_FAIL_COND_V_MSG(get_child_count() != 0, copy, "Subtree prototype shouldn't have children.");
|
|
||||||
|
|
||||||
copy->add_child(subtree->get_root_task()->clone());
|
// while (get_child_count() > 0) {
|
||||||
}
|
// remove_child_at_index(get_child_count() - 1);
|
||||||
return copy;
|
// }
|
||||||
|
|
||||||
|
add_child(subtree->get_root_task()->clone());
|
||||||
|
|
||||||
|
BTNewScope::initialize(p_agent, p_blackboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BTSubtree::_tick(float p_delta) {
|
int BTSubtree::_tick(float p_delta) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
}
|
}
|
||||||
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
Ref<BehaviorTree> get_subtree() const { return subtree; }
|
||||||
|
|
||||||
virtual Ref<BTTask> clone() const;
|
virtual void initialize(Object *p_agent, const Ref<Blackboard> &p_blackboard);
|
||||||
virtual String get_configuration_warning() const;
|
virtual String get_configuration_warning() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue