Skip to content

Commit 8b9802c

Browse files
Merge pull request #6208 from decentraland/release/2025-11-18
release: 2025-11-18
2 parents 3f6c4be + 7b6d5ce commit 8b9802c

460 files changed

Lines changed: 27042 additions & 1731 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ MonoBehaviour:
215215
m_ReadOnly: 0
216216
m_SerializedLabels: []
217217
FlaggedDuringContentUpdateRestriction: 0
218+
- m_GUID: c16a7c2b7d6b642a4822df00f8bd5f71
219+
m_Address: Assets/DCL/UI/ErrorPopup/Assets/ErrorPopupWithRetry.prefab
220+
m_ReadOnly: 0
221+
m_SerializedLabels: []
222+
FlaggedDuringContentUpdateRestriction: 0
218223
- m_GUID: c7939fa59480e654a8537b6fc2f007e3
219224
m_Address: MediaPlayer
220225
m_ReadOnly: 0
@@ -225,6 +230,11 @@ MonoBehaviour:
225230
m_ReadOnly: 0
226231
m_SerializedLabels: []
227232
FlaggedDuringContentUpdateRestriction: 0
233+
- m_GUID: d08e60223593f4abe8863c64316f3476
234+
m_Address: FlipLinearToGammaMaterial.mat
235+
m_ReadOnly: 0
236+
m_SerializedLabels: []
237+
FlaggedDuringContentUpdateRestriction: 0
228238
- m_GUID: d9a7adc162dc338449107a4654a26d50
229239
m_Address: WorldAudioContainer
230240
m_ReadOnly: 0

Explorer/Assets/AddressableAssetsData/AssetGroups/UI.asset

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ MonoBehaviour:
1515
m_GroupName: UI
1616
m_GUID: 9d34671c4a9995044aa4b38f0c1c3570
1717
m_SerializeEntries:
18+
- m_GUID: 000fc6d94dca3b64594f10aae8994ed7
19+
m_Address: Assets/DCL/SmartWearables/Assets/SmartWearablePopup.prefab
20+
m_ReadOnly: 0
21+
m_SerializedLabels: []
22+
FlaggedDuringContentUpdateRestriction: 0
1823
- m_GUID: 022077403db6945e58f0023757b0155f
1924
m_Address: Assets/DCL/ApplicationsGuards/ApplicationLivekitGuard/LivekitDownGuardPopup.prefab
2025
m_ReadOnly: 0
@@ -680,11 +685,6 @@ MonoBehaviour:
680685
m_ReadOnly: 0
681686
m_SerializedLabels: []
682687
FlaggedDuringContentUpdateRestriction: 0
683-
- m_GUID: dd40e574a59d9b348a7c02ca96be6ae9
684-
m_Address: Assets/DCL/Backpack/AvatarSection/Outfits/Slots/OutfitSlot.prefab
685-
m_ReadOnly: 0
686-
m_SerializedLabels: []
687-
FlaggedDuringContentUpdateRestriction: 0
688688
- m_GUID: de88bd0dde8feda4393664330ac8afb4
689689
m_Address: Assets/DCL/UI/GenericContextMenu/Prefabs/ToggleWithTitleIconAndCheck.prefab
690690
m_ReadOnly: 0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-nullable:enable

Explorer/Assets/DCL/ApplicationsGuards/csc.rsp.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Explorer/Assets/DCL/AvatarRendering/Emotes/Systems/FinalizeEmoteLoadingSystem.cs

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
using ECS.StreamableLoading.Common;
1616
using ECS.StreamableLoading.Common.Components;
1717
using ECS.StreamableLoading.GLTF;
18-
using SceneRunner.Scene;
1918
using System;
2019
using AssetBundlePromise = ECS.StreamableLoading.Common.AssetPromise<ECS.StreamableLoading.AssetBundles.AssetBundleData, ECS.StreamableLoading.AssetBundles.GetAssetBundleIntention>;
2120
using AudioPromise = ECS.StreamableLoading.Common.AssetPromise<ECS.StreamableLoading.AudioClips.AudioClipData, ECS.StreamableLoading.AudioClips.GetAudioClipIntention>;
@@ -71,59 +70,78 @@ ref EmotesFromRealmPromise promise
7170
}
7271

