mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Add support for making arrays and dictionaries with Resources unique
This commit is contained in:
parent
b4472f4670
commit
12ced6c83b
1 changed files with 103 additions and 10 deletions
|
@ -53,8 +53,26 @@ static bool _has_sub_resources(const Ref<Resource> &p_res) {
|
||||||
List<PropertyInfo> property_list;
|
List<PropertyInfo> property_list;
|
||||||
p_res->get_property_list(&property_list);
|
p_res->get_property_list(&property_list);
|
||||||
for (const PropertyInfo &p : 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()) {
|
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;
|
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;
|
return false;
|
||||||
|
@ -1097,9 +1115,9 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res_name.is_empty()) {
|
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 {
|
} 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()));
|
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);
|
p_resource->get_property_list(&plist);
|
||||||
|
|
||||||
for (const PropertyInfo &E : 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,13 +1188,11 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
|
||||||
if (res.is_null()) {
|
if (res.is_null()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
child = p_item->create_child();
|
||||||
TreeItem *child = p_item->create_child();
|
|
||||||
_gather_resources_to_duplicate(res, child, E.name);
|
_gather_resources_to_duplicate(res, child, E.name);
|
||||||
|
|
||||||
meta = child->get_metadata(0);
|
meta = child->get_metadata(0);
|
||||||
// Remember property name.
|
// Remember property name.
|
||||||
meta.append(E.name);
|
meta.push_back(E.name);
|
||||||
|
|
||||||
if ((E.usage & PROPERTY_USAGE_NEVER_DUPLICATE)) {
|
if ((E.usage & PROPERTY_USAGE_NEVER_DUPLICATE)) {
|
||||||
// The resource can't be duplicated, but make it appear on the list anyway.
|
// 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.
|
if (meta.size() == 1) { // Root.
|
||||||
edited_resource = unique_resource;
|
edited_resource = unique_resource;
|
||||||
_resource_changed();
|
_resource_changed();
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
Array parent_meta = item->get_parent()->get_metadata(0);
|
Array parent_meta = item->get_parent()->get_metadata(0);
|
||||||
Ref<Resource> parent = parent_meta[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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue