66using MainScripts . DCL . Controllers . HUD . CharacterPreview ;
77using System ;
88using System . Collections . Generic ;
9+ using System . Linq ;
910using System . Text ;
1011using System . Threading ;
1112using UnityEngine ;
@@ -26,6 +27,30 @@ public class BackpackEditorHUDController
2627 private readonly OutfitsController outfitsController ;
2728 private readonly IVRMExporter vrmExporter ;
2829 private readonly IDCLFileBrowserService fileBrowser ;
30+ private readonly Dictionary < string , Dictionary < string , string > > fallbackWearables = new ( )
31+ {
32+ { "urn:decentraland:off-chain:base-avatars:BaseFemale" , new Dictionary < string , string >
33+ {
34+ { WearableLiterals . Categories . UPPER_BODY , "urn:decentraland:off-chain:base-avatars:f_blue_jacket" } ,
35+ { WearableLiterals . Categories . LOWER_BODY , "urn:decentraland:off-chain:base-avatars:f_capris" } ,
36+ { WearableLiterals . Categories . FEET , "urn:decentraland:off-chain:base-avatars:ruby_blue_loafer" } ,
37+ { WearableLiterals . Categories . HAIR , "urn:decentraland:off-chain:base-avatars:pony_tail" } ,
38+ { WearableLiterals . Categories . MOUTH , "urn:decentraland:off-chain:base-avatars:f_mouth_05" } ,
39+ { WearableLiterals . Categories . EYEBROWS , "urn:decentraland:off-chain:base-avatars:f_eyebrows_02" } ,
40+ { WearableLiterals . Categories . EYES , "urn:decentraland:off-chain:base-avatars:f_eyes_06" } ,
41+ } } ,
42+ { "urn:decentraland:off-chain:base-avatars:BaseMale" , new Dictionary < string , string >
43+ {
44+ { WearableLiterals . Categories . UPPER_BODY , "urn:decentraland:off-chain:base-avatars:m_sweater_02" } ,
45+ { WearableLiterals . Categories . LOWER_BODY , "urn:decentraland:off-chain:base-avatars:comfortablepants" } ,
46+ { WearableLiterals . Categories . FEET , "urn:decentraland:off-chain:base-avatars:Espadrilles" } ,
47+ { WearableLiterals . Categories . HAIR , "urn:decentraland:off-chain:base-avatars:cool_hair" } ,
48+ { WearableLiterals . Categories . FACIAL_HAIR , "urn:decentraland:off-chain:base-avatars:beard" } ,
49+ { WearableLiterals . Categories . EYEBROWS , "urn:decentraland:off-chain:base-avatars:eyebrows_00" } ,
50+ { WearableLiterals . Categories . EYES , "urn:decentraland:off-chain:base-avatars:eyes_00" } ,
51+ } }
52+ } ;
53+
2954 private string currentSlotSelected ;
3055 private bool avatarIsDirty ;
3156 private CancellationTokenSource loadProfileCancellationToken = new ( ) ;
@@ -350,7 +375,8 @@ private void UpdateAvatarPreview()
350375
351376 // We always keep the loaded emotes into the Avatar Preview
352377 foreach ( string emoteId in dataStore . emotesCustomization . currentLoadedEmotes . Get ( ) )
353- modelToUpdate . emotes . Add ( new AvatarModel . AvatarEmoteEntry ( ) { urn = emoteId } ) ;
378+ modelToUpdate . emotes . Add ( new AvatarModel . AvatarEmoteEntry
379+ { urn = emoteId } ) ;
354380
355381 UpdateAvatarModel ( modelToUpdate ) ;
356382 }
@@ -508,6 +534,7 @@ private void EquipWearable(WearableItem wearable,
508534 {
509535 UnEquipCurrentBodyShape ( ) ;
510536 EquipBodyShape ( wearable ) ;
537+ ReplaceIncompatibleWearablesWithDefaultWearables ( ) ;
511538 }
512539 else
513540 {
@@ -526,7 +553,7 @@ private void EquipWearable(WearableItem wearable,
526553 if ( resetOverride )
527554 ResetOverridesOfAffectedCategories ( wearable , setAsDirty ) ;
528555
529- avatarSlotsHUDController . Equip ( wearable , ownUserProfile . avatar . bodyShape , model . forceRender ) ;
556+ avatarSlotsHUDController . Equip ( wearable , model . bodyShape . id , model . forceRender ) ;
530557 wearableGridController . Equip ( wearableId ) ;
531558 }
532559
@@ -543,6 +570,36 @@ private void EquipWearable(WearableItem wearable,
543570 }
544571 }
545572
573+ private void ReplaceIncompatibleWearablesWithDefaultWearables ( )
574+ {
575+ WearableItem bodyShape = model . bodyShape ;
576+
577+ if ( bodyShape == null ) return ;
578+ if ( ! fallbackWearables . ContainsKey ( bodyShape . id ) ) return ;
579+
580+ HashSet < string > replacedCategories = new ( ) ;
581+
582+ foreach ( var w in model . wearables . Values . ToArray ( ) )
583+ {
584+ if ( w . SupportsBodyShape ( bodyShape . id ) ) continue ;
585+
586+ UnEquipWearable ( w , UnequipWearableSource . None , true , false ) ;
587+
588+ string category = w . data . category ;
589+
590+ if ( ! string . IsNullOrEmpty ( category ) && ! replacedCategories . Contains ( category ) )
591+ replacedCategories . Add ( category ) ;
592+ }
593+
594+ Dictionary < string , string > fallbackWearablesByCategory = fallbackWearables [ bodyShape . id ] ;
595+
596+ foreach ( string category in replacedCategories )
597+ {
598+ if ( ! fallbackWearablesByCategory . ContainsKey ( category ) ) continue ;
599+ EquipWearable ( fallbackWearablesByCategory [ category ] , EquipWearableSource . None , true , false ) ;
600+ }
601+ }
602+
546603 private void UnEquipCurrentBodyShape ( bool setAsDirty = true )
547604 {
548605 if ( model . bodyShape . id == "NOT_LOADED" ) return ;
0 commit comments