2024-01-23 09:33:57 +00:00
|
|
|
/**
|
2024-01-23 19:02:23 +00:00
|
|
|
* blackboard_plan.cpp
|
2024-01-23 09:33:57 +00:00
|
|
|
* =============================================================================
|
|
|
|
* Copyright 2021-2024 Serhii Snitsaruk
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style
|
|
|
|
* license that can be found in the LICENSE file or at
|
|
|
|
* https://opensource.org/licenses/MIT.
|
|
|
|
* =============================================================================
|
|
|
|
*/
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
#include "blackboard_plan.h"
|
2024-01-23 09:33:57 +00:00
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
bool BlackboardPlan::_set(const StringName &p_name, const Variant &p_value) {
|
2024-01-23 14:31:56 +00:00
|
|
|
String prop_name = p_name;
|
|
|
|
|
|
|
|
// * Editor
|
|
|
|
if (data.has(prop_name)) {
|
|
|
|
data[prop_name].set_value(p_value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// * Storage
|
|
|
|
if (prop_name.begins_with("var/")) {
|
|
|
|
String var_name = prop_name.get_slicec('/', 1);
|
|
|
|
String what = prop_name.get_slicec('/', 2);
|
|
|
|
if (!data.has(var_name) && what == "name") {
|
|
|
|
data.insert(var_name, BBVariable());
|
|
|
|
}
|
|
|
|
if (what == "name") {
|
|
|
|
// We don't store variable name with the variable.
|
|
|
|
} else if (what == "type") {
|
|
|
|
data[var_name].set_type((Variant::Type)(int)p_value);
|
|
|
|
} else if (what == "value") {
|
|
|
|
data[var_name].set_value(p_value);
|
|
|
|
} else if (what == "hint") {
|
|
|
|
data[var_name].set_hint((PropertyHint)(int)p_value);
|
|
|
|
} else if (what == "hint_string") {
|
|
|
|
data[var_name].set_hint_string(p_value);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
bool BlackboardPlan::_get(const StringName &p_name, Variant &r_ret) const {
|
2024-01-23 14:31:56 +00:00
|
|
|
String prop_name = p_name;
|
|
|
|
|
|
|
|
// * Editor
|
|
|
|
if (data.has(prop_name)) {
|
|
|
|
r_ret = data[prop_name].get_value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// * Storage
|
|
|
|
if (!prop_name.begins_with("var/")) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
String var_name = prop_name.get_slicec('/', 1);
|
|
|
|
String what = prop_name.get_slicec('/', 2);
|
|
|
|
ERR_FAIL_COND_V(!data.has(var_name), false);
|
|
|
|
if (what == "type") {
|
|
|
|
r_ret = data[var_name].get_type();
|
|
|
|
} else if (what == "value") {
|
|
|
|
r_ret = data[var_name].get_value();
|
|
|
|
} else if (what == "hint") {
|
|
|
|
r_ret = data[var_name].get_hint();
|
|
|
|
} else if (what == "hint_string") {
|
|
|
|
r_ret = data[var_name].get_hint_string();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::_get_property_list(List<PropertyInfo> *p_list) const {
|
2024-01-23 14:31:56 +00:00
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
String var_name = kv.key;
|
|
|
|
BBVariable var = kv.value;
|
|
|
|
|
|
|
|
// * Editor
|
|
|
|
p_list->push_back(PropertyInfo(var.get_type(), var_name, var.get_hint(), var.get_hint_string(), PROPERTY_USAGE_EDITOR));
|
|
|
|
|
|
|
|
// * 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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
bool BlackboardPlan::_property_can_revert(const StringName &p_name) const {
|
2024-01-23 16:54:20 +00:00
|
|
|
return base.is_valid() && base->data.has(p_name);
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
bool BlackboardPlan::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
2024-01-23 16:54:20 +00:00
|
|
|
if (base->data.has(p_name)) {
|
|
|
|
r_property = base->data[p_name].get_value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::set_base_plan(const Ref<BlackboardPlan> &p_base) {
|
2024-01-23 14:31:56 +00:00
|
|
|
base = p_base;
|
2024-01-23 19:02:23 +00:00
|
|
|
sync_with_base_plan();
|
2024-01-23 14:31:56 +00:00
|
|
|
emit_changed();
|
2024-01-24 22:11:09 +00:00
|
|
|
notify_property_list_changed();
|
2024-01-23 14:31:56 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::set_value(const String &p_name, const Variant &p_value) {
|
2024-01-23 11:05:54 +00:00
|
|
|
ERR_FAIL_COND(!data.has(p_name));
|
|
|
|
data.get(p_name).set_value(p_value);
|
2024-01-24 22:11:09 +00:00
|
|
|
emit_changed();
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
Variant BlackboardPlan::get_value(const String &p_name) const {
|
2024-01-23 11:05:54 +00:00
|
|
|
ERR_FAIL_COND_V(!data.has(p_name), Variant());
|
|
|
|
return data.get(p_name).get_value();
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::add_var(const String &p_name, const BBVariable &p_var) {
|
2024-01-23 11:05:54 +00:00
|
|
|
ERR_FAIL_COND(data.has(p_name));
|
2024-01-23 09:33:57 +00:00
|
|
|
ERR_FAIL_COND(base.is_valid());
|
2024-01-23 11:05:54 +00:00
|
|
|
data.insert(p_name, p_var);
|
2024-01-24 22:11:09 +00:00
|
|
|
notify_property_list_changed();
|
|
|
|
emit_changed();
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::remove_var(const String &p_name) {
|
2024-01-23 11:05:54 +00:00
|
|
|
ERR_FAIL_COND(!data.has(p_name));
|
2024-01-23 09:33:57 +00:00
|
|
|
ERR_FAIL_COND(base.is_valid());
|
2024-01-23 11:05:54 +00:00
|
|
|
data.erase(p_name);
|
2024-01-24 22:11:09 +00:00
|
|
|
notify_property_list_changed();
|
|
|
|
emit_changed();
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
BBVariable BlackboardPlan::get_var(const String &p_name) {
|
2024-01-23 11:05:54 +00:00
|
|
|
ERR_FAIL_COND_V(!data.has(p_name), BBVariable());
|
|
|
|
return data.get(p_name);
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-24 22:11:09 +00:00
|
|
|
Pair<String, BBVariable> BlackboardPlan::get_var_by_index(int p_index) {
|
|
|
|
Pair<String, BBVariable> ret;
|
|
|
|
ERR_FAIL_INDEX_V(p_index, (int)data.size(), ret);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
if (i == p_index) {
|
|
|
|
ret.first = kv.key;
|
|
|
|
ret.second = kv.value;
|
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
PackedStringArray BlackboardPlan::list_vars() const {
|
2024-01-23 09:33:57 +00:00
|
|
|
PackedStringArray ret;
|
2024-01-23 11:05:54 +00:00
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
2024-01-23 09:33:57 +00:00
|
|
|
ret.append(kv.key);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-01-24 22:11:09 +00:00
|
|
|
String BlackboardPlan::get_var_name(const BBVariable &p_var) const {
|
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
if (kv.value == p_var) {
|
|
|
|
return kv.key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return String();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlackboardPlan::rename_var(const String &p_name, const String &p_new_name) {
|
|
|
|
ERR_FAIL_COND(p_new_name.is_empty());
|
|
|
|
ERR_FAIL_COND(data.has(p_new_name));
|
|
|
|
ERR_FAIL_COND(!data.has(p_name));
|
|
|
|
|
|
|
|
data.replace_key(p_name, p_new_name);
|
|
|
|
notify_property_list_changed();
|
|
|
|
emit_changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlackboardPlan::swap_vars(int p_idx_a, int p_idx_b) {
|
|
|
|
ERR_FAIL_INDEX(p_idx_a, (int)data.size());
|
|
|
|
ERR_FAIL_INDEX(p_idx_b, (int)data.size());
|
|
|
|
|
|
|
|
Pair<String, BBVariable> a = get_var_by_index(p_idx_a);
|
|
|
|
Pair<String, BBVariable> b = get_var_by_index(p_idx_b);
|
|
|
|
|
|
|
|
data.replace_key(a.first, "__tmp__");
|
|
|
|
data.replace_key(b.first, a.first);
|
|
|
|
data.replace_key("__tmp__", b.first);
|
|
|
|
|
|
|
|
data[b.first] = b.second;
|
|
|
|
data[a.first] = a.second;
|
|
|
|
|
|
|
|
notify_property_list_changed();
|
|
|
|
emit_changed();
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::sync_with_base_plan() {
|
2024-01-23 16:54:20 +00:00
|
|
|
if (base.is_null()) {
|
|
|
|
return;
|
|
|
|
}
|
2024-01-23 19:02:23 +00:00
|
|
|
|
2024-01-24 22:11:09 +00:00
|
|
|
bool changed = false;
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
// Sync variables with the base plan.
|
2024-01-23 11:05:54 +00:00
|
|
|
for (const KeyValue<String, BBVariable> &kv : base->data) {
|
|
|
|
if (!data.has(kv.key)) {
|
|
|
|
data.insert(kv.key, kv.value.duplicate());
|
2024-01-24 22:11:09 +00:00
|
|
|
changed = true;
|
2024-01-23 09:33:57 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-01-23 11:05:54 +00:00
|
|
|
BBVariable var = data.get(kv.key);
|
2024-01-23 09:33:57 +00:00
|
|
|
if (!var.is_same_prop_info(kv.value)) {
|
|
|
|
var.copy_prop_info(kv.value);
|
2024-01-24 22:11:09 +00:00
|
|
|
changed = true;
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
if (var.get_value().get_type() != kv.value.get_type()) {
|
|
|
|
var.set_value(kv.value.get_value());
|
2024-01-24 22:11:09 +00:00
|
|
|
changed = true;
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-23 19:02:23 +00:00
|
|
|
|
|
|
|
// Erase variables that do not exist in the base plan.
|
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
if (!base->data.has(kv.key)) {
|
|
|
|
data.erase(kv.key);
|
2024-01-24 22:11:09 +00:00
|
|
|
changed = true;
|
2024-01-23 19:02:23 +00:00
|
|
|
}
|
|
|
|
}
|
2024-01-24 22:11:09 +00:00
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
notify_property_list_changed();
|
|
|
|
emit_changed();
|
|
|
|
}
|
2024-01-23 09:33:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
Ref<Blackboard> BlackboardPlan::create_blackboard() {
|
2024-01-23 09:33:57 +00:00
|
|
|
Ref<Blackboard> bb = memnew(Blackboard);
|
2024-01-23 11:05:54 +00:00
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
bb->add_var(kv.key, kv.value.duplicate());
|
|
|
|
}
|
2024-01-23 09:33:57 +00:00
|
|
|
return bb;
|
|
|
|
}
|
2024-01-23 11:05:54 +00:00
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite) {
|
2024-01-23 11:05:54 +00:00
|
|
|
for (const KeyValue<String, BBVariable> &kv : data) {
|
|
|
|
if (p_blackboard->has_var(kv.key)) {
|
|
|
|
if (overwrite) {
|
|
|
|
p_blackboard->erase_var(kv.key);
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p_blackboard->add_var(kv.key, kv.value.duplicate());
|
|
|
|
}
|
|
|
|
}
|
2024-01-23 14:31:56 +00:00
|
|
|
|
2024-01-23 19:02:23 +00:00
|
|
|
BlackboardPlan::BlackboardPlan() {
|
2024-01-23 14:31:56 +00:00
|
|
|
}
|