diff --git a/blackboard/blackboard.cpp b/blackboard/blackboard.cpp index 7e13c2d..e04e1bc 100644 --- a/blackboard/blackboard.cpp +++ b/blackboard/blackboard.cpp @@ -79,19 +79,6 @@ void Blackboard::add_var(const StringName &p_name, const BBVariable &p_var) { data.insert(p_name, p_var); } -void Blackboard::prefetch_nodepath_vars(Node *p_node) { - ERR_FAIL_COND(p_node == nullptr); - for (const KeyValue &kv : data) { - BBVariable var = kv.value; - if (var.get_value().get_type() == Variant::NODE_PATH) { - Node *fetched_node = p_node->get_node_or_null(var.get_value()); - if (fetched_node != nullptr) { - var.set_value(fetched_node); - } - } - } -} - void Blackboard::_bind_methods() { ClassDB::bind_method(D_METHOD("get_var", "var_name", "default", "complain"), &Blackboard::get_var, Variant(), true); ClassDB::bind_method(D_METHOD("set_var", "var_name", "value"), &Blackboard::set_var); @@ -99,7 +86,6 @@ void Blackboard::_bind_methods() { ClassDB::bind_method(D_METHOD("set_parent", "blackboard"), &Blackboard::set_parent); ClassDB::bind_method(D_METHOD("get_parent"), &Blackboard::get_parent); ClassDB::bind_method(D_METHOD("erase_var", "var_name"), &Blackboard::erase_var); - ClassDB::bind_method(D_METHOD("prefetch_nodepath_vars", "node"), &Blackboard::prefetch_nodepath_vars); ClassDB::bind_method(D_METHOD("top"), &Blackboard::top); ClassDB::bind_method(D_METHOD("bind_var_to_property", "var_name", "object", "property"), &Blackboard::bind_var_to_property); ClassDB::bind_method(D_METHOD("unbind_var", "var_name"), &Blackboard::unbind_var); diff --git a/blackboard/blackboard.h b/blackboard/blackboard.h index 074e132..0e8d7cb 100644 --- a/blackboard/blackboard.h +++ b/blackboard/blackboard.h @@ -56,8 +56,6 @@ public: void add_var(const StringName &p_name, const BBVariable &p_var); - void prefetch_nodepath_vars(Node *p_node); - // TODO: Add serialization API. }; diff --git a/blackboard/blackboard_plan.cpp b/blackboard/blackboard_plan.cpp index 9030265..0229e3c 100644 --- a/blackboard/blackboard_plan.cpp +++ b/blackboard/blackboard_plan.cpp @@ -119,6 +119,19 @@ void BlackboardPlan::set_base_plan(const Ref &p_base) { notify_property_list_changed(); } +void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) { + prefetch_nodepath_vars = p_enable; + emit_changed(); +} + +bool BlackboardPlan::is_prefetching_nodepath_vars() const { + if (is_derived()) { + return base->is_prefetching_nodepath_vars(); + } else { + return prefetch_nodepath_vars; + } +} + void BlackboardPlan::add_var(const StringName &p_name, const BBVariable &p_var) { ERR_FAIL_COND(var_map.has(p_name)); var_map.insert(p_name, p_var); @@ -263,15 +276,33 @@ void BlackboardPlan::sync_with_base_plan() { } } -Ref BlackboardPlan::create_blackboard() { +// Add a variable duplicate to the blackboard, optionally with NodePath prefetch. +inline void bb_add_var_dup_with_prefetch(const Ref &p_blackboard, const StringName &p_name, const BBVariable &p_var, bool p_prefetch, Node *p_node) { + if (unlikely(p_prefetch && p_var.get_type() == Variant::NODE_PATH)) { + Node *n = p_node->get_node_or_null(p_var.get_value()); + BBVariable var = p_var.duplicate(); + if (n != nullptr) { + var.set_value(n); + } else { + ERR_PRINT(vformat("BlackboardPlan: Prefetch failed for variable $%s with value: %s", p_name, p_var.get_value())); + } + p_blackboard->add_var(p_name, var); + } else { + p_blackboard->add_var(p_name, p_var.duplicate()); + } +} + +Ref BlackboardPlan::create_blackboard(Node *p_node) { + ERR_FAIL_COND_V(p_node == nullptr && prefetch_nodepath_vars, memnew(Blackboard)); Ref bb = memnew(Blackboard); for (const Pair &p : var_list) { - bb->add_var(p.first, p.second.duplicate()); + bb_add_var_dup_with_prefetch(bb, p.first, p.second, prefetch_nodepath_vars, p_node); } return bb; } -void BlackboardPlan::populate_blackboard(const Ref &p_blackboard, bool overwrite) { +void BlackboardPlan::populate_blackboard(const Ref &p_blackboard, bool overwrite, Node *p_node) { + ERR_FAIL_COND(p_node == nullptr && prefetch_nodepath_vars); for (const Pair &p : var_list) { if (p_blackboard->has_var(p.first)) { if (overwrite) { @@ -280,13 +311,18 @@ void BlackboardPlan::populate_blackboard(const Ref &p_blackboard, bo continue; } } - p_blackboard->add_var(p.first, p.second.duplicate()); + bb_add_var_dup_with_prefetch(p_blackboard, p.first, p.second, prefetch_nodepath_vars, p_node); } } void BlackboardPlan::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_blackboard"), &BlackboardPlan::create_blackboard); - ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite"), &BlackboardPlan::populate_blackboard); + ClassDB::bind_method(D_METHOD("set_prefetch_nodepath_vars", "enable"), &BlackboardPlan::set_prefetch_nodepath_vars); + ClassDB::bind_method(D_METHOD("is_prefetching_nodepath_vars"), &BlackboardPlan::is_prefetching_nodepath_vars); + + ClassDB::bind_method(D_METHOD("create_blackboard", "node"), &BlackboardPlan::create_blackboard); + ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "node"), &BlackboardPlan::populate_blackboard); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefetch_nodepath_vars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_prefetch_nodepath_vars", "is_prefetching_nodepath_vars"); } BlackboardPlan::BlackboardPlan() { diff --git a/blackboard/blackboard_plan.h b/blackboard/blackboard_plan.h index 25599dd..6df1a21 100644 --- a/blackboard/blackboard_plan.h +++ b/blackboard/blackboard_plan.h @@ -36,6 +36,9 @@ private: // and only the values can be different in those variables. Ref base; + // 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; + protected: static void _bind_methods(); @@ -49,12 +52,15 @@ public: void set_base_plan(const Ref &p_base); Ref get_base_plan() const { return base; } + void set_prefetch_nodepath_vars(bool p_enable); + bool is_prefetching_nodepath_vars() const; + void add_var(const StringName &p_name, const BBVariable &p_var); void remove_var(const StringName &p_name); BBVariable get_var(const StringName &p_name); Pair get_var_by_index(int p_index); - bool has_var(const StringName &p_name) { return var_map.has(p_name); } - bool is_empty() const { return var_map.is_empty(); } + _FORCE_INLINE_ bool has_var(const StringName &p_name) { return var_map.has(p_name); } + _FORCE_INLINE_ bool is_empty() const { return var_map.is_empty(); } int get_var_count() const { return var_map.size(); } PackedStringArray list_vars() const; @@ -66,8 +72,8 @@ public: void sync_with_base_plan(); bool is_derived() const { return base.is_valid(); } - Ref create_blackboard(); - void populate_blackboard(const Ref &p_blackboard, bool overwrite); + Ref create_blackboard(Node *p_agent); + void populate_blackboard(const Ref &p_blackboard, bool overwrite, Node *p_node); BlackboardPlan(); }; diff --git a/bt/bt_player.cpp b/bt/bt_player.cpp index bb9b6bf..2cbdf8d 100644 --- a/bt/bt_player.cpp +++ b/bt/bt_player.cpp @@ -52,9 +52,6 @@ void BTPlayer::_load_tree() { tree_instance.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(), "BTPlayer: Behavior tree has no valid root task."); - if (prefetch_nodepath_vars == true) { - blackboard->prefetch_nodepath_vars(this); - } tree_instance = behavior_tree->instantiate(get_owner(), blackboard); #ifdef DEBUG_ENABLED if (IS_DEBUGGER_ACTIVE()) { @@ -187,7 +184,7 @@ void BTPlayer::_notification(int p_notification) { blackboard = Ref(memnew(Blackboard)); } if (blackboard_plan.is_valid()) { - blackboard_plan->populate_blackboard(blackboard, false); + blackboard_plan->populate_blackboard(blackboard, false, this); } if (behavior_tree.is_valid()) { _load_tree(); @@ -231,8 +228,6 @@ void BTPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_active"), &BTPlayer::get_active); ClassDB::bind_method(D_METHOD("set_blackboard", "blackboard"), &BTPlayer::set_blackboard); ClassDB::bind_method(D_METHOD("get_blackboard"), &BTPlayer::get_blackboard); - ClassDB::bind_method(D_METHOD("set_prefetch_nodepath_vars", "enable"), &BTPlayer::set_prefetch_nodepath_vars); - ClassDB::bind_method(D_METHOD("get_prefetch_nodepath_vars"), &BTPlayer::get_prefetch_nodepath_vars); ClassDB::bind_method(D_METHOD("set_blackboard_plan", "plan"), &BTPlayer::set_blackboard_plan); ClassDB::bind_method(D_METHOD("get_blackboard_plan"), &BTPlayer::get_blackboard_plan); @@ -248,7 +243,6 @@ void BTPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_plan", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardPlan", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_blackboard_plan", "get_blackboard_plan"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefetch_nodepath_vars"), "set_prefetch_nodepath_vars", "get_prefetch_nodepath_vars"); BIND_ENUM_CONSTANT(IDLE); BIND_ENUM_CONSTANT(PHYSICS); diff --git a/bt/bt_player.h b/bt/bt_player.h index f58e17b..06eec72 100644 --- a/bt/bt_player.h +++ b/bt/bt_player.h @@ -41,7 +41,6 @@ private: UpdateMode update_mode = UpdateMode::PHYSICS; bool active = true; Ref blackboard; - bool prefetch_nodepath_vars = true; int last_status = -1; Ref tree_instance; @@ -70,9 +69,6 @@ public: Ref get_blackboard() const { return blackboard; } void set_blackboard(const Ref &p_blackboard) { blackboard = p_blackboard; } - void set_prefetch_nodepath_vars(bool p_value) { prefetch_nodepath_vars = p_value; } - bool get_prefetch_nodepath_vars() const { return prefetch_nodepath_vars; } - void update(double p_delta); void restart(); int get_last_status() const { return last_status; } diff --git a/bt/bt_state.cpp b/bt/bt_state.cpp index b73e96c..84f1d7c 100644 --- a/bt/bt_state.cpp +++ b/bt/bt_state.cpp @@ -34,6 +34,7 @@ void BTState::set_behavior_tree(const Ref &p_tree) { if (p_tree.is_valid()) { p_tree->connect(LW_NAME(changed), callable_mp(this, &BTState::_update_blackboard_plan)); } + _update_blackboard_plan(); } behavior_tree = p_tree; } @@ -48,6 +49,7 @@ void BTState::_update_blackboard_plan() { void BTState::_setup() { LimboState::_setup(); ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned."); + // TODO: BBNode relies on agent to be scene owner, so if the user provides anything else, the behavior tree can break. tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard()); #ifdef DEBUG_ENABLED diff --git a/bt/bt_state.h b/bt/bt_state.h index 07f79f8..3ac823b 100644 --- a/bt/bt_state.h +++ b/bt/bt_state.h @@ -33,6 +33,8 @@ protected: void _notification(int p_notification); + virtual bool _should_use_new_scope() const override { return true; } + virtual void _setup() override; virtual void _exit() override; virtual void _update(double p_delta) override; diff --git a/bt/tasks/decorators/bt_new_scope.cpp b/bt/tasks/decorators/bt_new_scope.cpp index e1bb51c..e23fba9 100644 --- a/bt/tasks/decorators/bt_new_scope.cpp +++ b/bt/tasks/decorators/bt_new_scope.cpp @@ -17,7 +17,7 @@ void BTNewScope::initialize(Node *p_agent, const Ref &p_blackboard) Ref bb; if (blackboard_plan.is_valid()) { - bb = blackboard_plan->create_blackboard(); + bb = blackboard_plan->create_blackboard(p_agent); } else { bb = Ref(memnew(Blackboard)); } diff --git a/doc/source/classes/class_blackboard.rst b/doc/source/classes/class_blackboard.rst index 330d15b..ebd9a35 100644 --- a/doc/source/classes/class_blackboard.rst +++ b/doc/source/classes/class_blackboard.rst @@ -44,8 +44,6 @@ Methods +-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ | bool | :ref:`has_var` **(** StringName var_name **)** |const| | +-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`prefetch_nodepath_vars` **(** Node node **)** | - +-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ | void | :ref:`set_parent` **(** :ref:`Blackboard` blackboard **)** | +-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ | void | :ref:`set_var` **(** StringName var_name, Variant value **)** | @@ -124,18 +122,6 @@ Returns ``true`` if the Blackboard contains the ``var_name`` variable, including ---- -.. _class_Blackboard_method_prefetch_nodepath_vars: - -.. rst-class:: classref-method - -void **prefetch_nodepath_vars** **(** Node node **)** - -If ``true``, any ``NodePath`` variables in the **Blackboard** are replaced with ``Node`` references when the tree is instantiated. References are retrieved by calling :ref:`Node.get_node` on the agent instance. - -.. rst-class:: classref-item-separator - ----- - .. _class_Blackboard_method_set_parent: .. rst-class:: classref-method diff --git a/doc/source/classes/class_blackboardplan.rst b/doc/source/classes/class_blackboardplan.rst index 016269e..7bddb32 100644 --- a/doc/source/classes/class_blackboardplan.rst +++ b/doc/source/classes/class_blackboardplan.rst @@ -16,17 +16,51 @@ Stores and manages variables that will be used in constructing new :ref:`Blackbo .. rst-class:: classref-reftable-group +Properties +---------- + +.. table:: + :widths: auto + + +------+-------------------------------------------------------------------------------------+----------+ + | bool | :ref:`prefetch_nodepath_vars` | ``true`` | + +------+-------------------------------------------------------------------------------------+----------+ + +.. rst-class:: classref-reftable-group + Methods ------- .. table:: :widths: auto - +-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`Blackboard` | :ref:`create_blackboard` **(** **)** | - +-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`populate_blackboard` **(** :ref:`Blackboard` blackboard, bool overwrite **)** | - +-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`Blackboard` | :ref:`create_blackboard` **(** Node node **)** | + +-------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`populate_blackboard` **(** :ref:`Blackboard` blackboard, bool overwrite, Node node **)** | + +-------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +.. rst-class:: classref-section-separator + +---- + +.. rst-class:: classref-descriptions-group + +Property Descriptions +--------------------- + +.. _class_BlackboardPlan_property_prefetch_nodepath_vars: + +.. rst-class:: classref-property + +bool **prefetch_nodepath_vars** = ``true`` + +.. rst-class:: classref-property-setget + +- void **set_prefetch_nodepath_vars** **(** bool value **)** +- bool **is_prefetching_nodepath_vars** **(** **)** + +Enables or disables ``NodePath`` variable prefetching. If ``true``, ``NodePath`` values will be replaced with node instances when the :ref:`Blackboard` is created. .. rst-class:: classref-section-separator @@ -41,9 +75,9 @@ Method Descriptions .. rst-class:: classref-method -:ref:`Blackboard` **create_blackboard** **(** **)** +:ref:`Blackboard` **create_blackboard** **(** Node node **)** -Constructs a new instance of a :ref:`Blackboard` using this plan. +Constructs a new instance of a :ref:`Blackboard` using this plan. If ``NodePath`` prefetching is enabled, ``node`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values. .. rst-class:: classref-item-separator @@ -53,9 +87,9 @@ Constructs a new instance of a :ref:`Blackboard` using this pl .. rst-class:: classref-method -void **populate_blackboard** **(** :ref:`Blackboard` blackboard, bool overwrite **)** +void **populate_blackboard** **(** :ref:`Blackboard` blackboard, bool overwrite, Node node **)** -Populates ``blackboard`` with the variables from this plan. If ``overwrite`` is ``true``, existing variables with the same names will be overwritten. +Populates ``blackboard`` with the variables from this plan. If ``overwrite`` is ``true``, existing variables with the same names will be overwritten. If ``NodePath`` prefetching is enabled, ``node`` will be used to retrieve node instances for ``NodePath`` variables and substitute their values. .. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)` .. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)` diff --git a/doc/source/classes/class_btplayer.rst b/doc/source/classes/class_btplayer.rst index e5a3e0b..8678139 100644 --- a/doc/source/classes/class_btplayer.rst +++ b/doc/source/classes/class_btplayer.rst @@ -31,21 +31,19 @@ Properties .. table:: :widths: auto - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | bool | :ref:`active` | ``true`` | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | :ref:`BehaviorTree` | :ref:`behavior_tree` | | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | :ref:`Blackboard` | :ref:`blackboard` | | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | :ref:`BlackboardPlan` | :ref:`blackboard_plan` | | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | bool | :ref:`monitor_performance` | ``false`` | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | bool | :ref:`prefetch_nodepath_vars` | ``true`` | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ - | :ref:`UpdateMode` | :ref:`update_mode` | ``1`` | - +---------------------------------------------+-------------------------------------------------------------------------------+-----------+ + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | bool | :ref:`active` | ``true`` | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | :ref:`BehaviorTree` | :ref:`behavior_tree` | | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | :ref:`Blackboard` | :ref:`blackboard` | | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | :ref:`BlackboardPlan` | :ref:`blackboard_plan` | | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | bool | :ref:`monitor_performance` | ``false`` | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ + | :ref:`UpdateMode` | :ref:`update_mode` | ``1`` | + +---------------------------------------------+-------------------------------------------------------------------------+-----------+ .. rst-class:: classref-reftable-group @@ -226,23 +224,6 @@ If ``true``, adds a performance monitor to "Debugger->Monitors" for each instanc ---- -.. _class_BTPlayer_property_prefetch_nodepath_vars: - -.. rst-class:: classref-property - -bool **prefetch_nodepath_vars** = ``true`` - -.. rst-class:: classref-property-setget - -- void **set_prefetch_nodepath_vars** **(** bool value **)** -- bool **get_prefetch_nodepath_vars** **(** **)** - -If ``true``, any ``NodePath`` variables in the :ref:`Blackboard` are replaced with ``Node`` references when the tree is instantiated. References are retrieved by calling :ref:`Node.get_node` on the agent instance (agent is the owner of the BTPlayer node). - -.. rst-class:: classref-item-separator - ----- - .. _class_BTPlayer_property_update_mode: .. rst-class:: classref-property diff --git a/doc_classes/BTPlayer.xml b/doc_classes/BTPlayer.xml index 1b9e9a6..ee232ca 100644 --- a/doc_classes/BTPlayer.xml +++ b/doc_classes/BTPlayer.xml @@ -52,9 +52,6 @@ If [code]true[/code], adds a performance monitor to "Debugger->Monitors" for each instance of this [BTPlayer] node. - - If [code]true[/code], any [NodePath] variables in the [Blackboard] are replaced with [Node] references when the tree is instantiated. References are retrieved by calling [method Node.get_node] on the agent instance (agent is the owner of the BTPlayer node). - Determines when the behavior tree is executed. See [enum UpdateMode]. diff --git a/doc_classes/Blackboard.xml b/doc_classes/Blackboard.xml index ae2fa1f..41ee2a9 100644 --- a/doc_classes/Blackboard.xml +++ b/doc_classes/Blackboard.xml @@ -49,13 +49,6 @@ Returns [code]true[/code] if the Blackboard contains the [param var_name] variable, including the parent scopes. - - - - - If [code]true[/code], any [NodePath] variables in the [Blackboard] are replaced with [Node] references when the tree is instantiated. References are retrieved by calling [method Node.get_node] on the agent instance. - - diff --git a/doc_classes/BlackboardPlan.xml b/doc_classes/BlackboardPlan.xml index c7c0218..fa40124 100644 --- a/doc_classes/BlackboardPlan.xml +++ b/doc_classes/BlackboardPlan.xml @@ -10,17 +10,24 @@ + - Constructs a new instance of a [Blackboard] using this plan. + Constructs a new instance of a [Blackboard] using this plan. If [NodePath] prefetching is enabled, [param node] will be used to retrieve node instances for [NodePath] variables and substitute their values. + - Populates [param blackboard] with the variables from this plan. If [param overwrite] is [code]true[/code], existing variables with the same names will be overwritten. + Populates [param blackboard] with the variables from this plan. If [param overwrite] is [code]true[/code], existing variables with the same names will be overwritten. If [NodePath] prefetching is enabled, [param node] will be used to retrieve node instances for [NodePath] variables and substitute their values. + + + Enables or disables [NodePath] variable prefetching. If [code]true[/code], [NodePath] values will be replaced with node instances when the [Blackboard] is created. + + diff --git a/editor/blackboard_plan_editor.cpp b/editor/blackboard_plan_editor.cpp index 7372fc7..a6f1223 100644 --- a/editor/blackboard_plan_editor.cpp +++ b/editor/blackboard_plan_editor.cpp @@ -176,6 +176,11 @@ void BlackboardPlanEditor::_add_var_pressed() { scroll_container->call_deferred(LW_NAME(call_deferred), LW_NAME(set_v_scroll), 888888888); } +void BlackboardPlanEditor::_prefetching_toggled(bool p_toggle_on) { + ERR_FAIL_COND(plan.is_null()); + plan->set_prefetch_nodepath_vars(p_toggle_on); +} + void BlackboardPlanEditor::_drag_button_down(Control *p_row) { drag_index = p_row->get_index(); drag_start = drag_index; @@ -240,7 +245,7 @@ void BlackboardPlanEditor::_refresh() { child->queue_free(); } - // TODO: Name validation + nodepath_prefetching->set_pressed(plan->is_prefetching_nodepath_vars()); PackedStringArray names = plan->list_vars(); int idx = 0; @@ -345,6 +350,7 @@ void BlackboardPlanEditor::_notification(int p_what) { connect(LW_NAME(visibility_changed), callable_mp(this, &BlackboardPlanEditor::_visibility_changed)); type_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_type_chosen)); hint_menu->connect(LW_NAME(id_pressed), callable_mp(this, &BlackboardPlanEditor::_hint_chosen)); + nodepath_prefetching->connect(LW_NAME(toggled), callable_mp(this, &BlackboardPlanEditor::_prefetching_toggled)); for (int i = 0; i < PropertyHint::PROPERTY_HINT_MAX; i++) { hint_menu->add_item(LimboUtility::get_singleton()->get_property_hint_text(PropertyHint(i)), i); @@ -377,6 +383,13 @@ BlackboardPlanEditor::BlackboardPlanEditor() { add_var_tool->set_focus_mode(Control::FOCUS_NONE); add_var_tool->set_text(TTR("Add variable")); + nodepath_prefetching = memnew(CheckBox); + toolbar->add_child(nodepath_prefetching); + nodepath_prefetching->set_text(TTR("NodePath Prefetching")); + nodepath_prefetching->set_tooltip_text(TTR("If checked, NodePath variables will be prefetched on Blackboard initialization.")); + nodepath_prefetching->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_END); + nodepath_prefetching->set_focus_mode(Control::FOCUS_NONE); + { // * Header header_row = memnew(PanelContainer); diff --git a/editor/blackboard_plan_editor.h b/editor/blackboard_plan_editor.h index 882ac41..7dcff2f 100644 --- a/editor/blackboard_plan_editor.h +++ b/editor/blackboard_plan_editor.h @@ -18,11 +18,13 @@ #ifdef LIMBOAI_MODULE #include "editor/editor_inspector.h" +#include "scene/gui/check_box.h" #include "scene/gui/dialogs.h" #endif // LIMBOAI_MODULE #ifdef LIMBOAI_GDEXTENSION #include +#include #include #include #include @@ -60,6 +62,7 @@ private: VBoxContainer *rows_vbox; Button *add_var_tool; + CheckBox *nodepath_prefetching; PanelContainer *header_row; ScrollContainer *scroll_container; PopupMenu *type_menu; @@ -78,6 +81,7 @@ private: void _type_chosen(int id); void _hint_chosen(int id); void _add_var_pressed(); + void _prefetching_toggled(bool p_toggle_on); void _drag_button_down(Control *p_row); void _drag_button_up(); diff --git a/hsm/limbo_hsm.cpp b/hsm/limbo_hsm.cpp index 9532712..6390fdd 100644 --- a/hsm/limbo_hsm.cpp +++ b/hsm/limbo_hsm.cpp @@ -195,9 +195,12 @@ bool LimboHSM::_dispatch(const StringName &p_event, const Variant &p_cargo) { void LimboHSM::initialize(Node *p_agent, const Ref &p_parent_scope) { ERR_FAIL_COND(p_agent == nullptr); + ERR_FAIL_COND_MSG(!is_root(), "LimboHSM: initialize() must be called on the root HSM."); + if (!p_parent_scope.is_null()) { blackboard->set_parent(p_parent_scope); } + _initialize(p_agent, nullptr); if (initial_state == nullptr) { diff --git a/hsm/limbo_state.cpp b/hsm/limbo_state.cpp index 180d135..5931d25 100644 --- a/hsm/limbo_state.cpp +++ b/hsm/limbo_state.cpp @@ -28,7 +28,7 @@ LimboState *LimboState::get_root() const { const LimboState *state = this; - while (state->get_parent() && state->get_parent()->is_class("LimboState")) { + while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) { state = Object::cast_to(get_parent()); } return const_cast(state); @@ -68,13 +68,13 @@ void LimboState::_initialize(Node *p_agent, const Ref &p_blackboard) ERR_FAIL_COND(p_agent == nullptr); agent = p_agent; - if (!p_blackboard.is_null()) { - if (blackboard_plan.is_valid() && !blackboard_plan->is_empty()) { - blackboard = blackboard_plan->create_blackboard(); - blackboard->set_parent(p_blackboard); - } else { - blackboard = p_blackboard; - } + if (_should_use_new_scope()) { + blackboard->set_parent(p_blackboard); + } else { + blackboard = p_blackboard; + } + if (blackboard_plan.is_valid() && !blackboard_plan->is_empty()) { + blackboard_plan->populate_blackboard(blackboard, true, this); } _setup(); diff --git a/hsm/limbo_state.h b/hsm/limbo_state.h index 47b6d75..571861e 100644 --- a/hsm/limbo_state.h +++ b/hsm/limbo_state.h @@ -15,6 +15,7 @@ #include "../blackboard/blackboard.h" #include "../blackboard/blackboard_plan.h" +#include "../util/limbo_compat.h" #include "../util/limbo_string_names.h" #ifdef LIMBOAI_MODULE @@ -56,6 +57,8 @@ protected: virtual void _initialize(Node *p_agent, const Ref &p_blackboard); virtual bool _dispatch(const StringName &p_event, const Variant &p_cargo = Variant()); + virtual bool _should_use_new_scope() const { return blackboard_plan.is_valid() || is_root(); } + virtual void _setup(); virtual void _enter(); virtual void _exit(); @@ -87,6 +90,7 @@ public: _FORCE_INLINE_ StringName event_finished() const { return LW_NAME(EVENT_FINISHED); } LimboState *get_root() const; + _FORCE_INLINE_ bool is_root() const { return !(get_parent() && IS_CLASS(get_parent(), LimboState)); } bool is_active() const { return active; } void set_guard(const Callable &p_guard_callable);