From bdfe5f52c21ea02b32f93092f8ed45fae2c2af57 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 13 May 2024 23:21:55 +0200 Subject: [PATCH] BlackboardPlan: Implement rudimentary mapping --- blackboard/blackboard_plan.cpp | 61 +++++++++++++++++++++++++++++----- blackboard/blackboard_plan.h | 11 +++++- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/blackboard/blackboard_plan.cpp b/blackboard/blackboard_plan.cpp index d55cd03..f9c97ec 100644 --- a/blackboard/blackboard_plan.cpp +++ b/blackboard/blackboard_plan.cpp @@ -24,6 +24,12 @@ bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) { } return true; } + if (name_str.begins_with("_mapping_")) { + StringName mapped_var_name = name_str.trim_prefix("_mapping_"); + ERR_FAIL_COND_V(!has_var(mapped_var_name), false); + parent_scope_mapping[mapped_var_name] = p_value; + return true; + } // * Storage if (name_str.begins_with("var/")) { @@ -56,7 +62,20 @@ 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 $" + parent_scope_mapping[p_name]; + } else { + r_ret = var_map[p_name].get_value(); + } + return true; + } + if (name_str.begins_with("_mapping_")) { + String mapped_var_name = name_str.trim_prefix("_mapping_"); + if (parent_scope_mapping.has(mapped_var_name)) { + r_ret = parent_scope_mapping[mapped_var_name]; + } else { + r_ret = StringName(); + } return true; } @@ -90,22 +109,33 @@ 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_allowed()) { + 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)); + } + } } bool BlackboardPlan::_property_can_revert(const StringName &p_name) const { @@ -131,6 +161,15 @@ 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(); +} + +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(); +} + void BlackboardPlan::set_prefetch_nodepath_vars(bool p_enable) { prefetch_nodepath_vars = p_enable; emit_changed(); @@ -335,12 +374,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, false, p_node); return bb; } @@ -351,6 +389,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); + } + } } } diff --git a/blackboard/blackboard_plan.h b/blackboard/blackboard_plan.h index 83fdd45..6a7d665 100644 --- a/blackboard/blackboard_plan.h +++ b/blackboard/blackboard_plan.h @@ -36,6 +36,11 @@ 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; + bool mapping_allowed = true; + // 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 +57,10 @@ 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; } + bool has_mapping(const StringName &p_name) const; + void set_prefetch_nodepath_vars(bool p_enable); bool is_prefetching_nodepath_vars() const; @@ -72,7 +81,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();