7372
[Query]
74-
private void FinalizeGltfLoading(
73+
private void FinalizeAssetBundleLoading(
7574
Entity entity,
76-
ref GltfPromise promise,
75+
ref AssetBundlePromise promise,
7776
ref IEmote emote,
7877
in BodyShape bodyShape)
7978
{
80-
FinalizeAssetLoading<GLTFData, GetGLTFIntention>(entity, ref promise, ref emote, bodyShape, result => result.ToRegularAsset());
79+
if (IsCancellationRequested(entity, ref promise, ref emote, in bodyShape))
80+
return;
81+
82+
if (promise.SafeTryConsume(World, GetReportCategory(), out StreamableLoadingResult<AssetBundleData> gltfAssetResult))
83+
{
84+
if (gltfAssetResult.Succeeded && gltfAssetResult.TryToConvertToRegularAsset(out AttachmentRegularAsset regularAssetResult))
85+
AssignEmoteResult(emote, bodyShape, regularAssetResult);
86+
else
87+
ReportHub.LogWarning(GetReportData(), $"The emote {emote.DTO.id} failed to load from the AB");
88+
89+
emote.UpdateLoadingStatus(false);
90+
World.Destroy(entity);
91+
}
8192
}
8293

8394
[Query]
84-
private void FinalizeAssetBundleLoading(
95+
private void FinalizeGltfLoading(
8596
Entity entity,
86-
ref AssetBundlePromise promise,
97+
ref GltfPromise promise,
8798
ref IEmote emote,
8899
in BodyShape bodyShape)
89100
{
90-
FinalizeAssetLoading<AssetBundleData, GetAssetBundleIntention>(entity, ref promise, ref emote, bodyShape, result => result.ToRegularAsset());
101+
if (IsCancellationRequested(entity, ref promise, ref emote, in bodyShape))
102+
return;
103+
104+
if (promise.SafeTryConsume(World, GetReportCategory(), out StreamableLoadingResult<GLTFData> gltfAssetResult))
105+
{
106+
if (gltfAssetResult.Succeeded && gltfAssetResult.TryToConvertToRegularAsset(out AttachmentRegularAsset regularAssetResult))
107+
AssignEmoteResult(emote, bodyShape, regularAssetResult);
108+
else
109+
ReportHub.LogWarning(GetReportData(), $"The emote {emote.DTO.id} failed to load from the GLTF");
110+
111+
emote.UpdateLoadingStatus(false);
112+
World.Destroy(entity);
113+
}
114+
}
115+
116+
private void AssignEmoteResult(IEmote emote, BodyShape bodyShape, AttachmentRegularAsset regularAssetResult)
117+
{
118+
var asset = new StreamableLoadingResult<AttachmentRegularAsset>(regularAssetResult);
119+
120+
if (emote.IsUnisex() && emote.HasSameClipForAllGenders())
121+
{
122+
emote.AssetResults[BodyShape.MALE] = asset;
123+
emote.AssetResults[BodyShape.FEMALE] = asset;
124+
}
125+
else
126+
emote.AssetResults[bodyShape] = asset;
91127
}
92128

93-
private void FinalizeAssetLoading<TAsset, TLoadingIntention>(
129+
private bool IsCancellationRequested<TAsset, TLoadingIntention>(
94130
Entity entity,
95131
ref AssetPromise<TAsset, TLoadingIntention> promise,
96132
ref IEmote emote,
97-
in BodyShape bodyShape,
98-
Func<StreamableLoadingResult<TAsset>, AttachmentRegularAsset> toRegularAsset)
133+
in BodyShape bodyShape)
99134
where TLoadingIntention: IAssetIntention, IEquatable<TLoadingIntention>
100135
{
101136
if (promise.LoadingIntention.CancellationTokenSource.IsCancellationRequested)
102137
{
103138
ResetEmoteResultOnCancellation(emote, bodyShape);
104139
promise.ForgetLoading(World);
105140
World.Destroy(entity);
106-
return;
141+
return true;
107142
}
108143

109-
if (promise.SafeTryConsume(World, GetReportCategory(), out StreamableLoadingResult<TAsset> result))
110-
{
111-
if (result.Succeeded)
112-
{
113-
var asset = new StreamableLoadingResult<AttachmentRegularAsset>(toRegularAsset.Invoke(result));
114-
115-
if (emote.IsUnisex() && emote.HasSameClipForAllGenders())
116-
{
117-
emote.AssetResults[BodyShape.MALE] = asset;
118-
emote.AssetResults[BodyShape.FEMALE] = asset;
119-
}
120-
else
121-
emote.AssetResults[bodyShape] = asset;
122-
}
123-
124-
emote.UpdateLoadingStatus(false);
125-
World.Destroy(entity);
126-
}
144+
return false;
127145
}
128146

129147
[Query]

Explorer/Assets/DCL/AvatarRendering/Wearables/ApplicationParametersWearablesProvider.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ public ApplicationParametersWearablesProvider(IAppArgs appArgs, IWearablesProvid
2727
this.builderDTOsUrl = builderDTOsUrl;
2828
}
2929

30-
public async UniTask<(IReadOnlyList<IWearable> results, int totalAmount)> GetAsync(int pageSize, int pageNumber, CancellationToken ct,
30+
public async UniTask<(IReadOnlyList<IWearable> results, int totalAmount)> GetAsync(int pageSize,
31+
int pageNumber,
32+
CancellationToken ct,
3133
IWearablesProvider.SortingField sortingField = IWearablesProvider.SortingField.Date,
3234
IWearablesProvider.OrderBy orderBy = IWearablesProvider.OrderBy.Descending,
3335
string? category = null,
3436
IWearablesProvider.CollectionType collectionType = IWearablesProvider.CollectionType.All,
37+
bool smartWearablesOnly = false,
3538
string? name = null,
3639
List<IWearable>? results = null,
3740
CommonLoadingArguments? loadingArguments = null,
@@ -74,7 +77,17 @@ await UniTask.WhenAll(RequestPointersAsync(pointers, BodyShape.MALE, ct),
7477
for (var i = 0; i < collections.Length; i++)
7578
{
7679
// localBuffer accumulates the loaded wearables
77-
await source.GetAsync(pageSize, pageNumber, ct, sortingField, orderBy, category, collectionType, name, localBuffer,
80+
await source.GetAsync(
81+
pageSize,
82+
pageNumber,
83+
ct,
84+
sortingField,
85+
orderBy,
86+
category,
87+
collectionType,
88+
smartWearablesOnly,
89+
name,
90+
localBuffer,
7891
loadingArguments: new CommonLoadingArguments(
7992
builderDTOsUrl.Replace(LoadingConstants.BUILDER_DTO_URL_COL_ID_PLACEHOLDER, collections[i]),
8093
cancellationTokenSource: new CancellationTokenSource()
@@ -100,6 +113,7 @@ await source.GetAsync(pageSize, pageNumber, ct, sortingField, orderBy, category,
100113
orderBy,
101114
category,
102115
collectionType,
116+
smartWearablesOnly,
103117
name,
104118
ownedPageBuffer
105119
);
@@ -130,7 +144,7 @@ await source.GetAsync(pageSize, pageNumber, ct, sortingField, orderBy, category,
130144
}
131145

132146
// Regular path without any "self-preview" element
133-
return await source.GetAsync(pageSize, pageNumber, ct, sortingField, orderBy, category, collectionType, name, results);
147+
return await source.GetAsync(pageSize, pageNumber, ct, sortingField, orderBy, category, collectionType, smartWearablesOnly, name, results);
134148
}
135149

136150
public async UniTask<IReadOnlyCollection<IWearable>?> RequestPointersAsync(IReadOnlyCollection<URN> pointers,

Explorer/Assets/DCL/AvatarRendering/Wearables/Components/Wearable.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ public enum WearableType : byte
2424
[Serializable]
2525
public class Wearable : IWearable
2626
{
27-
public StreamableLoadingResult<SceneAssetBundleManifest>? ManifestResult { get; set; }
28-
2927
public WearableAssets[] WearableAssetResults { get; } = new WearableAssets[BodyShape.COUNT];
3028

3129
public StreamableLoadingResult<WearableDTO> Model { get; set; }

Explorer/Assets/DCL/AvatarRendering/Wearables/ECSWearablesProvider.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class ECSWearablesProvider : IWearablesProvider
3333
private const string ON_CHAIN_COLLECTION_TYPE = "on-chain";
3434
private const string THIRD_PARTY_COLLECTION_TYPE = "third-party";
3535
private const string BASE_WEARABLE_COLLECTION_TYPE = "base-wearable";
36+
private const string IS_SMART_WEARABLE = "isSmartWearable";
3637

3738
private readonly string[] allWearableCategories = WearableCategories.CATEGORIES_PRIORITY.ToArray();
3839
private readonly IWeb3IdentityCache web3IdentityCache;
@@ -47,10 +48,17 @@ public ECSWearablesProvider(
4748
this.world = world;
4849
}
4950

50-
public async UniTask<(IReadOnlyList<IWearable> results, int totalAmount)> GetAsync(int pageSize, int pageNumber, CancellationToken ct,
51-
IWearablesProvider.SortingField sortingField = IWearablesProvider.SortingField.Date, IWearablesProvider.OrderBy orderBy = IWearablesProvider.OrderBy.Descending,
52-
string? category = null, IWearablesProvider.CollectionType collectionType = IWearablesProvider.CollectionType.All,
53-
string? name = null, List<IWearable>? results = null, CommonLoadingArguments? loadingArguments = null,
51+
public async UniTask<(IReadOnlyList<IWearable> results, int totalAmount)> GetAsync(int pageSize,
52+
int pageNumber,
53+
CancellationToken ct,
54+
IWearablesProvider.SortingField sortingField = IWearablesProvider.SortingField.Date,
55+
IWearablesProvider.OrderBy orderBy = IWearablesProvider.OrderBy.Descending,
56+
string? category = null,
57+
IWearablesProvider.CollectionType collectionType = IWearablesProvider.CollectionType.All,
58+
bool smartWearablesOnly = false,
59+
string? name = null,
60+
List<IWearable>? results = null,
61+
CommonLoadingArguments? loadingArguments = null,
5462
bool needsBuilderAPISigning = false)
5563
{
5664
requestParameters.Clear();
@@ -72,6 +80,9 @@ public ECSWearablesProvider(
7280
if ((collectionType & IWearablesProvider.CollectionType.ThirdParty) != 0)
7381
requestParameters.Add((COLLECTION_TYPE, THIRD_PARTY_COLLECTION_TYPE));
7482

83+
if (smartWearablesOnly)
84+
requestParameters.Add((IS_SMART_WEARABLE, "true"));
85+
7586
if (!string.IsNullOrEmpty(name))
7687
requestParameters.Add((SEARCH, name));
7788

Explorer/Assets/DCL/AvatarRendering/Wearables/Helpers/WearablePolymorphicBehaviour.cs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ private static void CreateRawWearablePromise<T>(
252252

253253
if (content.file.EndsWith(".glb")) // Wearables cannot be ".gltf"
254254
{
255-
var promise = RawGltfPromise.Create(world, GetGLTFIntention.Create(content.file, content.hash), partitionComponent);
255+
// We pass in the DTO content mappings (file -> hash) to the promise, so that external assets can be resolved
256+
var getGltf = GetGLTFIntention.Create(content.file, content.hash, false, wearable.DTO.content);
257+
var promise = RawGltfPromise.Create(world, getGltf, partitionComponent);
256258
world.Create(promise, wearable, intention.BodyShape, index);
257259
}
258260
else if (content.file.EndsWith(".png")) // Facial Feature Wearables documentation specifies PNG format
@@ -277,32 +279,46 @@ public static StreamableLoadingResult<AttachmentAssetBase> ToWearableAsset(this
277279
switch (wearable.Type)
278280
{
279281
case WearableType.FacialFeature:
280-
return new StreamableLoadingResult<AttachmentAssetBase>(new AttachmentTextureAsset(result.Asset!.GetAsset<Texture>(), result.Asset));
282+
{
283+
if (result.Asset.TryGetAsset(out Texture texture))
284+
return new StreamableLoadingResult<AttachmentAssetBase>(new AttachmentTextureAsset(texture, result.Asset));
285+
286+
return new StreamableLoadingResult<AttachmentAssetBase>(result.ReportData, new ArgumentException($"Failed to create facial feature asset for {wearable} from the AB"));
287+
}
281288
default:
282-
return new StreamableLoadingResult<AttachmentAssetBase>(ToRegularAsset(result));
289+
if (result.TryToConvertToRegularAsset(out AttachmentRegularAsset regularAsset))
290+
return new StreamableLoadingResult<AttachmentAssetBase>(regularAsset);
291+
292+
return new StreamableLoadingResult<AttachmentAssetBase>(result.ReportData, new ArgumentException($"Failed to create wearable asset for {wearable} from the AB"));
293+
283294
}
284295
}
285296

286297
// Raw GLTF Wearable
287-
public static StreamableLoadingResult<AttachmentAssetBase> ToWearableAsset(this StreamableLoadingResult<GLTFData> result, IWearable wearable)
298+
public static StreamableLoadingResult<AttachmentAssetBase> ToWearableAsset(this StreamableLoadingResult<GLTFData> result)
288299
{
289-
if (!result.Succeeded) return new StreamableLoadingResult<AttachmentAssetBase>(result.ReportData, result.Exception!);
300+
if (result.Succeeded && result.TryToConvertToRegularAsset(out AttachmentRegularAsset regularAsset))
301+
return new StreamableLoadingResult<AttachmentAssetBase>(regularAsset);
290302

291-
return new StreamableLoadingResult<AttachmentAssetBase>(ToRegularAsset(result));
303+
return new StreamableLoadingResult<AttachmentAssetBase>(result.ReportData, result.Exception!);
292304
}
293305

294306
// Raw Facial Feature Wearable
295-
public static StreamableLoadingResult<AttachmentAssetBase> ToWearableAsset(this StreamableLoadingResult<TextureData> result, IWearable wearable)
307+
public static StreamableLoadingResult<AttachmentAssetBase> ToWearableAsset(this StreamableLoadingResult<TextureData> result)
296308
{
297309
if (!result.Succeeded) return new StreamableLoadingResult<AttachmentAssetBase>(result.ReportData, result.Exception!);
298310

299311
// Has to be RGBA32 to work with the avatar shader TextureArrays (Unity cannot compress BC7 in runtime)
300312
return new StreamableLoadingResult<AttachmentAssetBase>(new AttachmentTextureAsset(TextureUtilities.EnsureRGBA32Format(result.Asset!.EnsureTexture2D()), result.Asset));
301313
}
302314

303-
public static AttachmentRegularAsset ToRegularAsset(this StreamableLoadingResult<AssetBundleData> result)
315+
public static bool TryToConvertToRegularAsset(this StreamableLoadingResult<AssetBundleData> result, out AttachmentRegularAsset regularAssetResult)
304316
{
305-
GameObject go = result.Asset!.GetAsset<GameObject>();
317+
if (!result.Asset.TryGetAsset(out GameObject go))
318+
{
319+
regularAssetResult = null;
320+
return false;
321+
}
306322

307323
// collect all renderers
308324
List<AttachmentRegularAsset.RendererInfo> rendererInfos = AttachmentRegularAsset.RENDERER_INFO_POOL.Get();
@@ -312,10 +328,12 @@ public static AttachmentRegularAsset ToRegularAsset(this StreamableLoadingResult
312328
foreach (SkinnedMeshRenderer skinnedMeshRenderer in pooledList.Value)
313329
rendererInfos.Add(new AttachmentRegularAsset.RendererInfo(skinnedMeshRenderer.sharedMaterial));
314330

315-
return new AttachmentRegularAsset(go, rendererInfos, result.Asset);
331+
regularAssetResult = new AttachmentRegularAsset(go, rendererInfos, result.Asset);
332+
return true;
316333
}
317334

318-
public static AttachmentRegularAsset ToRegularAsset(this StreamableLoadingResult<GLTFData> result)
335+
//GLTFs should never fail
336+
public static bool TryToConvertToRegularAsset(this StreamableLoadingResult<GLTFData> result, out AttachmentRegularAsset regularAssetResult)
319337
{
320338
GameObject go = result.Asset!.Root;
321339

@@ -327,7 +345,8 @@ public static AttachmentRegularAsset ToRegularAsset(this StreamableLoadingResult
327345
foreach (SkinnedMeshRenderer skinnedMeshRenderer in pooledList.Value)
328346
rendererInfos.Add(new AttachmentRegularAsset.RendererInfo(skinnedMeshRenderer.sharedMaterial));
329347

330-
return new AttachmentRegularAsset(go, rendererInfos, result.Asset);
348+
regularAssetResult = new AttachmentRegularAsset(go, rendererInfos, result.Asset);
349+
return true;
331350
}
332351

333352
public static bool HasEssentialAssetsResolved(this IWearable wearable, BodyShape bodyShape)

0 commit comments

Comments
 (0)