diff options
-rw-r--r-- | core/core_constants.cpp | 1 | ||||
-rw-r--r-- | core/object/object.h | 1 | ||||
-rw-r--r-- | doc/classes/@GlobalScope.xml | 4 | ||||
-rw-r--r-- | doc/classes/EditorProperty.xml | 2 | ||||
-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 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 72 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 14 | ||||
-rw-r--r-- | scene/resources/resource_format_text.cpp | 19 |
11 files changed, 185 insertions, 37 deletions
diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 1f46223a1d..67aa2bbbfb 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -613,6 +613,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); diff --git a/core/object/object.h b/core/object/object.h index 2a9f2ebf93..7dac96bc2b 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -91,6 +91,7 @@ enum PropertyHint { PROPERTY_HINT_INT_IS_POINTER, PROPERTY_HINT_LOCALE_ID, PROPERTY_HINT_LOCALIZABLE_STRING, + PROPERTY_HINT_NODE_TYPE, ///< a node object type PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 475d166925..863ea899ee 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2583,7 +2583,9 @@ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="44" enum="PropertyHint"> Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings. </constant> - <constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint"> + <constant name="PROPERTY_HINT_NODE_TYPE" value="45" enum="PropertyHint"> + </constant> + <constant name="PROPERTY_HINT_MAX" value="46" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index c428233372..84f8523da3 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -38,7 +38,7 @@ Gets the edited object. </description> </method> - <method name="get_edited_property"> + <method name="get_edited_property" qualifiers="const"> <return type="StringName" /> <description> Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin._parse_property]), then this will return the property. 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 2562c740aa..0e6c9162ce 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(); }; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index b90f396110..2c58aa83a9 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -35,6 +35,7 @@ #include "core/core_string_names.h" #include "core/io/missing_resource.h" #include "core/io/resource_loader.h" +#include "core/templates/local_vector.h" #include "scene/2d/node_2d.h" #include "scene/3d/node_3d.h" #include "scene/gui/control.h" @@ -43,7 +44,7 @@ #include "scene/property_utils.h" #define PACKED_SCENE_VERSION 2 - +#define META_POINTER_PROPERTY_BASE "metadata/_editor_prop_ptr_" bool SceneState::can_instantiate() const { return nodes.size() > 0; } @@ -108,6 +109,8 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { HashMap<Ref<Resource>, Ref<Resource>> resources_local_to_scene; + LocalVector<DeferredNodePathProperties> deferred_node_paths; + for (int i = 0; i < nc; i++) { const NodeData &n = nd[i]; @@ -230,9 +233,28 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { for (int j = 0; j < nprop_count; j++) { bool valid; - ERR_FAIL_INDEX_V(nprops[j].name, sname_count, nullptr); + ERR_FAIL_INDEX_V(nprops[j].value, prop_count, nullptr); + if (nprops[j].name & FLAG_PATH_PROPERTY_IS_NODE) { + uint32_t name_idx = nprops[j].name & (FLAG_PATH_PROPERTY_IS_NODE - 1); + ERR_FAIL_UNSIGNED_INDEX_V(name_idx, (uint32_t)sname_count, nullptr); + if (Engine::get_singleton()->is_editor_hint()) { + // If editor, just set the metadata and be it + node->set(META_POINTER_PROPERTY_BASE + String(snames[name_idx]), props[nprops[j].value]); + } else { + // Do an actual deferred sed of the property path. + DeferredNodePathProperties dnp; + dnp.path = props[nprops[j].value]; + dnp.base = node; + dnp.property = snames[name_idx]; + deferred_node_paths.push_back(dnp); + } + continue; + } + + ERR_FAIL_INDEX_V(nprops[j].name, sname_count, nullptr); + if (snames[nprops[j].name] == CoreStringNames::get_singleton()->_script) { //work around to avoid old script variables from disappearing, should be the proper fix to: //https://github.com/godotengine/godot/issues/2958 @@ -369,6 +391,12 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } } + for (uint32_t i = 0; i < deferred_node_paths.size(); i++) { + const DeferredNodePathProperties &dnp = deferred_node_paths[i]; + Node *other = dnp.base->get_node_or_null(dnp.path); + dnp.base->set(dnp.property, other); + } + for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_scene) { E.value->setup_local_to_scene(); } @@ -532,6 +560,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has if (E.name == META_PROPERTY_MISSING_RESOURCES) { continue; // Ignore this property when packing. } + if (E.name.begins_with(META_POINTER_PROPERTY_BASE)) { + continue; // do not save. + } // If instance or inheriting, not saving if property requested so. if (!states_stack.is_empty()) { @@ -542,8 +573,15 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has StringName name = E.name; Variant value = p_node->get(name); + bool use_deferred_node_path_bit = false; - if (E.type == Variant::OBJECT && missing_resource_properties.has(E.name)) { + if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE) { + value = p_node->get(META_POINTER_PROPERTY_BASE + E.name); + if (value.get_type() != Variant::NODE_PATH) { + continue; //was never set, ignore. + } + use_deferred_node_path_bit = true; + } else if (E.type == Variant::OBJECT && missing_resource_properties.has(E.name)) { // Was this missing resource overridden? If so do not save the old value. Ref<Resource> ures = value; if (ures.is_null()) { @@ -562,6 +600,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has NodeData::Property prop; prop.name = _nm_get_string(name, name_map); prop.value = _vm_get_variant(value, variant_map); + if (use_deferred_node_path_bit) { + prop.name |= FLAG_PATH_PROPERTY_IS_NODE; + } nd.properties.push_back(prop); } @@ -1018,7 +1059,7 @@ Variant SceneState::get_property_value(int p_node, const StringName &p_property, const NodeData::Property *p = nodes[p_node].properties.ptr(); for (int i = 0; i < pc; i++) { - if (p_property == namep[p[i].name]) { + if (p_property == namep[p[i].name & FLAG_PROP_NAME_MASK]) { found = true; return variants[p[i].value]; } @@ -1409,7 +1450,19 @@ int SceneState::get_node_property_count(int p_idx) const { StringName SceneState::get_node_property_name(int p_idx, int p_prop) const { ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName()); ERR_FAIL_INDEX_V(p_prop, nodes[p_idx].properties.size(), StringName()); - return names[nodes[p_idx].properties[p_prop].name]; + return names[nodes[p_idx].properties[p_prop].name & FLAG_PROP_NAME_MASK]; +} + +Vector<String> SceneState::get_node_deferred_nodepath_properties(int p_idx) const { + Vector<String> ret; + ERR_FAIL_INDEX_V(p_idx, nodes.size(), ret); + for (int i = 0; i < nodes[p_idx].properties.size(); i++) { + uint32_t idx = nodes[p_idx].properties[i].name; + if (idx & FLAG_PATH_PROPERTY_IS_NODE) { + ret.push_back(names[idx & FLAG_PROP_NAME_MASK]); + } + } + return ret; } Variant SceneState::get_node_property_value(int p_idx, int p_prop) const { @@ -1555,13 +1608,16 @@ int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int return nodes.size() - 1; } -void SceneState::add_node_property(int p_node, int p_name, int p_value) { +void SceneState::add_node_property(int p_node, int p_name, int p_value, bool p_deferred_node_path) { ERR_FAIL_INDEX(p_node, nodes.size()); ERR_FAIL_INDEX(p_name, names.size()); ERR_FAIL_INDEX(p_value, variants.size()); NodeData::Property prop; prop.name = p_name; + if (p_deferred_node_path) { + prop.name |= FLAG_PATH_PROPERTY_IS_NODE; + } prop.value = p_value; nodes.write[p_node].properties.push_back(prop); } @@ -1599,6 +1655,10 @@ void SceneState::add_editable_instance(const NodePath &p_path) { editable_instances.push_back(p_path); } +String SceneState::get_meta_pointer_property(const String &p_property) { + return META_POINTER_PROPERTY_BASE + p_property; +} + Vector<String> SceneState::_get_node_groups(int p_idx) const { Vector<StringName> groups = get_node_groups(p_idx); Vector<String> ret; diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 05abb23284..5f8001c871 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -69,6 +69,12 @@ class SceneState : public RefCounted { Vector<int> groups; }; + struct DeferredNodePathProperties { + Node *base = nullptr; + StringName property; + NodePath path; + }; + Vector<NodeData> nodes; struct ConnectionData { @@ -104,6 +110,8 @@ public: FLAG_ID_IS_PATH = (1 << 30), TYPE_INSTANCED = 0x7FFFFFFF, FLAG_INSTANCE_IS_PLACEHOLDER = (1 << 30), + FLAG_PATH_PROPERTY_IS_NODE = (1 << 30), + FLAG_PROP_NAME_MASK = FLAG_PATH_PROPERTY_IS_NODE - 1, FLAG_MASK = (1 << 24) - 1, }; @@ -157,6 +165,7 @@ public: int get_node_property_count(int p_idx) const; StringName get_node_property_name(int p_idx, int p_prop) const; Variant get_node_property_value(int p_idx, int p_prop) const; + Vector<String> get_node_deferred_nodepath_properties(int p_idx) const; int get_connection_count() const; NodePath get_connection_source(int p_idx) const; @@ -177,7 +186,7 @@ public: int add_value(const Variant &p_value); int add_node_path(const NodePath &p_path); int add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance, int p_index); - void add_node_property(int p_node, int p_name, int p_value); + void add_node_property(int p_node, int p_name, int p_value, bool p_deferred_node_path = false); void add_node_group(int p_node, int p_group); void set_base_scene(int p_idx); void add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, int p_unbinds, const Vector<int> &p_binds); @@ -186,6 +195,9 @@ public: virtual void set_last_modified_time(uint64_t p_time) { last_modified_time = p_time; } uint64_t get_last_modified_time() const { return last_modified_time; } + // Used when saving pointers (saves a path property instead). + static String get_meta_pointer_property(const String &p_property); + SceneState(); }; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 3cda2f05b2..66afb001fb 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -212,6 +212,15 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars type = SceneState::TYPE_INSTANCED; //no type? assume this was instantiated } + HashSet<StringName> path_properties; + + if (next_tag.fields.has("node_paths")) { + Vector<String> paths = next_tag.fields["node_paths"]; + for (int i = 0; i < paths.size(); i++) { + path_properties.insert(paths[i]); + } + } + if (next_tag.fields.has("instance")) { instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]); @@ -276,9 +285,10 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars } if (!assign.is_empty()) { - int nameidx = packed_scene->get_state()->add_name(assign); + StringName assign_name = assign; + int nameidx = packed_scene->get_state()->add_name(assign_name); int valueidx = packed_scene->get_state()->add_value(value); - packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx); + packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx, path_properties.has(assign_name)); //it's assignment } else if (!next_tag.name.is_empty()) { break; @@ -1939,6 +1949,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso Ref<PackedScene> instance = state->get_node_instance(i); String instance_placeholder = state->get_node_instance_placeholder(i); Vector<StringName> groups = state->get_node_groups(i); + Vector<String> deferred_node_paths = state->get_node_deferred_nodepath_properties(i); String header = "[node"; header += " name=\"" + String(name).c_escape() + "\""; @@ -1955,6 +1966,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso header += " index=\"" + itos(index) + "\""; } + if (deferred_node_paths.size()) { + header += " node_paths=" + Variant(deferred_node_paths).get_construct_string(); + } + if (groups.size()) { // Write all groups on the same line as they're part of a section header. // This improves readability while not impacting VCS friendliness too much, |