Fix recursive resource local to scene
Any resource that contains other local to scene resources inside of arrays or dictionaries will now be duplicated and configured. The case where a scene's node has an exported array/dictionary property containing local to scene resources is NOT handled here.
This commit is contained in:
parent
12ee58d8bc
commit
608b5d2e07
2 changed files with 98 additions and 27 deletions
|
@ -204,7 +204,58 @@ void Resource::reload_from_file() {
|
|||
copy_from(s);
|
||||
}
|
||||
|
||||
Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) {
|
||||
void Resource::_dupe_sub_resources(Variant &r_variant, Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) {
|
||||
switch (r_variant.get_type()) {
|
||||
case Variant::ARRAY: {
|
||||
Array a = r_variant;
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
_dupe_sub_resources(a[i], p_for_scene, p_remap_cache);
|
||||
}
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = r_variant;
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
for (Variant &k : keys) {
|
||||
if (k.get_type() == Variant::OBJECT) {
|
||||
// Replace in dictionary key.
|
||||
Ref<Resource> sr = k;
|
||||
if (sr.is_valid() && sr->is_local_to_scene()) {
|
||||
if (p_remap_cache.has(sr)) {
|
||||
d[p_remap_cache[sr]] = d[k];
|
||||
d.erase(k);
|
||||
} else {
|
||||
Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, p_remap_cache);
|
||||
d[dupe] = d[k];
|
||||
d.erase(k);
|
||||
p_remap_cache[sr] = dupe;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_dupe_sub_resources(k, p_for_scene, p_remap_cache);
|
||||
}
|
||||
|
||||
_dupe_sub_resources(d[k], p_for_scene, p_remap_cache);
|
||||
}
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
Ref<Resource> sr = r_variant;
|
||||
if (sr.is_valid() && sr->is_local_to_scene()) {
|
||||
if (p_remap_cache.has(sr)) {
|
||||
r_variant = p_remap_cache[sr];
|
||||
} else {
|
||||
Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, p_remap_cache);
|
||||
r_variant = dupe;
|
||||
p_remap_cache[sr] = dupe;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) {
|
||||
List<PropertyInfo> plist;
|
||||
get_property_list(&plist);
|
||||
|
||||
|
@ -217,21 +268,9 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref
|
|||
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
Variant p = get(E.name);
|
||||
if (p.get_type() == Variant::OBJECT) {
|
||||
Ref<Resource> sr = p;
|
||||
if (sr.is_valid()) {
|
||||
if (sr->is_local_to_scene()) {
|
||||
if (remap_cache.has(sr)) {
|
||||
p = remap_cache[sr];
|
||||
} else {
|
||||
Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache);
|
||||
p = dupe;
|
||||
remap_cache[sr] = dupe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Variant p = get(E.name).duplicate(true);
|
||||
|
||||
_dupe_sub_resources(p, p_for_scene, p_remap_cache);
|
||||
|
||||
r->set(E.name, p);
|
||||
}
|
||||
|
@ -239,7 +278,35 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref
|
|||
return r;
|
||||
}
|
||||
|
||||
void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache) {
|
||||
void Resource::_find_sub_resources(const Variant &p_variant, HashSet<Ref<Resource>> &p_resources_found) {
|
||||
switch (p_variant.get_type()) {
|
||||
case Variant::ARRAY: {
|
||||
Array a = p_variant;
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
_find_sub_resources(a[i], p_resources_found);
|
||||
}
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_variant;
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
for (const Variant &k : keys) {
|
||||
_find_sub_resources(k, p_resources_found);
|
||||
_find_sub_resources(d[k], p_resources_found);
|
||||
}
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
Ref<Resource> r = p_variant;
|
||||
if (r.is_valid()) {
|
||||
p_resources_found.insert(r);
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache) {
|
||||
List<PropertyInfo> plist;
|
||||
get_property_list(&plist);
|
||||
|
||||
|
@ -251,14 +318,15 @@ void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource
|
|||
continue;
|
||||
}
|
||||
Variant p = get(E.name);
|
||||
if (p.get_type() == Variant::OBJECT) {
|
||||
Ref<Resource> sr = p;
|
||||
if (sr.is_valid()) {
|
||||
|
||||
HashSet<Ref<Resource>> sub_resources;
|
||||
_find_sub_resources(p, sub_resources);
|
||||
|
||||
for (Ref<Resource> sr : sub_resources) {
|
||||
if (sr->is_local_to_scene()) {
|
||||
if (!remap_cache.has(sr)) {
|
||||
sr->configure_for_local_scene(p_for_scene, remap_cache);
|
||||
remap_cache[sr] = sr;
|
||||
}
|
||||
if (!p_remap_cache.has(sr)) {
|
||||
sr->configure_for_local_scene(p_for_scene, p_remap_cache);
|
||||
p_remap_cache[sr] = sr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ private:
|
|||
|
||||
SelfList<Resource> remapped_list;
|
||||
|
||||
void _dupe_sub_resources(Variant &r_variant, Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache);
|
||||
void _find_sub_resources(const Variant &p_variant, HashSet<Ref<Resource>> &p_resources_found);
|
||||
|
||||
protected:
|
||||
virtual void _resource_path_changed();
|
||||
static void _bind_methods();
|
||||
|
@ -111,8 +114,8 @@ public:
|
|||
String get_scene_unique_id() const;
|
||||
|
||||
virtual Ref<Resource> duplicate(bool p_subresources = false) const;
|
||||
Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache);
|
||||
void configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &remap_cache);
|
||||
Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache);
|
||||
void configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource>, Ref<Resource>> &p_remap_cache);
|
||||
|
||||
void set_local_to_scene(bool p_enable);
|
||||
bool is_local_to_scene() const;
|
||||
|
|
Loading…
Reference in a new issue