mirror of
https://github.com/godotengine/godot.git
synced 2025-10-15 02:49:24 +00:00
Merge pull request #109816 from SatLess/ArraysArePeopleToo
Add `Make_Unique_Recursive` option for `Resources` with `Arrays` and `Dictionaries`
This commit is contained in:
@@ -53,8 +53,26 @@ static bool _has_sub_resources(const Ref<Resource> &p_res) {
|
||||
List<PropertyInfo> property_list;
|
||||
p_res->get_property_list(&property_list);
|
||||
for (const PropertyInfo &p : property_list) {
|
||||
Variant value = p_res->get(p.name);
|
||||
if (p.type == Variant::OBJECT && p.hint == PROPERTY_HINT_RESOURCE_TYPE && !(p.usage & PROPERTY_USAGE_NEVER_DUPLICATE) && p_res->get(p.name).get_validated_object()) {
|
||||
return true;
|
||||
} else if (p.type == Variant::ARRAY) {
|
||||
Array arr = value;
|
||||
for (Variant &var : arr) {
|
||||
Ref<Resource> res = var;
|
||||
if (res.is_valid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (p.type == Variant::DICTIONARY) {
|
||||
Dictionary dict = value;
|
||||
for (const KeyValue<Variant, Variant> &kv : dict) {
|
||||
Ref<Resource> resk = kv.key;
|
||||
Ref<Resource> resv = kv.value;
|
||||
if (resk.is_valid() || resv.is_valid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -1097,9 +1115,9 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
|
||||
}
|
||||
|
||||
if (res_name.is_empty()) {
|
||||
p_item->set_text(0, p_resource->get_class());
|
||||
p_item->set_text(0, _get_resource_type(p_resource));
|
||||
} else {
|
||||
p_item->set_text(0, vformat("%s (%s)", p_resource->get_class(), res_name));
|
||||
p_item->set_text(0, vformat("%s (%s)", _get_resource_type(p_resource), res_name));
|
||||
}
|
||||
|
||||
p_item->set_icon(0, EditorNode::get_singleton()->get_object_icon(p_resource.ptr()));
|
||||
@@ -1122,7 +1140,47 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
|
||||
p_resource->get_property_list(&plist);
|
||||
|
||||
for (const PropertyInfo &E : plist) {
|
||||
if (!(E.usage & PROPERTY_USAGE_STORAGE) || E.type != Variant::OBJECT || E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
if (!(E.usage & PROPERTY_USAGE_STORAGE) || (E.type != Variant::OBJECT && E.type != Variant::ARRAY && E.type != Variant::DICTIONARY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Variant value = p_resource->get(E.name);
|
||||
TreeItem *child = nullptr;
|
||||
|
||||
if (E.type == Variant::ARRAY) {
|
||||
Array arr = value;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
Ref<Resource> res = arr[i];
|
||||
if (res.is_valid()) {
|
||||
child = p_item->create_child();
|
||||
_gather_resources_to_duplicate(res, child, E.name);
|
||||
meta = child->get_metadata(0);
|
||||
meta.push_back(E.name);
|
||||
meta.push_back(i); // Remember index.
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else if (E.type == Variant::DICTIONARY) {
|
||||
Dictionary dict = value;
|
||||
for (const KeyValue<Variant, Variant> &kv : dict) {
|
||||
Ref<Resource> key_res = kv.key;
|
||||
Ref<Resource> value_res = kv.value;
|
||||
if (key_res.is_valid()) {
|
||||
child = p_item->create_child();
|
||||
_gather_resources_to_duplicate(key_res, child, E.name);
|
||||
meta = child->get_metadata(0);
|
||||
meta.push_back(E.name);
|
||||
meta.push_back(key_res);
|
||||
}
|
||||
if (value_res.is_valid()) {
|
||||
child = p_item->create_child();
|
||||
_gather_resources_to_duplicate(value_res, child, E.name);
|
||||
meta = child->get_metadata(0);
|
||||
meta.push_back(E.name);
|
||||
meta.push_back(value_res);
|
||||
meta.push_back(kv.key);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1130,13 +1188,11 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
|
||||
if (res.is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeItem *child = p_item->create_child();
|
||||
child = p_item->create_child();
|
||||
_gather_resources_to_duplicate(res, child, E.name);
|
||||
|
||||
meta = child->get_metadata(0);
|
||||
// Remember property name.
|
||||
meta.append(E.name);
|
||||
meta.push_back(E.name);
|
||||
|
||||
if ((E.usage & PROPERTY_USAGE_NEVER_DUPLICATE)) {
|
||||
// The resource can't be duplicated, but make it appear on the list anyway.
|
||||
@@ -1161,10 +1217,47 @@ void EditorResourcePicker::_duplicate_selected_resources() {
|
||||
if (meta.size() == 1) { // Root.
|
||||
edited_resource = unique_resource;
|
||||
_resource_changed();
|
||||
} else {
|
||||
Array parent_meta = item->get_parent()->get_metadata(0);
|
||||
Ref<Resource> parent = parent_meta[0];
|
||||
continue;
|
||||
}
|
||||
Array parent_meta = item->get_parent()->get_metadata(0);
|
||||
Ref<Resource> parent = parent_meta[0];
|
||||
Variant::Type property_type = parent->get(meta[1]).get_type();
|
||||
|
||||
if (property_type == Variant::OBJECT) {
|
||||
parent->set(meta[1], unique_resource);
|
||||
continue;
|
||||
}
|
||||
|
||||
Variant property = parent->get(meta[1]);
|
||||
|
||||
if (!parent_meta.has(property)) {
|
||||
property = property.duplicate();
|
||||
parent->set(meta[1], property);
|
||||
parent_meta.push_back(property); // Append Duplicated Type so we can check if it's already been duplicated.
|
||||
}
|
||||
|
||||
if (property_type == Variant::ARRAY) {
|
||||
Array arr = property;
|
||||
arr[meta[2]] = unique_resource;
|
||||
continue;
|
||||
}
|
||||
|
||||
Dictionary dict = property;
|
||||
LocalVector<Variant> keys = dict.get_key_list();
|
||||
|
||||
if (meta[2].get_type() == Variant::OBJECT) {
|
||||
if (keys.has(meta[2])) {
|
||||
//It's a key.
|
||||
dict[unique_resource] = dict[meta[2]];
|
||||
dict.erase(meta[2]);
|
||||
parent_meta.push_back(unique_resource);
|
||||
} else {
|
||||
// If key has been erased, use last appended Resource key instead.
|
||||
Variant key = keys.has(meta[3]) ? meta[3] : parent_meta.back();
|
||||
dict[key] = unique_resource;
|
||||
}
|
||||
} else {
|
||||
dict[meta[2]] = unique_resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user