diff --git a/blackboard/blackboard_plan.cpp b/blackboard/blackboard_plan.cpp index 2ce7dc5..0ea59f7 100644 --- a/blackboard/blackboard_plan.cpp +++ b/blackboard/blackboard_plan.cpp @@ -134,7 +134,7 @@ void BlackboardPlan::_get_property_list(List *p_list) const { } // * Mapping - if (is_mapping_allowed()) { + if (is_mapping_enabled()) { p_list->push_back(PropertyInfo(Variant::NIL, "Mapping", PROPERTY_HINT_NONE, "mapping/", PROPERTY_USAGE_GROUP)); for (const Pair &p : var_list) { 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 &p_base) { notify_property_list_changed(); } -void BlackboardPlan::set_mapping_allowed(bool p_mapping_allowed) { - mapping_allowed = p_mapping_allowed; - emit_changed(); +void BlackboardPlan::set_parent_scope_plan(const Ref &p_plan) { + parent_scope_plan = p_plan; + notify_property_list_changed(); } 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) { @@ -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("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("sync_with_base_plan"), &BlackboardPlan::sync_with_base_plan); ClassDB::bind_method(D_METHOD("create_blackboard", "node"), &BlackboardPlan::create_blackboard); diff --git a/blackboard/blackboard_plan.h b/blackboard/blackboard_plan.h index 6a7d665..d24edab 100644 --- a/blackboard/blackboard_plan.h +++ b/blackboard/blackboard_plan.h @@ -39,7 +39,9 @@ private: // Mapping between variables in this plan and their parent scope names. // Used for linking variables to their parent scope counterparts upon Blackboard creation/population. HashMap 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 parent_scope_plan; // 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; @@ -57,8 +59,9 @@ public: void set_base_plan(const Ref &p_base); Ref get_base_plan() const { return base; } - void set_mapping_allowed(bool p_mapping_allowed); - bool is_mapping_allowed() const { return mapping_allowed; } + void set_parent_scope_plan(const Ref &p_plan); + Ref 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; void set_prefetch_nodepath_vars(bool p_enable); diff --git a/bt/behavior_tree.cpp b/bt/behavior_tree.cpp index 817b8a6..45d403f 100644 --- a/bt/behavior_tree.cpp +++ b/bt/behavior_tree.cpp @@ -48,11 +48,14 @@ void BehaviorTree::set_blackboard_plan(const Ref &p_plan) { blackboard_plan->connect(LW_NAME(changed), callable_mp(this, &BehaviorTree::_plan_changed)); } + _set_editor_behavior_tree_hint(); _plan_changed(); } void BehaviorTree::set_root_task(const Ref &p_value) { + _unset_editor_behavior_tree_hint(); root_task = p_value; + _set_editor_behavior_tree_hint(); emit_changed(); } @@ -85,6 +88,18 @@ void BehaviorTree::_plan_changed() { emit_changed(); } +void BehaviorTree::_set_editor_behavior_tree_hint() { + if (root_task.is_valid()) { + root_task->data.behavior_tree = Ref(this); + } +} + +void BehaviorTree::_unset_editor_behavior_tree_hint() { + if (root_task.is_valid()) { + root_task->data.behavior_tree.unref(); + } +} + void BehaviorTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_description", "description"), &BehaviorTree::set_description); ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description); diff --git a/bt/behavior_tree.h b/bt/behavior_tree.h index 01ae806..4d71b9d 100644 --- a/bt/behavior_tree.h +++ b/bt/behavior_tree.h @@ -33,6 +33,8 @@ private: Ref root_task; void _plan_changed(); + void _set_editor_behavior_tree_hint(); + void _unset_editor_behavior_tree_hint(); protected: static void _bind_methods(); diff --git a/bt/tasks/bt_task.cpp b/bt/tasks/bt_task.cpp index 9a5e284..7bc317b 100644 --- a/bt/tasks/bt_task.cpp +++ b/bt/tasks/bt_task.cpp @@ -14,6 +14,7 @@ #include "../../blackboard/blackboard.h" #include "../../util/limbo_string_names.h" #include "../../util/limbo_utility.h" +#include "../behavior_tree.h" #include "bt_comment.h" #ifdef LIMBOAI_MODULE @@ -376,6 +377,18 @@ void BTTask::print_tree(int p_initial_tabs) { } } +Ref 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 &p_bt) { + data.behavior_tree = p_bt; +} + void BTTask::_bind_methods() { // Public Methods. 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("get_task_name"), &BTTask::get_task_name); 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. ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent); diff --git a/bt/tasks/bt_task.h b/bt/tasks/bt_task.h index e9017ad..446e36d 100644 --- a/bt/tasks/bt_task.h +++ b/bt/tasks/bt_task.h @@ -42,6 +42,8 @@ using namespace godot; #endif // LIMBOAI_GDEXTENSION +class BehaviorTree; + /** * Base class for BTTask. * Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...) @@ -82,6 +84,9 @@ private: Status status = FRESH; double elapsed = 0.0; bool display_collapsed = false; +#ifdef TOOLS_ENABLED + Ref behavior_tree; +#endif } data; Array _get_children() const; @@ -162,6 +167,11 @@ public: void print_tree(int p_initial_tabs = 0); +#ifdef TOOLS_ENABLED + Ref editor_get_behavior_tree(); + void editor_set_behavior_tree(const Ref &p_bt); +#endif + BTTask(); ~BTTask(); }; diff --git a/bt/tasks/decorators/bt_subtree.cpp b/bt/tasks/decorators/bt_subtree.cpp index 9124912..331d538 100644 --- a/bt/tasks/decorators/bt_subtree.cpp +++ b/bt/tasks/decorators/bt_subtree.cpp @@ -30,6 +30,10 @@ void BTSubtree::_update_blackboard_plan() { set_blackboard_plan(Ref(memnew(BlackboardPlan))); } 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() {