@@ -53,8 +53,26 @@ static bool _has_sub_resources(const Ref<Resource> &p_res) {
5353 List<PropertyInfo> property_list;
5454 p_res->get_property_list (&property_list);
5555 for (const PropertyInfo &p : property_list) {
56+ Variant value = p_res->get (p.name );
5657 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 ()) {
5758 return true ;
59+ } else if (p.type == Variant::ARRAY) {
60+ Array arr = value;
61+ for (Variant &var : arr) {
62+ Ref<Resource> res = var;
63+ if (res.is_valid ()) {
64+ return true ;
65+ }
66+ }
67+ } else if (p.type == Variant::DICTIONARY) {
68+ Dictionary dict = value;
69+ for (const KeyValue<Variant, Variant> &kv : dict) {
70+ Ref<Resource> resk = kv.key ;
71+ Ref<Resource> resv = kv.value ;
72+ if (resk.is_valid () || resv.is_valid ()) {
73+ return true ;
74+ }
75+ }
5876 }
5977 }
6078 return false ;
@@ -1097,9 +1115,9 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
10971115 }
10981116
10991117 if (res_name.is_empty ()) {
1100- p_item->set_text (0 , p_resource-> get_class ( ));
1118+ p_item->set_text (0 , _get_resource_type (p_resource ));
11011119 } else {
1102- p_item->set_text (0 , vformat (" %s (%s)" , p_resource-> get_class ( ), res_name));
1120+ p_item->set_text (0 , vformat (" %s (%s)" , _get_resource_type (p_resource ), res_name));
11031121 }
11041122
11051123 p_item->set_icon (0 , EditorNode::get_singleton ()->get_object_icon (p_resource.ptr ()));
@@ -1122,21 +1140,59 @@ void EditorResourcePicker::_gather_resources_to_duplicate(const Ref<Resource> p_
11221140 p_resource->get_property_list (&plist);
11231141
11241142 for (const PropertyInfo &E : plist) {
1125- if (!(E.usage & PROPERTY_USAGE_STORAGE) || E.type != Variant::OBJECT || E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
1143+ if (!(E.usage & PROPERTY_USAGE_STORAGE) || (E.type != Variant::OBJECT && E.type != Variant::ARRAY && E.type != Variant::DICTIONARY)) {
1144+ continue ;
1145+ }
1146+
1147+ Variant value = p_resource->get (E.name );
1148+ TreeItem *child = nullptr ;
1149+
1150+ if (E.type == Variant::ARRAY) {
1151+ Array arr = value;
1152+ for (int i = 0 ; i < arr.size (); i++) {
1153+ Ref<Resource> res = arr[i];
1154+ if (res.is_valid ()) {
1155+ child = p_item->create_child ();
1156+ _gather_resources_to_duplicate (res, child, E.name );
1157+ meta = child->get_metadata (0 );
1158+ meta.push_back (E.name );
1159+ meta.push_back (i); // Remember index.
1160+ }
1161+ }
1162+ continue ;
1163+ } else if (E.type == Variant::DICTIONARY) {
1164+ Dictionary dict = value;
1165+ for (const KeyValue<Variant, Variant> &kv : dict) {
1166+ Ref<Resource> key_res = kv.key ;
1167+ Ref<Resource> value_res = kv.value ;
1168+ if (key_res.is_valid ()) {
1169+ child = p_item->create_child ();
1170+ _gather_resources_to_duplicate (key_res, child, E.name );
1171+ meta = child->get_metadata (0 );
1172+ meta.push_back (E.name );
1173+ meta.push_back (key_res);
1174+ }
1175+ if (value_res.is_valid ()) {
1176+ child = p_item->create_child ();
1177+ _gather_resources_to_duplicate (value_res, child, E.name );
1178+ meta = child->get_metadata (0 );
1179+ meta.push_back (E.name );
1180+ meta.push_back (value_res);
1181+ meta.push_back (kv.key );
1182+ }
1183+ }
11261184 continue ;
11271185 }
11281186
11291187 Ref<Resource> res = p_resource->get (E.name );
11301188 if (res.is_null ()) {
11311189 continue ;
11321190 }
1133-
1134- TreeItem *child = p_item->create_child ();
1191+ child = p_item->create_child ();
11351192 _gather_resources_to_duplicate (res, child, E.name );
1136-
11371193 meta = child->get_metadata (0 );
11381194 // Remember property name.
1139- meta.append (E.name );
1195+ meta.push_back (E.name );
11401196
11411197 if ((E.usage & PROPERTY_USAGE_NEVER_DUPLICATE)) {
11421198 // The resource can't be duplicated, but make it appear on the list anyway.
@@ -1161,10 +1217,47 @@ void EditorResourcePicker::_duplicate_selected_resources() {
11611217 if (meta.size () == 1 ) { // Root.
11621218 edited_resource = unique_resource;
11631219 _resource_changed ();
1164- } else {
1165- Array parent_meta = item->get_parent ()->get_metadata (0 );
1166- Ref<Resource> parent = parent_meta[0 ];
1220+ continue ;
1221+ }
1222+ Array parent_meta = item->get_parent ()->get_metadata (0 );
1223+ Ref<Resource> parent = parent_meta[0 ];
1224+ Variant::Type property_type = parent->get (meta[1 ]).get_type ();
1225+
1226+ if (property_type == Variant::OBJECT) {
11671227 parent->set (meta[1 ], unique_resource);
1228+ continue ;
1229+ }
1230+
1231+ Variant property = parent->get (meta[1 ]);
1232+
1233+ if (!parent_meta.has (property)) {
1234+ property = property.duplicate ();
1235+ parent->set (meta[1 ], property);
1236+ parent_meta.push_back (property); // Append Duplicated Type so we can check if it's already been duplicated.
1237+ }
1238+
1239+ if (property_type == Variant::ARRAY) {
1240+ Array arr = property;
1241+ arr[meta[2 ]] = unique_resource;
1242+ continue ;
1243+ }
1244+
1245+ Dictionary dict = property;
1246+ LocalVector<Variant> keys = dict.get_key_list ();
1247+
1248+ if (meta[2 ].get_type () == Variant::OBJECT) {
1249+ if (keys.has (meta[2 ])) {
1250+ // It's a key.
1251+ dict[unique_resource] = dict[meta[2 ]];
1252+ dict.erase (meta[2 ]);
1253+ parent_meta.push_back (unique_resource);
1254+ } else {
1255+ // If key has been erased, use last appended Resource key instead.
1256+ Variant key = keys.has (meta[3 ]) ? meta[3 ] : parent_meta.back ();
1257+ dict[key] = unique_resource;
1258+ }
1259+ } else {
1260+ dict[meta[2 ]] = unique_resource;
11681261 }
11691262 }
11701263}
0 commit comments