BlackboardPlan: Use mapping with BTSubtree

This commit is contained in:
Serhii Snitsaruk 2024-05-14 11:39:32 +02:00
parent 2d493a76bd
commit 0d1e846d93
No known key found for this signature in database
GPG Key ID: A965EF8799FFEC2D
7 changed files with 59 additions and 8 deletions

View File

@ -134,7 +134,7 @@ void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const {
} }
// * Mapping // * Mapping
if (is_mapping_allowed()) { if (is_mapping_enabled()) {
p_list->push_back(PropertyInfo(Variant::NIL, "Mapping", PROPERTY_HINT_NONE, "mapping/", PROPERTY_USAGE_GROUP)); p_list->push_back(PropertyInfo(Variant::NIL, "Mapping", PROPERTY_HINT_NONE, "mapping/", PROPERTY_USAGE_GROUP));
for (const Pair<StringName, BBVariable> &p : var_list) { for (const Pair<StringName, BBVariable> &p : var_list) {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "mapping/" + p.first, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT)); p_list->push_back(PropertyInfo(Variant::STRING_NAME, "mapping/" + p.first, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
@ -165,13 +165,13 @@ void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
notify_property_list_changed(); notify_property_list_changed();
} }
void BlackboardPlan::set_mapping_allowed(bool p_mapping_allowed) { void BlackboardPlan::set_parent_scope_plan(const Ref<BlackboardPlan> &p_plan) {
mapping_allowed = p_mapping_allowed; parent_scope_plan = p_plan;
emit_changed(); notify_property_list_changed();
} }
bool BlackboardPlan::has_mapping(const StringName &p_name) const { bool BlackboardPlan::has_mapping(const StringName &p_name) const {
return is_mapping_allowed() && parent_scope_mapping.has(p_name) && parent_scope_mapping[p_name] != StringName(); return is_mapping_enabled() && parent_scope_mapping.has(p_name) && parent_scope_mapping[p_name] != StringName();
} }
void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) { void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) {
@ -409,6 +409,9 @@ void BlackboardPlan::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_base_plan", "blackboard_plan"), &BlackboardPlan::set_base_plan); ClassDB::bind_method(D_METHOD("set_base_plan", "blackboard_plan"), &BlackboardPlan::set_base_plan);
ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan); ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan);
ClassDB::bind_method(D_METHOD("set_parent_scope_plan", "blackboard_plan"), &BlackboardPlan::set_parent_scope_plan);
ClassDB::bind_method(D_METHOD("get_parent_scope_plan"), &BlackboardPlan::get_parent_scope_plan);
ClassDB::bind_method(D_METHOD("is_mapping_enabled"), &BlackboardPlan::is_mapping_enabled);
ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived); ClassDB::bind_method(D_METHOD("is_derived"), &BlackboardPlan::is_derived);
ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan); ClassDB::bind_method(D_METHOD("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan);
ClassDB::bind_method(D_METHOD("create_blackboard", "node"), &BlackboardPlan::create_blackboard); ClassDB::bind_method(D_METHOD("create_blackboard", "node"), &BlackboardPlan::create_blackboard);

View File

@ -39,7 +39,9 @@ private:
// Mapping between variables in this plan and their parent scope names. // Mapping between variables in this plan and their parent scope names.
// Used for linking variables to their parent scope counterparts upon Blackboard creation/population. // Used for linking variables to their parent scope counterparts upon Blackboard creation/population.
HashMap<StringName, StringName> parent_scope_mapping; HashMap<StringName, StringName> parent_scope_mapping;
bool mapping_allowed = true; // BlackboardPlan that will be used in parent scope Blackboard creation at runtime.
// Used to provide hints in the inspector. When set, mapping is enabled in the inspector.
Ref<BlackboardPlan> parent_scope_plan;
// If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population). // If true, NodePath variables will be prefetched, so that the vars will contain node pointers instead (upon BB creation/population).
bool prefetch_nodepath_vars = true; bool prefetch_nodepath_vars = true;
@ -57,8 +59,9 @@ public:
void set_base_plan(const Ref<BlackboardPlan> &p_base); void set_base_plan(const Ref<BlackboardPlan> &p_base);
Ref<BlackboardPlan> get_base_plan() const { return base; } Ref<BlackboardPlan> get_base_plan() const { return base; }
void set_mapping_allowed(bool p_mapping_allowed); void set_parent_scope_plan(const Ref<BlackboardPlan> &p_plan);
bool is_mapping_allowed() const { return mapping_allowed; } Ref<BlackboardPlan> get_parent_scope_plan() const { return parent_scope_plan; }
bool is_mapping_enabled() const { return parent_scope_plan.is_valid(); }
bool has_mapping(const StringName &p_name) const; bool has_mapping(const StringName &p_name) const;
void set_prefetch_nodepath_vars(bool p_enable); void set_prefetch_nodepath_vars(bool p_enable);

View File

@ -48,11 +48,14 @@ void BehaviorTree::set_blackboard_plan(const Ref<BlackboardPlan> &p_plan) {
blackboard_plan->connect(LW_NAME(changed), callable_mp(this, &BehaviorTree::_plan_changed)); blackboard_plan->connect(LW_NAME(changed), callable_mp(this, &BehaviorTree::_plan_changed));
} }
_set_editor_behavior_tree_hint();
_plan_changed(); _plan_changed();
} }
void BehaviorTree::set_root_task(const Ref<BTTask> &p_value) { void BehaviorTree::set_root_task(const Ref<BTTask> &p_value) {
_unset_editor_behavior_tree_hint();
root_task = p_value; root_task = p_value;
_set_editor_behavior_tree_hint();
emit_changed(); emit_changed();
} }
@ -85,6 +88,18 @@ void BehaviorTree::_plan_changed() {
emit_changed(); emit_changed();
} }
void BehaviorTree::_set_editor_behavior_tree_hint() {
if (root_task.is_valid()) {
root_task->data.behavior_tree = Ref<BehaviorTree>(this);
}
}
void BehaviorTree::_unset_editor_behavior_tree_hint() {
if (root_task.is_valid()) {
root_task->data.behavior_tree.unref();
}
}
void BehaviorTree::_bind_methods() { void BehaviorTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_description", "description"), &BehaviorTree::set_description); ClassDB::bind_method(D_METHOD("set_description", "description"), &BehaviorTree::set_description);
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description); ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);

