Parsing BlackboardSource properties
This commit is contained in:
parent
a247d0d67b
commit
8c67886b52
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "bb_variable.h"
|
||||
|
||||
#include "../util/limbo_compat.h"
|
||||
|
||||
void BBVariable::unref() {
|
||||
if (data && data->refcount.unref()) {
|
||||
memdelete(data);
|
||||
|
@ -36,6 +38,7 @@ Variant BBVariable::get_value() const {
|
|||
|
||||
void BBVariable::set_type(Variant::Type p_type) {
|
||||
data->type = p_type;
|
||||
data->value = VARIANT_DEFAULT(p_type);
|
||||
}
|
||||
|
||||
Variant::Type BBVariable::get_type() const {
|
||||
|
@ -136,9 +139,13 @@ BBVariable::BBVariable(const BBVariable &p_var) {
|
|||
}
|
||||
}
|
||||
|
||||
BBVariable::BBVariable() {
|
||||
BBVariable::BBVariable(Variant::Type p_type, PropertyHint p_hint, const String &p_hint_string) {
|
||||
data = memnew(Data);
|
||||
data->refcount.init();
|
||||
|
||||
set_type(p_type);
|
||||
data->hint = p_hint;
|
||||
data->hint_string = p_hint_string;
|
||||
}
|
||||
|
||||
BBVariable::~BBVariable() {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "core/object/object.h"
|
||||
#include "core/templates/safe_refcount.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
class BBVariable {
|
||||
private:
|
||||
|
@ -60,7 +61,7 @@ public:
|
|||
void operator=(const BBVariable &p_var);
|
||||
|
||||
BBVariable(const BBVariable &p_var);
|
||||
BBVariable();
|
||||
BBVariable(Variant::Type p_type = Variant::Type::NIL, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "");
|
||||
~BBVariable();
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,93 @@
|
|||
|
||||
#include "blackboard_source.h"
|
||||
|
||||
bool BlackboardSource::_set(const StringName &p_name, const Variant &p_value) {
|
||||
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;
|
||||
}
|
||||
|
||||
bool BlackboardSource::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
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;
|
||||
}
|
||||
|
||||
void BlackboardSource::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void BlackboardSource::set_base_source(const Ref<BlackboardSource> &p_base) {
|
||||
base = p_base;
|
||||
sync_base();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void BlackboardSource::set_value(const String &p_name, const Variant &p_value) {
|
||||
ERR_FAIL_COND(!data.has(p_name));
|
||||
data.get(p_name).set_value(p_value);
|
||||
|
@ -83,3 +170,10 @@ void BlackboardSource::populate_blackboard(const Ref<Blackboard> &p_blackboard,
|
|||
p_blackboard->add_var(kv.key, kv.value.duplicate());
|
||||
}
|
||||
}
|
||||
|
||||
BlackboardSource::BlackboardSource() {
|
||||
// TODO: REMOVE ALL BELOW
|
||||
data.insert("speed", BBVariable(Variant::Type::FLOAT, PropertyHint::PROPERTY_HINT_NONE, ""));
|
||||
data.insert("limit_speed", BBVariable(Variant::Type::BOOL, PropertyHint::PROPERTY_HINT_NONE, ""));
|
||||
data.insert("about", BBVariable(Variant::Type::STRING, PropertyHint::PROPERTY_HINT_MULTILINE_TEXT, ""));
|
||||
}
|
||||
|
|
|
@ -25,7 +25,15 @@ private:
|
|||
Ref<BlackboardSource> base;
|
||||
// HashMap<String, BBVariable> overrides;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
void set_base_source(const Ref<BlackboardSource> &p_base);
|
||||
Ref<BlackboardSource> get_base_source() const { return base; }
|
||||
|
||||
void set_value(const String &p_name, const Variant &p_value);
|
||||
Variant get_value(const String &p_name) const;
|
||||
void add_var(const String &p_name, const BBVariable &p_var);
|
||||
|
@ -38,7 +46,7 @@ public:
|
|||
Ref<Blackboard> create_blackboard();
|
||||
void populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite);
|
||||
|
||||
BlackboardSource() = default;
|
||||
BlackboardSource();
|
||||
};
|
||||
|
||||
#endif // BLACKBOARD_SOURCE_H
|
||||
|
|
|
@ -47,6 +47,8 @@ Ref<BTTask> BehaviorTree::instantiate(Node *p_agent, const Ref<Blackboard> &p_bl
|
|||
void BehaviorTree::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_description", "p_value"), &BehaviorTree::set_description);
|
||||
ClassDB::bind_method(D_METHOD("get_description"), &BehaviorTree::get_description);
|
||||
ClassDB::bind_method(D_METHOD("set_blackboard_source", "p_source"), &BehaviorTree::set_blackboard_source);
|
||||
ClassDB::bind_method(D_METHOD("get_blackboard_source"), &BehaviorTree::get_blackboard_source);
|
||||
ClassDB::bind_method(D_METHOD("set_root_task", "p_value"), &BehaviorTree::set_root_task);
|
||||
ClassDB::bind_method(D_METHOD("get_root_task"), &BehaviorTree::get_root_task);
|
||||
ClassDB::bind_method(D_METHOD("clone"), &BehaviorTree::clone);
|
||||
|
@ -55,4 +57,9 @@ void BehaviorTree::_bind_methods() {
|
|||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description", PROPERTY_HINT_MULTILINE_TEXT), "set_description", "get_description");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_task", PROPERTY_HINT_RESOURCE_TYPE, "BTTask", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_root_task", "get_root_task");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_source", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardSource", PROPERTY_USAGE_DEFAULT), "set_blackboard_source", "get_blackboard_source");
|
||||
}
|
||||
|
||||
BehaviorTree::BehaviorTree() {
|
||||
blackboard_source = Ref<BlackboardSource>(memnew(BlackboardSource));
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
#ifndef BEHAVIOR_TREE_H
|
||||
#define BEHAVIOR_TREE_H
|
||||
|
||||
#include "../blackboard/blackboard_source.h"
|
||||
#include "tasks/bt_task.h"
|
||||
|
||||
#ifdef LIMBOAI_MODULE
|
||||
#include "core/io/resource.h"
|
||||
#include "modules/limboai/blackboard/blackboard.h"
|
||||
#endif // LIMBOAI_MODULE
|
||||
|
||||
#ifdef LIMBOAI_GDEXTENSION
|
||||
|
@ -29,6 +29,7 @@ class BehaviorTree : public Resource {
|
|||
|
||||
private:
|
||||
String description;
|
||||
Ref<BlackboardSource> blackboard_source;
|
||||
Ref<BTTask> root_task;
|
||||
|
||||
protected:
|
||||
|
@ -39,6 +40,12 @@ public:
|
|||
virtual bool editor_can_reload_from_file() override { return false; }
|
||||
#endif
|
||||
|
||||
void set_blackboard_source(const Ref<BlackboardSource> &p_source) {
|
||||
blackboard_source = p_source;
|
||||
emit_changed();
|
||||
}
|
||||
Ref<BlackboardSource> get_blackboard_source() const { return blackboard_source; }
|
||||
|
||||
void set_description(String p_value) {
|
||||
description = p_value;
|
||||
emit_changed();
|
||||
|
@ -54,6 +61,8 @@ public:
|
|||
Ref<BehaviorTree> clone() const;
|
||||
void copy_other(const Ref<BehaviorTree> &p_other);
|
||||
Ref<BTTask> instantiate(Node *p_agent, const Ref<Blackboard> &p_blackboard) const;
|
||||
|
||||
BehaviorTree();
|
||||
};
|
||||
|
||||
#endif // BEHAVIOR_TREE_H
|
||||
|
|
|
@ -63,11 +63,33 @@ void BTPlayer::_load_tree() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void BTPlayer::_update_blackboard_source() {
|
||||
if (behavior_tree.is_valid() && behavior_tree->get_blackboard_source().is_valid()) {
|
||||
if (blackboard_source.is_null()) {
|
||||
blackboard_source = Ref<BlackboardSource>(memnew(BlackboardSource));
|
||||
}
|
||||
if (blackboard_source == behavior_tree->get_blackboard_source()) {
|
||||
blackboard_source->sync_base();
|
||||
} else {
|
||||
blackboard_source->set_base_source(behavior_tree->get_blackboard_source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
|
||||
behavior_tree = p_tree;
|
||||
if (Engine::get_singleton()->is_editor_hint() == false && get_owner()) {
|
||||
_load_tree();
|
||||
}
|
||||
_update_blackboard_source();
|
||||
}
|
||||
|
||||
void BTPlayer::set_blackboard_source(const Ref<BlackboardSource> &p_source) {
|
||||
blackboard_source = p_source;
|
||||
if (blackboard_source.is_null()) {
|
||||
blackboard_source = Ref<BlackboardSource>(memnew(BlackboardSource));
|
||||
}
|
||||
_update_blackboard_source();
|
||||
}
|
||||
|
||||
void BTPlayer::set_update_mode(UpdateMode p_mode) {
|
||||
|
|
|
@ -47,6 +47,7 @@ private:
|
|||
Ref<BTTask> tree_instance;
|
||||
|
||||
void _load_tree();
|
||||
void _update_blackboard_source();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -57,7 +58,7 @@ public:
|
|||
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||
|
||||
void set_blackboard_source(const Ref<BlackboardSource> &p_source) { blackboard_source = p_source; }
|
||||
void set_blackboard_source(const Ref<BlackboardSource> &p_source);
|
||||
Ref<BlackboardSource> get_blackboard_source() const { return blackboard_source; }
|
||||
|
||||
void set_update_mode(UpdateMode p_mode);
|
||||
|
|
|
@ -26,6 +26,19 @@
|
|||
#include <godot_cpp/classes/engine_debugger.hpp>
|
||||
#endif // LIMBOAI_GDEXTENSION
|
||||
|
||||
void BTState::_update_blackboard_source() {
|
||||
if (behavior_tree.is_valid() && behavior_tree->get_blackboard_source().is_valid()) {
|
||||
if (get_blackboard_source().is_null()) {
|
||||
set_blackboard_source(Ref<BlackboardSource>(memnew(BlackboardSource)));
|
||||
}
|
||||
if (get_blackboard_source() == behavior_tree->get_blackboard_source()) {
|
||||
get_blackboard_source()->sync_base();
|
||||
} else {
|
||||
get_blackboard_source()->set_base_source(behavior_tree->get_blackboard_source());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTState::_setup() {
|
||||
ERR_FAIL_COND_MSG(behavior_tree.is_null(), "BTState: BehaviorTree is not assigned.");
|
||||
tree_instance = behavior_tree->instantiate(get_agent(), get_blackboard());
|
||||
|
|
|
@ -26,6 +26,8 @@ private:
|
|||
String success_event;
|
||||
String failure_event;
|
||||
|
||||
void _update_blackboard_source();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "blackboard/bb_param/bb_vector4.h"
|
||||
#include "blackboard/bb_param/bb_vector4i.h"
|
||||
#include "blackboard/blackboard.h"
|
||||
#include "blackboard/blackboard_source.h"
|
||||
#include "bt/behavior_tree.h"
|
||||
#include "bt/bt_player.h"
|
||||
#include "bt/bt_state.h"
|
||||
|
@ -133,6 +134,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
|
|||
|
||||
GDREGISTER_CLASS(LimboUtility);
|
||||
GDREGISTER_CLASS(Blackboard);
|
||||
GDREGISTER_CLASS(BlackboardSource);
|
||||
|
||||
GDREGISTER_CLASS(LimboState);
|
||||
GDREGISTER_CLASS(LimboHSM);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "core/io/resource.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/plugins/script_editor_plugin.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
@ -85,6 +86,128 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
|
|||
|
||||
// **** Shared
|
||||
|
||||
Variant VARIANT_DEFAULT(Variant::Type p_type) {
|
||||
switch (p_type) {
|
||||
case Variant::Type::NIL: {
|
||||
return Variant();
|
||||
} break;
|
||||
case Variant::Type::BOOL: {
|
||||
return Variant(false);
|
||||
} break;
|
||||
case Variant::Type::INT: {
|
||||
return Variant(0);
|
||||
} break;
|
||||
case Variant::Type::FLOAT: {
|
||||
return Variant(0.0);
|
||||
} break;
|
||||
case Variant::Type::STRING: {
|
||||
return Variant("");
|
||||
} break;
|
||||
case Variant::Type::VECTOR2: {
|
||||
return Variant(Vector2());
|
||||
} break;
|
||||
case Variant::Type::VECTOR2I: {
|
||||
return Variant(Vector2i());
|
||||
} break;
|
||||
case Variant::Type::RECT2: {
|
||||
return Variant(Rect2());
|
||||
} break;
|
||||
case Variant::Type::RECT2I: {
|
||||
return Variant(Rect2i());
|
||||
} break;
|
||||
case Variant::Type::VECTOR3: {
|
||||
return Variant(Vector3());
|
||||
} break;
|
||||
case Variant::Type::VECTOR3I: {
|
||||
return Variant(Vector3i());
|
||||
} break;
|
||||
case Variant::Type::TRANSFORM2D: {
|
||||
return Variant(Transform2D());
|
||||
} break;
|
||||
case Variant::Type::VECTOR4: {
|
||||
return Variant(Vector4());
|
||||
} break;
|
||||
case Variant::Type::VECTOR4I: {
|
||||
return Variant(Vector4i());
|
||||
} break;
|
||||
case Variant::Type::PLANE: {
|
||||
return Variant(Plane());
|
||||
} break;
|
||||
case Variant::Type::QUATERNION: {
|
||||
return Variant(Quaternion());
|
||||
} break;
|
||||
case Variant::Type::AABB: {
|
||||
return Variant(AABB());
|
||||
} break;
|
||||
case Variant::Type::BASIS: {
|
||||
return Variant(Basis());
|
||||
} break;
|
||||
case Variant::Type::TRANSFORM3D: {
|
||||
return Variant(Transform3D());
|
||||
} break;
|
||||
case Variant::Type::PROJECTION: {
|
||||
return Variant(Projection());
|
||||
} break;
|
||||
case Variant::Type::COLOR: {
|
||||
return Variant(Color());
|
||||
} break;
|
||||
case Variant::Type::STRING_NAME: {
|
||||
return Variant(StringName());
|
||||
} break;
|
||||
case Variant::Type::NODE_PATH: {
|
||||
return Variant(NodePath());
|
||||
} break;
|
||||
case Variant::Type::RID: {
|
||||
return Variant(RID());
|
||||
} break;
|
||||
case Variant::Type::OBJECT: {
|
||||
return Variant();
|
||||
} break;
|
||||
case Variant::Type::CALLABLE: {
|
||||
return Variant();
|
||||
} break;
|
||||
case Variant::Type::SIGNAL: {
|
||||
return Variant();
|
||||
} break;
|
||||
case Variant::Type::DICTIONARY: {
|
||||
return Variant(Dictionary());
|
||||
} break;
|
||||
case Variant::Type::ARRAY: {
|
||||
return Variant(Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_BYTE_ARRAY: {
|
||||
return Variant(PackedByteArray());
|
||||
} break;
|
||||
case Variant::Type::PACKED_INT32_ARRAY: {
|
||||
return Variant(PackedInt32Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_INT64_ARRAY: {
|
||||
return Variant(PackedInt64Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_FLOAT32_ARRAY: {
|
||||
return Variant(PackedFloat32Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_FLOAT64_ARRAY: {
|
||||
return Variant(PackedFloat64Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_STRING_ARRAY: {
|
||||
return Variant(PackedStringArray());
|
||||
} break;
|
||||
case Variant::Type::PACKED_VECTOR2_ARRAY: {
|
||||
return Variant(PackedVector2Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_VECTOR3_ARRAY: {
|
||||
return Variant(PackedVector3Array());
|
||||
} break;
|
||||
case Variant::Type::PACKED_COLOR_ARRAY: {
|
||||
return Variant(PackedColorArray());
|
||||
} break;
|
||||
default: {
|
||||
return Variant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
void SHOW_DOC(const String &p_topic) {
|
||||
|
|
|
@ -218,6 +218,8 @@ inline void VARIANT_DELETE_IF_OBJECT(Variant m_variant) {
|
|||
}
|
||||
}
|
||||
|
||||
Variant VARIANT_DEFAULT(Variant::Type p_type);
|
||||
|
||||
#define PROJECT_CONFIG_FILE() GET_PROJECT_SETTINGS_DIR().path_join("limbo_ai.cfg")
|
||||
#define IS_RESOURCE_FILE(m_path) (m_path.begins_with("res://") && m_path.find("::") == -1)
|
||||
#define RESOURCE_TYPE_HINT(m_type) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, m_type)
|
||||
|
|
Loading…
Reference in New Issue