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);
|
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;
|
List<PropertyInfo> plist;
|
||||||
get_property_list(&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)) {
|
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Variant p = get(E.name);
|
Variant p = get(E.name).duplicate(true);
|
||||||
if (p.get_type() == Variant::OBJECT) {
|
|
||||||
Ref<Resource> sr = p;
|
_dupe_sub_resources(p, p_for_scene, p_remap_cache);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r->set(E.name, p);
|
r->set(E.name, p);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +278,35 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, HashMap<Ref
|
||||||
return r;
|
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;
|
List<PropertyInfo> plist;
|
||||||
get_property_list(&plist);
|
get_property_list(&plist);
|
||||||
|
|
||||||
|
@ -251,14 +318,15 @@ void Resource::configure_for_local_scene(Node *p_for_scene, HashMap<Ref<Resource
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Variant p = get(E.name);
|
Variant p = get(E.name);
|
||||||
if (p.get_type() == Variant::OBJECT) {
|
|
||||||
Ref<Resource> sr = p;
|
HashSet<Ref<Resource>> sub_resources;
|
||||||
if (sr.is_valid()) {
|
_find_sub_resources(p, sub_resources);
|
||||||
if (sr->is_local_to_scene()) {
|
|
||||||
if (!remap_cache.has(sr)) {
|
for (Ref<Resource> sr : sub_resources) {
|
||||||
sr->configure_for_local_scene(p_for_scene, remap_cache);
|
if (sr->is_local_to_scene()) {
|
||||||
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;
|
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:
|
protected:
|
||||||
virtual void _resource_path_changed();
|
virtual void _resource_path_changed();
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
@ -111,8 +114,8 @@ public:
|
||||||
String get_scene_unique_id() const;
|
String get_scene_unique_id() const;
|
||||||
|
|
||||||
virtual Ref<Resource> duplicate(bool p_subresources = false) 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);
|
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>> &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);
|
void set_local_to_scene(bool p_enable);
|
||||||
bool is_local_to_scene() const;
|
bool is_local_to_scene() const;
|
||||||
|
|
Loading…
Reference in a new issue