diff options
author | reduz <reduzio@gmail.com> | 2022-06-19 00:42:02 +0200 |
---|---|---|
committer | reduz <reduzio@gmail.com> | 2022-06-25 15:50:15 +0200 |
commit | b7c41f9ba1afe892af465b56cd942b83e1a19b13 (patch) | |
tree | 4704fff413b5593bed54ccc483088e7cb7a357a0 /editor | |
parent | c32285733d4f235249c1031ee64d19b751e4d7df (diff) |
Add ability to export Node pointers as NodePaths
This PR implements:
* A new hint: PROPERTY_HINT_NODE_TYPE for variant type OBJECT, which can take specific node types as hint string.
* The editor will show it as a node path, but will set it as a pointer to a node from the current scene if you select a path.
* When scene is saved, the node path is saved, then restored as a pointer.
NOTE: This is a proof of concept and this approach will most likely not work. The reason if that, if the node referenced is deleted, then when trying to edit this the node will become invalid.
Potential workarounds: Since this uses the Variant API, it should obtain the pointer from the Variant object ID. Yet, this would either only really work in GDScript or it would need to be implemented with workarounds in every language.
Alternative ways to make this work: Nodes could export an additional property with a node path (like for which_node, it could be which_node_path).
Another alternative: Path editing could happen as a hidden metadata (ignoring the pointer).
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_inspector.cpp | 21 | ||||
-rw-r--r-- | editor/editor_inspector.h | 7 | ||||
-rw-r--r-- | editor/editor_properties.cpp | 74 | ||||
-rw-r--r-- | editor/editor_properties.h | 7 |
4 files changed, 83 insertions, 26 deletions
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 0f31e3e7bb..2bf0cd2f20 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -406,7 +406,7 @@ Object *EditorProperty::get_edited_object() { return object; } -StringName EditorProperty::get_edited_property() { +StringName EditorProperty::get_edited_property() const { return property; } @@ -437,16 +437,20 @@ Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const return PropertyUtils::get_property_default_value(p_object, p_property, r_is_valid); } -bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) { +bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property, const Variant *p_custom_current_value) { bool is_valid_revert = false; Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_object, p_property, &is_valid_revert); if (!is_valid_revert) { return false; } - Variant current_value = p_object->get(p_property); + Variant current_value = p_custom_current_value ? *p_custom_current_value : p_object->get(p_property); return PropertyUtils::is_property_value_different(current_value, revert_value); } +StringName EditorProperty::_get_revert_property() const { + return property; +} + void EditorProperty::update_revert_and_pin_status() { if (property == StringName()) { return; //no property, so nothing to do @@ -458,7 +462,8 @@ void EditorProperty::update_revert_and_pin_status() { CRASH_COND(!node); new_pinned = node->is_property_pinned(property); } - bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property) && !is_read_only(); + Variant current = object->get(_get_revert_property()); + bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, ¤t) && !is_read_only(); if (new_can_revert != can_revert || new_pinned != pinned) { can_revert = new_can_revert; @@ -717,11 +722,15 @@ void EditorProperty::set_bottom_editor(Control *p_control) { bottom_editor = p_control; } +Variant EditorProperty::_get_cache_value(const StringName &p_prop, bool &r_valid) const { + return object->get(p_prop, &r_valid); +} + bool EditorProperty::is_cache_valid() const { if (object) { for (const KeyValue<StringName, Variant> &E : cache) { bool valid; - Variant value = object->get(E.key, &valid); + Variant value = _get_cache_value(E.key, valid); if (!valid || value != E.value) { return false; } @@ -733,7 +742,7 @@ void EditorProperty::update_cache() { cache.clear(); if (object && property != StringName()) { bool valid; - Variant value = object->get(property, &valid); + Variant value = _get_cache_value(property, valid); if (valid) { cache[property] = value; } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 555fedf939..d70d06c48b 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -50,7 +50,7 @@ public: static bool is_property_value_different(const Variant &p_a, const Variant &p_b); static Variant get_property_revert_value(Object *p_object, const StringName &p_property, bool *r_is_valid); - static bool can_property_revert(Object *p_object, const StringName &p_property); + static bool can_property_revert(Object *p_object, const StringName &p_property, const Variant *p_custom_current_value = nullptr); }; class EditorProperty : public Container { @@ -131,6 +131,9 @@ protected: virtual void shortcut_input(const Ref<InputEvent> &p_event) override; const Color *_get_property_colors(); + virtual Variant _get_cache_value(const StringName &p_prop, bool &r_valid) const; + virtual StringName _get_revert_property() const; + public: void emit_changed(const StringName &p_property, const Variant &p_value, const StringName &p_field = StringName(), bool p_changing = false); @@ -143,7 +146,7 @@ public: bool is_read_only() const; Object *get_edited_object(); - StringName get_edited_property(); + StringName get_edited_property() const; virtual void update_property(); void update_revert_and_pin_status(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 61b434a240..ed7fac9990 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -43,6 +43,7 @@ #include "scene/main/window.h" #include "scene/resources/font.h" #include "scene/resources/mesh.h" +#include "scene/resources/packed_scene.h" ///////////////////// Nil ///////////////////////// @@ -3017,6 +3018,23 @@ void EditorPropertyNodePath::_set_read_only(bool p_read_only) { clear->set_disabled(p_read_only); }; +String EditorPropertyNodePath::_get_meta_pointer_property() const { + ERR_FAIL_COND_V(!pointer_mode, String()); + return SceneState::get_meta_pointer_property(get_edited_property()); +} + +Variant EditorPropertyNodePath::_get_cache_value(const StringName &p_prop, bool &r_valid) const { + if (p_prop == get_edited_property()) { + r_valid = true; + return const_cast<EditorPropertyNodePath *>(this)->get_edited_object()->get(_get_meta_pointer_property(), &r_valid); + } + return Variant(); +} + +StringName EditorPropertyNodePath::_get_revert_property() const { + return _get_meta_pointer_property(); +} + void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { NodePath path = p_path; Node *base_node = nullptr; @@ -3048,7 +3066,11 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { if (base_node) { // for AnimationTrackKeyEdit path = base_node->get_path().rel_path_to(p_path); } - emit_changed(get_edited_property(), path); + if (pointer_mode && base_node) { + emit_changed(_get_meta_pointer_property(), path); + } else { + emit_changed(get_edited_property(), path); + } update_property(); } @@ -3064,7 +3086,11 @@ void EditorPropertyNodePath::_node_assign() { } void EditorPropertyNodePath::_node_clear() { - emit_changed(get_edited_property(), NodePath()); + if (pointer_mode) { + emit_changed(_get_meta_pointer_property(), NodePath()); + } else { + emit_changed(get_edited_property(), NodePath()); + } update_property(); } @@ -3092,7 +3118,12 @@ bool EditorPropertyNodePath::is_drop_valid(const Dictionary &p_drag_data) const } void EditorPropertyNodePath::update_property() { - NodePath p = get_edited_object()->get(get_edited_property()); + NodePath p; + if (pointer_mode) { + p = get_edited_object()->get(_get_meta_pointer_property()); + } else { + p = get_edited_object()->get(get_edited_property()); + } assign->set_tooltip(p); if (p == NodePath()) { @@ -3131,7 +3162,8 @@ void EditorPropertyNodePath::update_property() { assign->set_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node")); } -void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringName> p_valid_types, bool p_use_path_from_scene_root) { +void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringName> p_valid_types, bool p_use_path_from_scene_root, bool p_pointer_mode) { + pointer_mode = p_pointer_mode; base_hint = p_base_hint; valid_types = p_valid_types; use_path_from_scene_root = p_use_path_from_scene_root; @@ -3927,23 +3959,31 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ return editor; } break; case Variant::OBJECT: { - EditorPropertyResource *editor = memnew(EditorPropertyResource); - editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); - - if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { - String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); - for (int i = 0; i < open_in_new.get_slice_count(","); i++) { - String type = open_in_new.get_slicec(',', i).strip_edges(); - for (int j = 0; j < p_hint_text.get_slice_count(","); j++) { - String inherits = p_hint_text.get_slicec(',', j); - if (ClassDB::is_parent_class(inherits, type)) { - editor->set_use_sub_inspector(false); + if (p_hint == PROPERTY_HINT_NODE_TYPE) { + EditorPropertyNodePath *editor = memnew(EditorPropertyNodePath); + Vector<String> types = p_hint_text.split(",", false); + Vector<StringName> sn = Variant(types); //convert via variant + editor->setup(NodePath(), sn, false, true); + return editor; + } else { + EditorPropertyResource *editor = memnew(EditorPropertyResource); + editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); + + if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { + String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); + for (int i = 0; i < open_in_new.get_slice_count(","); i++) { + String type = open_in_new.get_slicec(',', i).strip_edges(); + for (int j = 0; j < p_hint_text.get_slice_count(","); j++) { + String inherits = p_hint_text.get_slicec(',', j); + if (ClassDB::is_parent_class(inherits, type)) { + editor->set_use_sub_inspector(false); + } } } } - } - return editor; + return editor; + } } break; case Variant::DICTIONARY: { diff --git a/editor/editor_properties.h b/editor/editor_properties.h index a3b98b7724..72b2b0b283 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -704,6 +704,7 @@ class EditorPropertyNodePath : public EditorProperty { SceneTreeDialog *scene_tree = nullptr; NodePath base_hint; bool use_path_from_scene_root = false; + bool pointer_mode = false; Vector<StringName> valid_types; void _node_selected(const NodePath &p_path); @@ -714,6 +715,10 @@ class EditorPropertyNodePath : public EditorProperty { void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); bool is_drop_valid(const Dictionary &p_drag_data) const; + String _get_meta_pointer_property() const; + virtual Variant _get_cache_value(const StringName &p_prop, bool &r_valid) const override; + virtual StringName _get_revert_property() const override; + protected: virtual void _set_read_only(bool p_read_only) override; static void _bind_methods(); @@ -721,7 +726,7 @@ protected: public: virtual void update_property() override; - void setup(const NodePath &p_base_hint, Vector<StringName> p_valid_types, bool p_use_path_from_scene_root = true); + void setup(const NodePath &p_base_hint, Vector<StringName> p_valid_types, bool p_use_path_from_scene_root = true, bool p_pointer_mode = false); EditorPropertyNodePath(); }; |