diff --git a/blackboard/blackboard_plan.cpp b/blackboard/blackboard_plan.cpp index d55cd03..6d9c7ff 100644 --- a/blackboard/blackboard_plan.cpp +++ b/blackboard/blackboard_plan.cpp @@ -11,6 +11,8 @@ #include "blackboard_plan.h" +#include "../util/limbo_utility.h" + bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) { String name_str = p_name; @@ -25,6 +27,28 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) { return true; } + // * Mapping + if (name_str.begins_with("mapping/")) { + StringName mapped_var_name = name_str.get_slicec('/', 1); + StringName value = p_value; + bool properties_changed = false; + if (value == StringName()) { + if (parent_scope_mapping.has(mapped_var_name)) { + properties_changed = true; + parent_scope_mapping.erase(mapped_var_name); + } + } else { + if (!parent_scope_mapping.has(mapped_var_name)) { + properties_changed = true; + } + parent_scope_mapping[mapped_var_name] = value; + } + if (properties_changed) { + notify_property_list_changed(); + } + return true; + } + // * Storage if (name_str.begins_with("var/")) { StringName var_name = name_str.get_slicec('/', 1); @@ -56,7 +80,23 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const { // * Editor if (var_map.has(p_name)) { - r_ret = var_map[p_name].get_value(); + if (has_mapping(p_name)) { + r_ret = "Mapped to " + LimboUtility::get_singleton()->decorate_var(parent_scope_mapping[p_name]); + } else { + r_ret = var_map[p_name].get_value(); + } + return true; + } + + // * Mapping + if (name_str.begins_with("mapping/")) { + StringName mapped_var_name = name_str.get_slicec('/', 1); + ERR_FAIL_COND_V(mapped_var_name == StringName(), false); + if (parent_scope_mapping.has(mapped_var_name)) { + r_ret = parent_scope_mapping[mapped_var_name]; + } else { + r_ret = StringName(); + } return true; } @@ -64,7 +104,6 @@ bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const { if (!name_str.begins_with("var/")) { return false; } - StringName var_name = name_str.get_slicec('/', 1); String what = name_str.get_slicec('/', 2); ERR_FAIL_COND_V(!var_map.has(var_name), false); @@ -90,29 +129,49 @@ void BlackboardPlan::_get_property_list(List *p_list) const { // * Editor if (var.get_type() != Variant::NIL && (!is_derived() || !var_name.begins_with("_"))) { - p_list->push_back(PropertyInfo(var.get_type(), var_name, var.get_hint(), var.get_hint_string(), PROPERTY_USAGE_EDITOR)); + if (has_mapping(var_name)) { + p_list->push_back(PropertyInfo(Variant::STRING, var_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY)); + } else { + p_list->push_back(PropertyInfo(var.get_type(), var_name, var.get_hint(), var.get_hint_string(), PROPERTY_USAGE_EDITOR)); + } } + // * Storage if (is_derived() && (!var.is_value_changed() || var.get_value() == base->var_map[var_name].get_value())) { // Don't store variable if it's not modified in a derived plan. // Variable is considered modified when it's marked as changed and its value is different from the base plan. continue; } - - // * Storage p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(var.get_type(), "var/" + var_name + "/value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::INT, "var/" + var_name + "/hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::STRING, "var/" + var_name + "/hint_string", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } + + // * Mapping + 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) { + // Serialize only non-empty mappings. + PropertyUsageFlags usage = has_mapping(p.first) ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_EDITOR; + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "mapping/" + p.first, PROPERTY_HINT_NONE, "", usage)); + } + } } bool BlackboardPlan::_property_can_revert(const StringName &p_name) const { + if (String(p_name).begins_with("mapping/")) { + return true; + } return base.is_valid() && base->var_map.has(p_name); } bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const { + if (String(p_name).begins_with("mapping/")) { + r_property = StringName(); + return true; + } if (base->var_map.has(p_name)) { r_property = base->var_map[p_name].get_value(); return true; @@ -131,6 +190,15 @@ void BlackboardPlan::set_base_plan(const Ref &p_base) { notify_property_list_changed(); } +void BlackboardPlan::set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider) { + parent_scope_plan_provider = p_parent_scope_plan_provider; + notify_property_list_changed(); +} + +bool BlackboardPlan::has_mapping(const StringName &p_name) const { + 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) { prefetch_nodepath_vars = p_enable; emit_changed(); @@ -214,6 +282,11 @@ void BlackboardPlan::rename_var(const StringName &p_name, const StringName &p_ne var_map.erase(p_name); var_map.insert(p_new_name, var); + if (parent_scope_mapping.has(p_name)) { + parent_scope_mapping[p_new_name] = parent_scope_mapping[p_name]; + parent_scope_mapping.erase(p_name); + } + notify_property_list_changed(); emit_changed(); } @@ -335,12 +408,11 @@ inline void bb_add_var_dup_with_prefetch(const Ref &p_blackboard, co } } -Ref BlackboardPlan::create_blackboard(Node *p_node) { +Ref BlackboardPlan::create_blackboard(Node *p_node, const Ref &p_parent_scope) { 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_dup_with_prefetch(bb, p.first, p.second, prefetch_nodepath_vars, p_node); - } + bb->set_parent(p_parent_scope); + populate_blackboard(bb, true, p_node); return bb; } @@ -351,6 +423,13 @@ void BlackboardPlan::populate_blackboard(const Ref &p_blackboard, bo continue; } bb_add_var_dup_with_prefetch(p_blackboard, p.first, p.second, prefetch_nodepath_vars, p_node); + if (parent_scope_mapping.has(p.first)) { + StringName target_var = parent_scope_mapping[p.first]; + if (target_var != StringName()) { + ERR_CONTINUE_MSG(p_blackboard->get_parent() == nullptr, vformat("BlackboardPlan: Cannot link variable $%s to parent scope because the parent scope is not set.", p.first)); + p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var); + } + } } } @@ -362,7 +441,9 @@ void BlackboardPlan::_bind_methods() { ClassDB::bind_method(D_METHOD("get_base_plan"), &BlackboardPlan::get_base_plan); 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); + ClassDB::bind_method(D_METHOD("set_parent_scope_plan_provider", "callable"), &BlackboardPlan::set_parent_scope_plan_provider); + ClassDB::bind_method(D_METHOD("get_parent_scope_plan_provider"), &BlackboardPlan::get_parent_scope_plan_provider); + ClassDB::bind_method(D_METHOD("create_blackboard", "node", "parent_scope"), &BlackboardPlan::create_blackboard, DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("populate_blackboard", "blackboard", "overwrite", "node"), &BlackboardPlan::populate_blackboard); // To avoid cluttering the member namespace, we do not export unnecessary properties in this class. diff --git a/blackboard/blackboard_plan.h b/blackboard/blackboard_plan.h index 83fdd45..222af2f 100644 --- a/blackboard/blackboard_plan.h +++ b/blackboard/blackboard_plan.h @@ -36,6 +36,13 @@ private: // and only the values can be different in those variables. Ref base; + // 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; + // Fetcher function for the parent scope plan. Funtion should return a Ref. + // Used in the inspector. When set, mapping feature becomes available. + Callable parent_scope_plan_provider; + // 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; @@ -52,6 +59,12 @@ public: void set_base_plan(const Ref &p_base); Ref get_base_plan() const { return base; } + void set_parent_scope_plan_provider(const Callable &p_parent_scope_plan_provider); + Callable get_parent_scope_plan_provider() const { return parent_scope_plan_provider; } + + bool is_mapping_enabled() const { return parent_scope_plan_provider.is_valid() && (parent_scope_plan_provider.call() != Ref()); } + bool has_mapping(const StringName &p_name) const; + void set_prefetch_nodepath_vars(bool p_enable); bool is_prefetching_nodepath_vars() const; @@ -72,7 +85,7 @@ public: void sync_with_base_plan(); _FORCE_INLINE_ bool is_derived() const { return base.is_valid(); } - Ref create_blackboard(Node *p_agent); + Ref create_blackboard(Node *p_agent, const Ref &p_parent_scope = Ref()); void populate_blackboard(const Ref &p_blackboard, bool overwrite, Node *p_node); BlackboardPlan(); diff --git a/bt/behavior_tree.cpp b/bt/behavior_tree.cpp index 817b8a6..b15f480 100644 --- a/bt/behavior_tree.cpp +++ b/bt/behavior_tree.cpp @@ -52,7 +52,13 @@ void BehaviorTree::set_blackboard_plan(const Ref &p_plan) { } void BehaviorTree::set_root_task(const Ref &p_value) { +#ifdef TOOLS_ENABLED + _unset_editor_behavior_tree_hint(); +#endif // TOOLS_ENABLED root_task = p_value; +#ifdef TOOLS_ENABLED + _set_editor_behavior_tree_hint(); +#endif // TOOLS_ENABLED emit_changed(); } @@ -85,6 +91,22 @@ void BehaviorTree::_plan_changed() { emit_changed(); } +#ifdef TOOLS_ENABLED + +void BehaviorTree::_set_editor_behavior_tree_hint() { + if (root_task.is_valid()) { + root_task->data.behavior_tree_id = this->get_instance_id(); + } +} + +void BehaviorTree::_unset_editor_behavior_tree_hint() { + if (root_task.is_valid()) { + root_task->data.behavior_tree_id = ObjectID(); + } +} + +#endif // TOOLS_ENABLED + 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..46507c5 100644 --- a/bt/behavior_tree.h +++ b/bt/behavior_tree.h @@ -34,6 +34,11 @@ private: void _plan_changed(); +#ifdef TOOLS_ENABLED + void _set_editor_behavior_tree_hint(); + void _unset_editor_behavior_tree_hint(); +#endif // TOOLS_ENABLED + protected: static void _bind_methods(); diff --git a/bt/bt_state.cpp b/bt/bt_state.cpp index 1a29f03..dd1c659 100644 --- a/bt/bt_state.cpp +++ b/bt/bt_state.cpp @@ -32,10 +32,10 @@ void BTState::set_behavior_tree(const Ref &p_tree) { p_tree->connect(LW_NAME(plan_changed), callable_mp(this, &BTState::_update_blackboard_plan)); } behavior_tree = p_tree; - _update_blackboard_plan(); } else { behavior_tree = p_tree; } + _update_blackboard_plan(); } void BTState::_update_blackboard_plan() { diff --git a/bt/tasks/bt_task.cpp b/bt/tasks/bt_task.cpp index 9a5e284..4fa7ef1 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,22 @@ void BTTask::print_tree(int p_initial_tabs) { } } +#ifdef TOOLS_ENABLED + +Ref BTTask::editor_get_behavior_tree() { + BTTask *task = this; + while (task->data.behavior_tree_id.is_null() && task->get_parent().is_valid()) { + task = task->data.parent; + } + return Object::cast_to(ObjectDB::get_instance(task->data.behavior_tree_id)); +} + +void BTTask::editor_set_behavior_tree(const Ref &p_bt) { + data.behavior_tree_id = p_bt->get_instance_id(); +} + +#endif // TOOLS_ENABLED + void BTTask::_bind_methods() { // Public Methods. ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root); @@ -397,6 +414,9 @@ 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); +#ifdef TOOLS_ENABLED + ClassDB::bind_method(D_METHOD("editor_get_behavior_tree"), &BTTask::editor_get_behavior_tree); +#endif // TOOLS_ENABLED // 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..b571c27 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 + ObjectID behavior_tree_id; +#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_new_scope.cpp b/bt/tasks/decorators/bt_new_scope.cpp index 5aaa4bc..5a2b1c4 100644 --- a/bt/tasks/decorators/bt_new_scope.cpp +++ b/bt/tasks/decorators/bt_new_scope.cpp @@ -11,28 +11,45 @@ #include "bt_new_scope.h" +#include "../../behavior_tree.h" + void BTNewScope::set_blackboard_plan(const Ref &p_plan) { blackboard_plan = p_plan; if (blackboard_plan.is_null()) { blackboard_plan.instantiate(); } + _update_blackboard_plan(); + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + callable_mp(this, &BTNewScope::_set_parent_scope_plan_from_bt).call_deferred(); + } +#endif // TOOLS_ENABLED + emit_changed(); } +#ifdef TOOLS_ENABLED +void BTNewScope::_set_parent_scope_plan_from_bt() { + ERR_FAIL_NULL(get_blackboard_plan()); + Ref bt = get_root()->editor_get_behavior_tree(); + ERR_FAIL_NULL(bt); + get_blackboard_plan()->set_parent_scope_plan_provider(callable_mp(bt.ptr(), &BehaviorTree::get_blackboard_plan)); +} +#endif // TOOLS_ENABLED + void BTNewScope::initialize(Node *p_agent, const Ref &p_blackboard, Node *p_scene_root) { ERR_FAIL_COND(p_agent == nullptr); ERR_FAIL_COND(p_blackboard == nullptr); Ref bb; if (blackboard_plan.is_valid()) { - bb = blackboard_plan->create_blackboard(p_agent); + bb = blackboard_plan->create_blackboard(p_agent, p_blackboard); } else { bb = Ref(memnew(Blackboard)); + bb->set_parent(p_blackboard); } - - bb->set_parent(p_blackboard); - BTDecorator::initialize(p_agent, bb, p_scene_root); } diff --git a/bt/tasks/decorators/bt_new_scope.h b/bt/tasks/decorators/bt_new_scope.h index a7e0020..b3662f5 100644 --- a/bt/tasks/decorators/bt_new_scope.h +++ b/bt/tasks/decorators/bt_new_scope.h @@ -23,6 +23,10 @@ class BTNewScope : public BTDecorator { private: Ref blackboard_plan; +#ifdef TOOLS_ENABLED + void _set_parent_scope_plan_from_bt(); +#endif // TOOLS_ENABLED + protected: static void _bind_methods(); diff --git a/doc/source/classes/class_blackboardplan.rst b/doc/source/classes/class_blackboardplan.rst index f19a4c7..cb66121 100644 --- a/doc/source/classes/class_blackboardplan.rst +++ b/doc/source/classes/class_blackboardplan.rst @@ -35,16 +35,20 @@ Methods :widths: auto +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`Blackboard` | :ref:`create_blackboard` **(** Node node **)** | + | :ref:`Blackboard` | :ref:`create_blackboard` **(** Node node, :ref:`Blackboard` parent_scope=null **)** | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`BlackboardPlan` | :ref:`get_base_plan` **(** **)** |const| | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Callable | :ref:`get_parent_scope_plan_provider` **(** **)** |const| | + +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | bool | :ref:`is_derived` **(** **)** |const| | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | void | :ref:`populate_blackboard` **(** :ref:`Blackboard` blackboard, bool overwrite, Node node **)** | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | void | :ref:`set_base_plan` **(** :ref:`BlackboardPlan` blackboard_plan **)** | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`set_parent_scope_plan_provider` **(** Callable callable **)** | + +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | void | :ref:`sync_with_base_plan` **(** **)** | +---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -83,7 +87,7 @@ Method Descriptions .. rst-class:: classref-method -:ref:`Blackboard` **create_blackboard** **(** Node node **)** +:ref:`Blackboard` **create_blackboard** **(** Node node, :ref:`Blackboard` parent_scope=null **)** 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. @@ -103,6 +107,18 @@ Returns the base plan. See :ref:`is_derived` **(** **)** |virtual| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`_exit` **(** **)** |virtual| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | String | :ref:`_generate_name` **(** **)** |virtual| |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | PackedStringArray | :ref:`_get_configuration_warnings` **(** **)** |virtual| |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`_setup` **(** **)** |virtual| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`Status` | :ref:`_tick` **(** float delta **)** |virtual| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`abort` **(** **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`add_child` **(** :ref:`BTTask` task **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`add_child_at_index` **(** :ref:`BTTask` task, int idx **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`BTTask` | :ref:`clone` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`Status` | :ref:`execute` **(** float delta **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`BTTask` | :ref:`get_child` **(** int idx **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | int | :ref:`get_child_count` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | int | :ref:`get_child_count_excluding_comments` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | int | :ref:`get_index` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`BTTask` | :ref:`get_parent` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`BTTask` | :ref:`get_root` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | String | :ref:`get_task_name` **(** **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | bool | :ref:`has_child` **(** :ref:`BTTask` task **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`initialize` **(** Node agent, :ref:`Blackboard` blackboard, Node scene_root **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | bool | :ref:`is_descendant_of` **(** :ref:`BTTask` task **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | bool | :ref:`is_root` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | :ref:`BTTask` | :ref:`next_sibling` **(** **)** |const| | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`print_tree` **(** int initial_tabs=0 **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`remove_child` **(** :ref:`BTTask` task **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - | void | :ref:`remove_child_at_index` **(** int idx **)** | - +-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`_enter` **(** **)** |virtual| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`_exit` **(** **)** |virtual| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | String | :ref:`_generate_name` **(** **)** |virtual| |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | PackedStringArray | :ref:`_get_configuration_warnings` **(** **)** |virtual| |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`_setup` **(** **)** |virtual| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`Status` | :ref:`_tick` **(** float delta **)** |virtual| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`abort` **(** **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`add_child` **(** :ref:`BTTask` task **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`add_child_at_index` **(** :ref:`BTTask` task, int idx **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BTTask` | :ref:`clone` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BehaviorTree` | :ref:`editor_get_behavior_tree` **(** **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`Status` | :ref:`execute` **(** float delta **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BTTask` | :ref:`get_child` **(** int idx **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | int | :ref:`get_child_count` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | int | :ref:`get_child_count_excluding_comments` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | int | :ref:`get_index` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BTTask` | :ref:`get_parent` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BTTask` | :ref:`get_root` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | String | :ref:`get_task_name` **(** **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | bool | :ref:`has_child` **(** :ref:`BTTask` task **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`initialize` **(** Node agent, :ref:`Blackboard` blackboard, Node scene_root **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | bool | :ref:`is_descendant_of` **(** :ref:`BTTask` task **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | bool | :ref:`is_root` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | :ref:`BTTask` | :ref:`next_sibling` **(** **)** |const| | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`print_tree` **(** int initial_tabs=0 **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`remove_child` **(** :ref:`BTTask` task **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + | void | :ref:`remove_child_at_index` **(** int idx **)** | + +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+ .. rst-class:: classref-section-separator @@ -366,6 +368,18 @@ Duplicates the task and its children, copying the exported members. Sub-resource ---- +.. _class_BTTask_method_editor_get_behavior_tree: + +.. rst-class:: classref-method + +:ref:`BehaviorTree` **editor_get_behavior_tree** **(** **)** + +Returns the behavior tree that owns this task. This is only available in the editor. + +.. rst-class:: classref-item-separator + +---- + .. _class_BTTask_method_execute: .. rst-class:: classref-method diff --git a/doc_classes/BTTask.xml b/doc_classes/BTTask.xml index 1c922ee..ff2085c 100644 --- a/doc_classes/BTTask.xml +++ b/doc_classes/BTTask.xml @@ -79,6 +79,12 @@ Duplicates the task and its children, copying the exported members. Sub-resources are shared for efficiency, except for [BBParam] subtypes, which are always copied. Used by the editor to instantiate [BehaviorTree] and copy-paste tasks. + + + + Returns the behavior tree that owns this task. This is only available in the editor. + + diff --git a/doc_classes/BlackboardPlan.xml b/doc_classes/BlackboardPlan.xml index 2be4080..80de4d5 100644 --- a/doc_classes/BlackboardPlan.xml +++ b/doc_classes/BlackboardPlan.xml @@ -11,6 +11,7 @@ + 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. @@ -21,6 +22,12 @@ Returns the base plan. See [method is_derived]. + + + + Returns the parent scope plan provider - a callable that returns a [BlackboardPlan]. + + @@ -44,6 +51,13 @@ Use with caution, as it will remove variables not present in the base plan. Only use this for custom tooling. + + + + + Sets the parent scope plan provider - a callable that returns a [BlackboardPlan]. Used to provide hints in the inspector. When set, mapping feature becomes available. + + diff --git a/editor/blackboard_plan_editor.cpp b/editor/blackboard_plan_editor.cpp index a6f1223..afdb5bf 100644 --- a/editor/blackboard_plan_editor.cpp +++ b/editor/blackboard_plan_editor.cpp @@ -48,14 +48,18 @@ void BlackboardPlanEditor::_add_var() { ERR_FAIL_NULL(plan); int suffix = 1; - StringName var_name = default_var_name; + StringName var_name = default_var_name == StringName() ? "var" : default_var_name; while (plan->has_var(var_name)) { suffix += 1; var_name = String(default_var_name) + itos(suffix); } - BBVariable var(Variant::Type::FLOAT); + BBVariable var(default_type, default_hint, default_hint_string); + if (default_value.get_type() == default_type) { + var.set_value(default_value); + } plan->add_var(var_name, var); + reset_defaults(); _refresh(); } @@ -127,10 +131,19 @@ void BlackboardPlanEditor::edit_plan(const Ref &p_plan) { _refresh(); } -void BlackboardPlanEditor::set_next_var_name(const StringName &p_name) { - if (String(p_name).is_valid_identifier()) { - default_var_name = p_name; - } +void BlackboardPlanEditor::set_defaults(const StringName &p_var_name, Variant::Type p_type, PropertyHint p_hint, String p_hint_string, Variant p_value) { + default_var_name = p_var_name; + default_type = p_type; + default_hint = p_hint; + default_hint_string = p_hint_string; + default_value = p_value; +} + +void BlackboardPlanEditor::reset_defaults() { + default_var_name = "var"; + default_type = Variant::FLOAT; + default_hint = PROPERTY_HINT_NONE; + default_hint_string = ""; } void BlackboardPlanEditor::_show_button_popup(Button *p_button, PopupMenu *p_popup, int p_index) { @@ -233,7 +246,7 @@ void BlackboardPlanEditor::_drag_button_gui_input(const Ref &p_event void BlackboardPlanEditor::_visibility_changed() { if (!is_visible() && plan.is_valid()) { plan->notify_property_list_changed(); - default_var_name = "var"; + reset_defaults(); } } @@ -367,7 +380,7 @@ void BlackboardPlanEditor::_notification(int p_what) { } BlackboardPlanEditor::BlackboardPlanEditor() { - default_var_name = "var"; + reset_defaults(); set_title(TTR("Manage Blackboard Plan")); diff --git a/editor/blackboard_plan_editor.h b/editor/blackboard_plan_editor.h index 7dcff2f..a711184 100644 --- a/editor/blackboard_plan_editor.h +++ b/editor/blackboard_plan_editor.h @@ -59,6 +59,10 @@ private: Ref plan; StringName default_var_name; + Variant::Type default_type = Variant::NIL; + PropertyHint default_hint = PROPERTY_HINT_NONE; + String default_hint_string; + Variant default_value; VBoxContainer *rows_vbox; Button *add_var_tool; @@ -99,7 +103,8 @@ public: _FORCE_INLINE_ static BlackboardPlanEditor *get_singleton() { return singleton; } void edit_plan(const Ref &p_plan); - void set_next_var_name(const StringName &p_name); + void set_defaults(const StringName &p_name, Variant::Type p_type = Variant::FLOAT, PropertyHint p_hint = PROPERTY_HINT_NONE, String p_hint_string = "", Variant p_value = Variant()); + void reset_defaults(); BlackboardPlanEditor(); }; diff --git a/editor/editor_property_bb_param.cpp b/editor/editor_property_bb_param.cpp index 687b9eb..707fdbb 100644 --- a/editor/editor_property_bb_param.cpp +++ b/editor/editor_property_bb_param.cpp @@ -300,7 +300,7 @@ void EditorPropertyBBParam::update_property() { void EditorPropertyBBParam::setup(PropertyHint p_hint, const String &p_hint_text, const Ref &p_plan) { param_type = p_hint_text; property_hint = p_hint; - variable_editor->setup(p_plan); + variable_editor->setup(p_plan, false); variable_editor->set_name_split_ratio(0.0); } diff --git a/editor/editor_property_variable_name.cpp b/editor/editor_property_variable_name.cpp index 4a8190f..0c40293 100644 --- a/editor/editor_property_variable_name.cpp +++ b/editor/editor_property_variable_name.cpp @@ -31,6 +31,8 @@ #include #endif // LIMBOAI_GDEXTENSION +int EditorPropertyVariableName::last_caret_column = 0; + //***** EditorPropertyVariableName void EditorPropertyVariableName::_show_variables_popup() { @@ -55,14 +57,26 @@ void EditorPropertyVariableName::_show_variables_popup() { } void EditorPropertyVariableName::_name_changed(const String &p_new_name) { + if (updating) { + return; + } + emit_changed(get_edited_property(), p_new_name); + last_caret_column = name_edit->get_caret_column(); _update_status(); } +void EditorPropertyVariableName::_name_submitted() { + _name_changed(name_edit->get_text()); + if (name_edit->has_focus()) { + name_edit->release_focus(); + } +} + void EditorPropertyVariableName::_variable_selected(int p_id) { String var_name = plan->get_var_by_index(p_id).first; name_edit->set_text(var_name); - _name_changed(var_name); + _name_submitted(); } void EditorPropertyVariableName::_update_status() { @@ -71,9 +85,21 @@ void EditorPropertyVariableName::_update_status() { if (plan.is_null()) { return; } - if (plan->has_var(name_edit->get_text())) { - BUTTON_SET_ICON(status_btn, theme_cache.var_exists_icon); - status_btn->set_tooltip_text(TTR("This variable is present in the blackboard plan.\nClick to open the blackboard plan.")); + String var_name = name_edit->get_text(); + if (var_name.is_empty() && allow_empty) { + BUTTON_SET_ICON(status_btn, theme_cache.var_empty_icon); + status_btn->set_tooltip_text(TTR("Variable name not specified.\nClick to open the blackboard plan.")); + } else if (plan->has_var(var_name)) { + if (expected_type == Variant::NIL || plan->get_var(var_name).get_type() == expected_type) { + BUTTON_SET_ICON(status_btn, theme_cache.var_exists_icon); + status_btn->set_tooltip_text(TTR("This variable is present in the blackboard plan.\nClick to open the blackboard plan.")); + } else { + BUTTON_SET_ICON(status_btn, theme_cache.var_error_icon); + status_btn->set_tooltip_text(TTR(vformat( + "The %s variable in the blackboard plan is not of the same type as this variable (expected %s).\nClick to open the blackboard plan and fix the variable type.", + LimboUtility::get_singleton()->decorate_var(var_name), + Variant::get_type_name(expected_type)))); + } } else if (name_edit->get_text().begins_with("_")) { BUTTON_SET_ICON(status_btn, theme_cache.var_private_icon); status_btn->set_tooltip_text(TTR("This variable is private and is not included in the blackboard plan.\nClick to open the blackboard plan.")); @@ -86,7 +112,9 @@ void EditorPropertyVariableName::_update_status() { void EditorPropertyVariableName::_status_pressed() { ERR_FAIL_NULL(plan); if (!plan->has_var(name_edit->get_text())) { - BlackboardPlanEditor::get_singleton()->set_next_var_name(name_edit->get_text()); + BlackboardPlanEditor::get_singleton()->set_defaults(name_edit->get_text(), + expected_type == Variant::NIL ? Variant::FLOAT : expected_type, + default_hint, default_hint_string, default_value); } BlackboardPlanEditor::get_singleton()->edit_plan(plan); BlackboardPlanEditor::get_singleton()->popup_centered(); @@ -110,17 +138,27 @@ void EditorPropertyVariableName::update_property() { void EditorPropertyVariableName::_update_property() { #endif // LIMBOAI_GDEXTENSION String s = get_edited_object()->get(get_edited_property()); + updating = true; if (name_edit->get_text() != s) { int caret = name_edit->get_caret_column(); + if (caret == 0) { + caret = last_caret_column; + } name_edit->set_text(s); name_edit->set_caret_column(caret); } name_edit->set_editable(!is_read_only()); _update_status(); + updating = false; } -void EditorPropertyVariableName::setup(const Ref &p_plan) { +void EditorPropertyVariableName::setup(const Ref &p_plan, bool p_allow_empty, Variant::Type p_type, PropertyHint p_hint, String p_hint_string, Variant p_default_value) { plan = p_plan; + allow_empty = p_allow_empty; + expected_type = p_type; + default_hint = p_hint; + default_hint_string = p_hint_string; + default_value = p_default_value; _update_status(); } @@ -128,6 +166,8 @@ void EditorPropertyVariableName::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { name_edit->connect(LW_NAME(text_changed), callable_mp(this, &EditorPropertyVariableName::_name_changed)); + name_edit->connect(LW_NAME(text_submitted), callable_mp(this, &EditorPropertyVariableName::_name_submitted).unbind(1)); + name_edit->connect(LW_NAME(focus_exited), callable_mp(this, &EditorPropertyVariableName::_name_submitted)); variables_popup->connect(LW_NAME(id_pressed), callable_mp(this, &EditorPropertyVariableName::_variable_selected)); drop_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_show_variables_popup)); status_btn->connect(LW_NAME(pressed), callable_mp(this, &EditorPropertyVariableName::_status_pressed)); @@ -148,6 +188,8 @@ void EditorPropertyVariableName::_notification(int p_what) { theme_cache.var_exists_icon = LimboUtility::get_singleton()->get_task_icon(LW_NAME(LimboVarExists)); theme_cache.var_not_found_icon = LimboUtility::get_singleton()->get_task_icon(LW_NAME(LimboVarNotFound)); theme_cache.var_private_icon = LimboUtility::get_singleton()->get_task_icon(LW_NAME(LimboVarPrivate)); + theme_cache.var_empty_icon = LimboUtility::get_singleton()->get_task_icon(LW_NAME(LimboVarEmpty)); + theme_cache.var_error_icon = LimboUtility::get_singleton()->get_task_icon(LW_NAME(LimboVarError)); } break; } } @@ -192,6 +234,10 @@ bool EditorInspectorPluginVariableName::_can_handle(Object *p_object) const { if (param.is_valid()) { return true; } + Ref plan = Object::cast_to(p_object); + if (plan.is_valid()) { + return true; + } return false; } @@ -200,13 +246,41 @@ bool EditorInspectorPluginVariableName::parse_property(Object *p_object, const V #elif LIMBOAI_GDEXTENSION bool EditorInspectorPluginVariableName::_parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField p_usage, const bool p_wide) { #endif - if (!(p_type == Variant::Type::STRING_NAME || p_type == Variant::Type::STRING) || !(p_path.ends_with("_var") || p_path.ends_with("variable"))) { + bool is_mapping = p_path.begins_with("mapping/"); + if (!(p_type == Variant::Type::STRING_NAME || p_type == Variant::Type::STRING) || !(is_mapping || p_path.ends_with("_var") || p_path.ends_with("variable"))) { return false; } + Ref plan; + Variant::Type expected_type = Variant::NIL; + PropertyHint default_hint = PROPERTY_HINT_NONE; + String default_hint_string; + Variant default_value; + if (is_mapping) { + plan.reference_ptr(Object::cast_to(p_object)); + ERR_FAIL_NULL_V(plan, false); + String var_name = p_path.trim_prefix("mapping/"); + if (plan->has_var(var_name)) { + BBVariable variable = plan->get_var(var_name); + expected_type = variable.get_type(); + default_hint = variable.get_hint(); + default_hint_string = variable.get_hint_string(); + default_value = variable.get_value(); + } + if (plan->get_parent_scope_plan_provider().is_valid()) { + Ref parent_plan = plan->get_parent_scope_plan_provider().call(); + if (parent_plan.is_valid()) { + plan = parent_plan; + } + } + ERR_FAIL_NULL_V(plan, false); + } else { + plan = editor_plan_provider.call(); + } + EditorPropertyVariableName *ed = memnew(EditorPropertyVariableName); - ed->setup(plan_getter.call()); - add_property_editor(p_path, ed); + ed->setup(plan, is_mapping, expected_type, default_hint, default_hint_string, default_value); + add_property_editor(p_path, ed, expected_type); return true; } diff --git a/editor/editor_property_variable_name.h b/editor/editor_property_variable_name.h index 19cbe31..bff47a9 100644 --- a/editor/editor_property_variable_name.h +++ b/editor/editor_property_variable_name.h @@ -31,17 +31,30 @@ using namespace godot; class EditorPropertyVariableName : public EditorProperty { GDCLASS(EditorPropertyVariableName, EditorProperty); +private: + static int last_caret_column; + private: struct ThemeCache { + Ref var_add_icon; + Ref var_empty_icon; + Ref var_error_icon; Ref var_exists_icon; Ref var_not_found_icon; - Ref var_add_icon; Ref var_private_icon; }; ThemeCache theme_cache; Ref plan; + bool allow_empty = false; + Variant::Type expected_type = Variant::NIL; + PropertyHint default_hint = PROPERTY_HINT_NONE; + String default_hint_string; + Variant default_value; + + bool updating = false; + LineEdit *name_edit; Button *drop_btn; Button *status_btn; @@ -49,6 +62,7 @@ private: void _show_variables_popup(); void _name_changed(const String &p_new_name); + void _name_submitted(); void _variable_selected(int p_id); void _update_status(); @@ -68,7 +82,7 @@ public: virtual void _update_property() override; #endif - void setup(const Ref &p_plan); + void setup(const Ref &p_plan, bool p_allow_empty, Variant::Type p_type = Variant::NIL, PropertyHint p_hint = PROPERTY_HINT_NONE, String p_hint_string = "", Variant p_default_value = Variant()); EditorPropertyVariableName(); }; @@ -76,7 +90,7 @@ class EditorInspectorPluginVariableName : public EditorInspectorPlugin { GDCLASS(EditorInspectorPluginVariableName, EditorInspectorPlugin); private: - Callable plan_getter; + Callable editor_plan_provider; protected: static void _bind_methods() {} @@ -90,7 +104,7 @@ public: virtual bool _parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField p_usage, const bool p_wide = false) override; #endif - void set_plan_getter(const Callable &p_getter) { plan_getter = p_getter; } + void set_editor_plan_provider(const Callable &p_getter) { editor_plan_provider = p_getter; } EditorInspectorPluginVariableName() = default; }; diff --git a/editor/limbo_ai_editor_plugin.cpp b/editor/limbo_ai_editor_plugin.cpp index 82df889..09c91a0 100644 --- a/editor/limbo_ai_editor_plugin.cpp +++ b/editor/limbo_ai_editor_plugin.cpp @@ -1486,7 +1486,7 @@ void LimboAIEditorPlugin::_notification(int p_notification) { add_debugger_plugin(memnew(LimboDebuggerPlugin)); add_inspector_plugin(memnew(EditorInspectorPluginBBPlan)); EditorInspectorPluginVariableName *var_plugin = memnew(EditorInspectorPluginVariableName); - var_plugin->set_plan_getter(Callable(limbo_ai_editor, "get_edited_blackboard_plan")); + var_plugin->set_editor_plan_provider(Callable(limbo_ai_editor, "get_edited_blackboard_plan")); add_inspector_plugin(var_plugin); #ifdef LIMBOAI_MODULE // ! Only used in the module version. diff --git a/hsm/limbo_state.cpp b/hsm/limbo_state.cpp index 77554bb..f704dc1 100644 --- a/hsm/limbo_state.cpp +++ b/hsm/limbo_state.cpp @@ -22,12 +22,31 @@ void LimboState::set_blackboard_plan(const Ref &p_plan) { blackboard_plan = p_plan; + + if (Engine::get_singleton()->is_editor_hint() && blackboard_plan.is_valid()) { + blackboard_plan->set_parent_scope_plan_provider(callable_mp(this, &LimboState::_get_parent_scope_plan)); + } + _update_blackboard_plan(); } void LimboState::_update_blackboard_plan() { } +Ref LimboState::_get_parent_scope_plan() const { + BlackboardPlan *parent_plan = nullptr; + const LimboState *state = this; + while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) { + state = Object::cast_to(state->get_parent()); + ERR_FAIL_NULL_V(state, parent_plan); + if (state->blackboard_plan.is_valid()) { + parent_plan = state->blackboard_plan.ptr(); + break; + } + } + return parent_plan; +} + LimboState *LimboState::get_root() const { const Node *state = this; while (state->get_parent() && IS_CLASS(state->get_parent(), LimboState)) { diff --git a/hsm/limbo_state.h b/hsm/limbo_state.h index 69bc2cf..a4d9b00 100644 --- a/hsm/limbo_state.h +++ b/hsm/limbo_state.h @@ -38,6 +38,8 @@ private: HashMap handlers; Callable guard_callable; + Ref _get_parent_scope_plan() const; + protected: friend LimboHSM; diff --git a/icons/LimboVarEmpty.svg b/icons/LimboVarEmpty.svg new file mode 100644 index 0000000..24f5088 --- /dev/null +++ b/icons/LimboVarEmpty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/LimboVarError.svg b/icons/LimboVarError.svg new file mode 100644 index 0000000..563d762 --- /dev/null +++ b/icons/LimboVarError.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/util/limbo_string_names.cpp b/util/limbo_string_names.cpp index a223ded..be1b6f7 100644 --- a/util/limbo_string_names.cpp +++ b/util/limbo_string_names.cpp @@ -85,6 +85,7 @@ LimboStringNames::LimboStringNames() { exited = SN("exited"); favorite_tasks_changed = SN("favorite_tasks_changed"); Favorites = SN("Favorites"); + focus_exited = SN("focus_exited"); font = SN("font"); font_color = SN("font_color"); font_size = SN("font_size"); @@ -105,6 +106,8 @@ LimboStringNames::LimboStringNames() { LimboPercent = SN("LimboPercent"); LimboSelectAll = SN("LimboSelectAll"); LimboVarAdd = SN("LimboVarAdd"); + LimboVarEmpty = SN("LimboVarEmpty"); + LimboVarError = SN("LimboVarError"); LimboVarExists = SN("LimboVarExists"); LimboVarNotFound = SN("LimboVarNotFound"); LimboVarPrivate = SN("LimboVarPrivate"); diff --git a/util/limbo_string_names.h b/util/limbo_string_names.h index 10e6542..6a7c148 100644 --- a/util/limbo_string_names.h +++ b/util/limbo_string_names.h @@ -101,6 +101,7 @@ public: StringName exited; StringName favorite_tasks_changed; StringName Favorites; + StringName focus_exited; StringName font_color; StringName font_size; StringName font; @@ -122,6 +123,8 @@ public: StringName LimboPercent; StringName LimboSelectAll; StringName LimboVarAdd; + StringName LimboVarEmpty; + StringName LimboVarError; StringName LimboVarExists; StringName LimboVarNotFound; StringName LimboVarPrivate;