View File

@ -33,6 +33,8 @@ private:
Ref<BTTask> root_task; Ref<BTTask> root_task;
void _plan_changed(); void _plan_changed();
void _set_editor_behavior_tree_hint();
void _unset_editor_behavior_tree_hint();
protected: protected:
static void _bind_methods(); static void _bind_methods();

View File

@ -14,6 +14,7 @@
#include "../../blackboard/blackboard.h" #include "../../blackboard/blackboard.h"
#include "../../util/limbo_string_names.h" #include "../../util/limbo_string_names.h"
#include "../../util/limbo_utility.h" #include "../../util/limbo_utility.h"
#include "../behavior_tree.h"
#include "bt_comment.h" #include "bt_comment.h"
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
@ -376,6 +377,18 @@ void BTTask::print_tree(int p_initial_tabs) {
} }
} }
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;
}
void BTTask::_bind_methods() { void BTTask::_bind_methods() {
// Public Methods. // Public Methods.
ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root); ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root);
@ -397,6 +410,7 @@ void BTTask::_bind_methods() {
ClassDB::bind_method(D_METHOD("print_tree", "initial_tabs"), &BTTask::print_tree, Variant(0)); ClassDB::bind_method(D_METHOD("print_tree", "initial_tabs"), &BTTask::print_tree, Variant(0));
ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name); ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name);
ClassDB::bind_method(D_METHOD("abort"), &BTTask::abort); ClassDB::bind_method(D_METHOD("abort"), &BTTask::abort);
ClassDB::bind_method(D_METHOD("editor_get_behavior_tree"), &BTTask::editor_get_behavior_tree);
// Properties, setters and getters. // Properties, setters and getters.
ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent); ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent);

View File

@ -42,6 +42,8 @@
using namespace godot; using namespace godot;
#endif // LIMBOAI_GDEXTENSION #endif // LIMBOAI_GDEXTENSION
class BehaviorTree;
/** /**
* Base class for BTTask. * Base class for BTTask.
* Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...) * Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...)
@ -82,6 +84,9 @@ private:
Status status = FRESH; Status status = FRESH;
double elapsed = 0.0; double elapsed = 0.0;
bool display_collapsed = false; bool display_collapsed = false;
#ifdef TOOLS_ENABLED
Ref<BehaviorTree> behavior_tree;
#endif
} data; } data;
Array _get_children() const; Array _get_children() const;
@ -162,6 +167,11 @@ public:
void print_tree(int p_initial_tabs = 0); void print_tree(int p_initial_tabs = 0);
#ifdef TOOLS_ENABLED
Ref<BehaviorTree> editor_get_behavior_tree();
void editor_set_behavior_tree(const Ref<BehaviorTree> &p_bt);
#endif
BTTask(); BTTask();
~BTTask(); ~BTTask();
}; };

View File

@ -30,6 +30,10 @@ void BTSubtree::_update_blackboard_plan() {
set_blackboard_plan(Ref<BlackboardPlan>(memnew(BlackboardPlan))); set_blackboard_plan(Ref<BlackboardPlan>(memnew(BlackboardPlan)));
} }
get_blackboard_plan()->set_base_plan(subtree.is_valid() ? subtree->get_blackboard_plan() : nullptr); get_blackboard_plan()->set_base_plan(subtree.is_valid() ? subtree->get_blackboard_plan() : nullptr);
#ifdef TOOLS_ENABLED
get_blackboard_plan()->set_parent_scope_plan(get_root()->editor_get_behavior_tree()->get_blackboard_plan());
#endif // TOOLS_ENABLED
} }
String BTSubtree::_generate_name() { String BTSubtree::_generate_name() {