summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2022-08-28 17:12:26 +0200
committerGitHub <noreply@github.com>2022-08-28 17:12:26 +0200
commitc9972e3981b9b9768a01e517e4b6dd23f85a31b6 (patch)
treea946e91e90c886d82f805fd9dcde429052f53ee8
parentdd9602e74ce8d3f9c04f8c1973ec7d11b63e00af (diff)
parentd6c0959cb146aad36b4c6f36d44d69dafd1dd2c8 (diff)
Merge pull request #64526 from Rindbee/improve-packed-scene-instantiate
Improve PackedScene instantiate
-rw-r--r--scene/resources/packed_scene.cpp45
1 files changed, 28 insertions, 17 deletions
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 0e1b18d584..dcccc6898b 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -279,25 +279,34 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
Ref<Resource> res = value;
if (res.is_valid()) {
if (res->is_local_to_scene()) {
- HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res);
-
- if (E) {
- value = E->value;
+ // In a situation where a local-to-scene resource is used in a child node of a non-editable instance,
+ // we need to avoid the parent scene from overriding the resource potentially also used in the root
+ // of the instantiated scene. That would to the instance having two different instances of the resource.
+ // Since at this point it's too late to propagate the resource instance in the parent scene to all the relevant
+ // nodes in the instance (and that would require very complex bookkepping), what we do instead is
+ // tampering the resource object already there with the values from the node in the parent scene and
+ // then tell this node to reference that resource.
+ if (n.instance >= 0) {
+ Ref<Resource> node_res = node->get(snames[nprops[j].name]);
+ node_res->copy_from(res);
+ node_res->configure_for_local_scene(node, resources_local_to_scene);
+ value = node_res;
} else {
+ HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res);
Node *base = i == 0 ? node : ret_nodes[0];
-
- if (p_edit_state == GEN_EDIT_STATE_MAIN || p_edit_state == GEN_EDIT_STATE_MAIN_INHERITED) {
- //for the main scene, use the resource as is
- res->configure_for_local_scene(base, resources_local_to_scene);
- resources_local_to_scene[res] = res;
-
+ if (E) {
+ value = E->value;
} else {
- //for instances, a copy must be made
- Node *base2 = i == 0 ? node : ret_nodes[0];
- Ref<Resource> local_dupe = res->duplicate_for_local_scene(base2, resources_local_to_scene);
- resources_local_to_scene[res] = local_dupe;
- res = local_dupe;
- value = local_dupe;
+ if (p_edit_state == GEN_EDIT_STATE_MAIN || p_edit_state == GEN_EDIT_STATE_MAIN_INHERITED) {
+ //for the main scene, use the resource as is
+ res->configure_for_local_scene(base, resources_local_to_scene);
+ resources_local_to_scene[res] = res;
+ } else {
+ //for instances, a copy must be made
+ Ref<Resource> local_dupe = res->duplicate_for_local_scene(base, resources_local_to_scene);
+ resources_local_to_scene[res] = local_dupe;
+ value = local_dupe;
+ }
}
}
//must make a copy, because this res is local to scene
@@ -398,7 +407,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
}
for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_scene) {
- E.value->setup_local_to_scene();
+ if (E.value->get_local_scene() == ret_nodes[0]) {
+ E.value->setup_local_to_scene();
+ }
}
//do connections