@@ -78,18 +78,28 @@ static Array _sanitize_node_pinned_properties(Node *p_node) {
7878 return pinned;
7979}
8080
81- Ref<Resource> SceneState::get_remap_resource (const Ref<Resource> &p_resource, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache, const Ref<Resource> &p_fallback, Node *p_for_scene) {
81+ Ref<Resource> SceneState::get_remap_resource (const Ref<Resource> &p_resource, HashMap<Node *, HashMap< Ref<Resource>, Ref<Resource> >> &remap_cache, const Ref<Resource> &p_fallback, Node *p_for_scene) {
8282 ERR_FAIL_COND_V (p_resource.is_null (), Ref<Resource>());
8383
84- Ref<Resource> remap_resource;
85-
8684 // Find the shared copy of the source resource.
87- HashMap<Ref<Resource>, Ref<Resource>>::Iterator R = remap_cache.find (p_resource);
85+ HashMap<Ref<Resource>, Ref<Resource>>::Iterator R = remap_cache[p_for_scene] .find (p_resource);
8886 if (R) {
89- remap_resource = R->value ;
90- } else if (p_fallback.is_valid () && p_fallback->is_local_to_scene () && p_fallback->get_class () == p_resource->get_class ()) {
91- // Simply copy the data from the source resource to update the fallback resource that was previously set.
87+ return R->value ;
88+ }
89+
90+ bool reuse_fallback = p_fallback.is_valid () && p_fallback->is_local_to_scene () && p_fallback->get_class_name () == p_resource->get_class_name ();
91+
92+ if (reuse_fallback) {
93+ // The fallback resource can only be mapped at most once when it is valid.
94+ for (const KeyValue<Ref<Resource>, Ref<Resource>> &E : remap_cache[p_for_scene]) {
95+ if (E.value == p_fallback) {
96+ reuse_fallback = false ;
97+ break ;
98+ }
99+ }
100+ }
92101
102+ if (reuse_fallback) { // Simply copy the data from the source resource to update the fallback resource that was previously set.
93103 p_fallback->reset_state (); // May want to reset state.
94104
95105 List<PropertyInfo> pi;
@@ -113,18 +123,14 @@ Ref<Resource> SceneState::get_remap_resource(const Ref<Resource> &p_resource, Ha
113123
114124 p_fallback->set (E.name , value);
115125 }
116-
117- p_fallback->set_scene_unique_id (p_resource->get_scene_unique_id ()); // Get the id from the main scene, in case the id changes again when saving the scene.
118-
119- remap_cache[p_resource] = p_fallback;
120- remap_resource = p_fallback;
121- } else { // A copy of the source resource is required to overwrite the previous one.
122- Ref<Resource> local_dupe = p_resource->duplicate_for_local_scene (p_for_scene, remap_cache);
123- remap_cache[p_resource] = local_dupe;
124- remap_resource = local_dupe;
126+ remap_cache[p_for_scene][p_resource] = p_fallback;
127+ return p_fallback;
125128 }
126129
127- return remap_resource;
130+ // A copy of the source resource is required to overwrite the previous one.
131+ Ref<Resource> local_dupe = p_resource->duplicate_for_local_scene (p_for_scene, remap_cache[p_for_scene]);
132+ remap_cache[p_for_scene][p_resource] = local_dupe;
133+ return local_dupe;
128134}
129135
130136static Node *_find_node_by_id (Node *p_owner, Node *p_node, int32_t p_id) {
@@ -185,7 +191,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
185191
186192 bool gen_node_path_cache = p_edit_state != GEN_EDIT_STATE_DISABLED && node_path_cache.is_empty ();
187193
188- HashMap<Ref<Resource>, Ref<Resource>> resources_local_to_scene;
194+ HashMap<Node *, HashMap< Ref<Resource>, Ref<Resource>>> resources_local_to_scenes; // Record the mappings in sub-scenes.
189195
190196 LocalVector<DeferredNodePathProperties> deferred_node_paths;
191197
@@ -359,7 +365,6 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
359365 const NodeData::Property *nprops = &n.properties [0 ];
360366
361367 Dictionary missing_resource_properties;
362- HashMap<Ref<Resource>, Ref<Resource>> resources_local_to_sub_scene; // Record the mappings in the sub-scene.
363368
364369 for (int j = 0 ; j < nprop_count; j++) {
365370 bool valid;
@@ -430,7 +435,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
430435 // handle resources that are local to scene by duplicating them if needed
431436 Ref<Resource> res = value;
432437 if (res.is_valid ()) {
433- value = make_local_resource (value, n, resources_local_to_sub_scene , node, snames[nprops[j].name ], resources_local_to_scene , i, ret_nodes, p_edit_state);
438+ value = make_local_resource (value, n, resources_local_to_scenes , node, snames[nprops[j].name ], i, ret_nodes, p_edit_state);
434439 }
435440 } else {
436441 // Making sure that instances of inherited scenes don't share the same
@@ -454,7 +459,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
454459 }
455460 }
456461
457- value = setup_resources_in_array (set_array, n, resources_local_to_sub_scene , node, snames[nprops[j].name ], resources_local_to_scene , i, ret_nodes, p_edit_state);
462+ value = setup_resources_in_array (set_array, n, resources_local_to_scenes , node, snames[nprops[j].name ], i, ret_nodes, p_edit_state);
458463 }
459464
460465 if (value.get_type () == Variant::DICTIONARY) {
@@ -471,7 +476,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
471476 }
472477 }
473478
474- value = setup_resources_in_dictionary (set_dict, n, resources_local_to_sub_scene , node, snames[nprops[j].name ], resources_local_to_scene , i, ret_nodes, p_edit_state);
479+ value = setup_resources_in_dictionary (set_dict, n, resources_local_to_scenes , node, snames[nprops[j].name ], i, ret_nodes, p_edit_state);
475480 }
476481
477482 bool set_valid = true ;
@@ -494,12 +499,6 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
494499 if (!missing_resource_properties.is_empty ()) {
495500 node->set_meta (META_MISSING_RESOURCES, missing_resource_properties);
496501 }
497-
498- for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_sub_scene) {
499- if (E.value ->get_local_scene () == node) {
500- E.value ->setup_local_to_scene (); // Setup may be required for the resource to work properly.
501- }
502- }
503502 }
504503
505504 // name
@@ -639,9 +638,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
639638 }
640639 }
641640
642- for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_scene ) {
643- if (E. value -> get_local_scene () == ret_nodes[ 0 ] ) {
644- E .value ->setup_local_to_scene ();
641+ for (KeyValue<Node *, HashMap< Ref<Resource>, Ref<Resource>>> &E : resources_local_to_scenes ) {
642+ for (KeyValue<Ref<Resource>, Ref<Resource>> &R : E. value ) {
643+ R .value ->setup_local_to_scene (); // Setup may be required for the resource to work properly.
645644 }
646645 }
647646
@@ -702,50 +701,55 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
702701 return ret_nodes[0 ];
703702}
704703
705- Variant SceneState::make_local_resource (Variant &p_value, const SceneState::NodeData &p_node_data, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_sub_scene , Node *p_node, const StringName p_sname, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_scene , int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
704+ Variant SceneState::make_local_resource (Variant &p_value, const SceneState::NodeData &p_node_data, HashMap<Node *, HashMap< Ref<Resource>, Ref<Resource>>> &p_resources_local_to_scenes , Node *p_node, const StringName p_sname, int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
706705 Ref<Resource> res = p_value;
707706 if (res.is_null () || !res->is_local_to_scene ()) {
708707 return p_value;
709708 }
710709
711- if (p_node_data.instance >= 0 ) { // For the root node of a sub-scene, treat it as part of the sub-scene.
712- return get_remap_resource (res, p_resources_local_to_sub_scene, p_node->get (p_sname), p_node);
713- } else {
714- HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = p_resources_local_to_scene.find (res);
715- Node *base = p_i == 0 ? p_node : p_ret_nodes[0 ];
716- if (E) {
717- return E->value ;
718- } else if (p_edit_state == GEN_EDIT_STATE_MAIN) { // For the main scene, use the resource as is
719- res->configure_for_local_scene (base, p_resources_local_to_scene);
720- p_resources_local_to_scene[res] = res;
721- return res;
722- } else { // For instances, a copy must be made.
723- Ref<Resource> local_dupe = res->duplicate_for_local_scene (base, p_resources_local_to_scene);
724- p_resources_local_to_scene[res] = local_dupe;
725- return local_dupe;
726- }
710+ Node *base = (p_i == 0 || p_node->is_instance ()) ? p_node : (p_node->get_owner () ? p_node->get_owner () : p_ret_nodes[0 ]);
711+
712+ if (p_node_data.type == TYPE_INSTANTIATED) { // For the (root) nodes of sub-scenes, treat them as parts of the sub-scenes.
713+ return get_remap_resource (res, p_resources_local_to_scenes, p_node->get (p_sname), base);
714+ }
715+
716+ // Find the shared copy of the source resource.
717+ HashMap<Ref<Resource>, Ref<Resource>>::Iterator R = p_resources_local_to_scenes[base].find (res);
718+ if (R) {
719+ return R->value ;
727720 }
721+
722+ if (p_edit_state == GEN_EDIT_STATE_MAIN) { // For the main scene, use the resource as is
723+ res->configure_for_local_scene (base, p_resources_local_to_scenes[base]);
724+ p_resources_local_to_scenes[base][res] = res;
725+ return res;
726+ }
727+
728+ // For instances, a copy must be made.
729+ Ref<Resource> local_dupe = res->duplicate_for_local_scene (base, p_resources_local_to_scenes[base]);
730+ p_resources_local_to_scenes[base][res] = local_dupe;
731+ return local_dupe;
728732}
729733
730- Array SceneState::setup_resources_in_array (Array &p_array_to_scan, const SceneState::NodeData &p_n, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_sub_scene , Node *p_node, const StringName p_sname, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_scene , int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
734+ Array SceneState::setup_resources_in_array (Array &p_array_to_scan, const SceneState::NodeData &p_n, HashMap<Node *, HashMap< Ref<Resource>, Ref<Resource>>> &p_resources_local_to_scenes , Node *p_node, const StringName p_sname, int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
731735 for (int i = 0 ; i < p_array_to_scan.size (); i++) {
732736 if (p_array_to_scan[i].get_type () == Variant::OBJECT) {
733- p_array_to_scan[i] = make_local_resource (p_array_to_scan[i], p_n, p_resources_local_to_sub_scene , p_node, p_sname, p_resources_local_to_scene , p_i, p_ret_nodes, p_edit_state);
737+ p_array_to_scan[i] = make_local_resource (p_array_to_scan[i], p_n, p_resources_local_to_scenes , p_node, p_sname, p_i, p_ret_nodes, p_edit_state);
734738 }
735739 }
736740 return p_array_to_scan;
737741}
738742
739- Dictionary SceneState::setup_resources_in_dictionary (Dictionary &p_dictionary_to_scan, const SceneState::NodeData &p_n, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_sub_scene , Node *p_node, const StringName p_sname, HashMap<Ref<Resource>, Ref<Resource>> &p_resources_local_to_scene , int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
743+ Dictionary SceneState::setup_resources_in_dictionary (Dictionary &p_dictionary_to_scan, const SceneState::NodeData &p_n, HashMap<Node *, HashMap< Ref<Resource>, Ref<Resource>>> &p_resources_local_to_scenes , Node *p_node, const StringName p_sname, int p_i, Node **p_ret_nodes, SceneState::GenEditState p_edit_state) const {
740744 const Array keys = p_dictionary_to_scan.keys ();
741745 const Array values = p_dictionary_to_scan.values ();
742746
743747 if (has_local_resource (values) || has_local_resource (keys)) {
744748 Array duplicated_keys = keys.duplicate (true );
745749 Array duplicated_values = values.duplicate (true );
746750
747- duplicated_keys = setup_resources_in_array (duplicated_keys, p_n, p_resources_local_to_sub_scene , p_node, p_sname, p_resources_local_to_scene , p_i, p_ret_nodes, p_edit_state);
748- duplicated_values = setup_resources_in_array (duplicated_values, p_n, p_resources_local_to_sub_scene , p_node, p_sname, p_resources_local_to_scene , p_i, p_ret_nodes, p_edit_state);
751+ duplicated_keys = setup_resources_in_array (duplicated_keys, p_n, p_resources_local_to_scenes , p_node, p_sname, p_i, p_ret_nodes, p_edit_state);
752+ duplicated_values = setup_resources_in_array (duplicated_values, p_n, p_resources_local_to_scenes , p_node, p_sname, p_i, p_ret_nodes, p_edit_state);
749753 p_dictionary_to_scan.clear ();
750754
751755 for (int i = 0 ; i < keys.size (); i++) {
0 commit comments