diff options
author | reduz <reduzio@gmail.com> | 2022-03-23 21:08:54 +0100 |
---|---|---|
committer | reduz <reduzio@gmail.com> | 2022-03-24 14:21:52 +0100 |
commit | 09b951b99b1a8e799b00adaa896c788949c18017 (patch) | |
tree | 4a81fb9584b90063c651758ba53b16462083fe66 /core/object | |
parent | d7d528c15f0e858b52bb0f510ff47e65c2341de1 (diff) |
Refactor Object metadata
* API kept the same (Although functions could be renamed to set_metadata/get_metadata in a later PR), so not much should change.
* Metadata now exposed as individual properties.
* Properties are editable in inspector (unless metadata name begins with _) under the metadata/ namespace.
* Added the ability to Add/Remove metadata properties to the inspector.
This is a functionality that was requested very often, that makes metadata work a bit more similar to custom properties in Blender.
Diffstat (limited to 'core/object')
-rw-r--r-- | core/object/object.cpp | 70 | ||||
-rw-r--r-- | core/object/object.h | 4 |
2 files changed, 52 insertions, 22 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp index 096edd4e60..226d3ef0b8 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -416,12 +416,22 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid } return; - } else if (p_name == CoreStringNames::get_singleton()->_meta) { - metadata = p_value.duplicate(); - if (r_valid) { - *r_valid = true; + } else { + OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); + if (E) { + E->get() = p_value; + if (r_valid) { + *r_valid = true; + } + return; + } else if (p_name.operator String().begins_with("metadata/")) { + // Must exist, otherwise duplicate() will not work. + set_meta(p_name.operator String().replace_first("metadata/", ""), p_value); + if (r_valid) { + *r_valid = true; + } + return; } - return; } // Something inside the object... :| @@ -496,9 +506,12 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { *r_valid = true; } return ret; + } + + const OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); - } else if (p_name == CoreStringNames::get_singleton()->_meta) { - ret = metadata; + if (E) { + ret = E->get(); if (r_valid) { *r_valid = true; } @@ -648,13 +661,20 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons if (!is_class("Script")) { // can still be set, but this is for user-friendliness p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } - if (!metadata.is_empty()) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); - } + if (script_instance && !p_reversed) { p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); } + + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + PropertyInfo pi = PropertyInfo(K.value().get_type(), "metadata/" + K.key().operator String()); + if (K.value().get_type() == Variant::OBJECT) { + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Resource"; + } + p_list->push_back(pi); + } } void Object::_validate_property(PropertyInfo &property) const { @@ -915,11 +935,23 @@ bool Object::has_meta(const StringName &p_name) const { void Object::set_meta(const StringName &p_name, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { - metadata.erase(p_name); + if (metadata.has(p_name)) { + metadata.erase(p_name); + metadata_properties.erase("metadata/" + p_name.operator String()); + notify_property_list_changed(); + } return; } - metadata[p_name] = p_value; + OrderedHashMap<StringName, Variant>::Element E = metadata.find(p_name); + if (E) { + E.value() = p_value; + } else { + ERR_FAIL_COND(!p_name.operator String().is_valid_identifier()); + E = metadata.insert(p_name, p_value); + metadata_properties["metadata/" + p_name.operator String()] = E; + notify_property_list_changed(); + } } Variant Object::get_meta(const StringName &p_name) const { @@ -928,7 +960,7 @@ Variant Object::get_meta(const StringName &p_name) const { } void Object::remove_meta(const StringName &p_name) { - metadata.erase(p_name); + set_meta(p_name, Variant()); } Array Object::_get_property_list_bind() const { @@ -954,20 +986,16 @@ Array Object::_get_method_list_bind() const { Vector<StringName> Object::_get_meta_list_bind() const { Vector<StringName> _metaret; - List<Variant> keys; - metadata.get_key_list(&keys); - for (const Variant &E : keys) { - _metaret.push_back(E); + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + _metaret.push_back(K.key()); } return _metaret; } void Object::get_meta_list(List<StringName> *p_list) const { - List<Variant> keys; - metadata.get_key_list(&keys); - for (const Variant &E : keys) { - p_list->push_back(E); + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + p_list->push_back(K.key()); } } diff --git a/core/object/object.h b/core/object/object.h index 6b4f1c81e6..41365cfe51 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -39,6 +39,7 @@ #include "core/templates/hash_map.h" #include "core/templates/list.h" #include "core/templates/map.h" +#include "core/templates/ordered_hash_map.h" #include "core/templates/safe_refcount.h" #include "core/templates/set.h" #include "core/templates/vmap.h" @@ -530,7 +531,8 @@ private: #endif ScriptInstance *script_instance = nullptr; Variant script; // Reference does not exist yet, store it in a Variant. - Dictionary metadata; + OrderedHashMap<StringName, Variant> metadata; + HashMap<StringName, OrderedHashMap<StringName, Variant>::Element> metadata_properties; mutable StringName _class_name; mutable const StringName *_class_ptr = nullptr; |