|
@@ -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;
|