< Summary

Class:AvatarSystem.WearableLoader
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs
Covered lines:49
Uncovered lines:7
Coverable lines:56
Total lines:128
Line coverage:87.5% (49 of 56)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WearableLoader()0%110100%
WearableLoader(...)0%110100%
Load()0%12.2812087.5%
SetBones(...)0%2100%
FallbackToDefault()0%9.546053.85%
LoadWearable()0%4.184077.78%
Dispose()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableLoader.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3using System.Threading;
 4using Cysharp.Threading.Tasks;
 5using DCL;
 6using UnityEngine;
 7
 8namespace AvatarSystem
 9{
 10    public class WearableLoader : IWearableLoader
 11    {
 12        // TODO: This should be a service
 113        internal static IWearableItemResolver defaultWearablesResolver = new WearableItemResolver();
 14        static WearableLoader()
 15        {
 16            // Prewarm default wearables
 117            defaultWearablesResolver.Resolve(WearableLiterals.DefaultWearables.GetDefaultWearables());
 118        }
 19
 2320        public WearableItem wearable { get; }
 3621        public Rendereable rendereable => retriever?.rendereable;
 18622        public IWearableLoader.Status status { get; private set; }
 23
 24        private readonly IWearableRetriever retriever;
 25        private AvatarSettings currentSettings;
 26
 1627        public WearableLoader(IWearableRetriever retriever, WearableItem wearable)
 28        {
 1629            this.wearable = wearable;
 1630            this.retriever = retriever;
 1631        }
 32
 33        public async UniTask Load(GameObject container, AvatarSettings settings, CancellationToken ct = default)
 34        {
 1535            ct.ThrowIfCancellationRequested();
 36
 37            try
 38            {
 1439                bool bodyshapeDirty = currentSettings.bodyshapeId != settings.bodyshapeId;
 1440                currentSettings = settings;
 1441                if (status == IWearableLoader.Status.Succeeded && !bodyshapeDirty)
 42                {
 043                    AvatarSystemUtils.PrepareMaterialColors(rendereable, currentSettings.skinColor, currentSettings.hair
 044                    return;
 45                }
 46
 1447                retriever.Dispose();
 48
 49                try
 50                {
 3051                    await LoadWearable(container, wearable, settings.bodyshapeId, ct);
 1152                }
 153                catch (OperationCanceledException)
 54                {
 155                    throw;
 56                }
 257                catch (Exception e)
 58                {
 59                    // Ignored so we try to fallback (if needed)
 260                }
 61
 62                // Succeeded
 1363                if (rendereable != null)
 64                {
 965                    AvatarSystemUtils.PrepareMaterialColors(rendereable, currentSettings.skinColor, currentSettings.hair
 966                    status = IWearableLoader.Status.Succeeded;
 967                    return;
 68                }
 69
 70                //Try getting a default if category is needed
 471                if (AvatarSystemUtils.IsCategoryRequired(wearable.data.category))
 272                    await FallbackToDefault(container, ct);
 73
 474                if (rendereable != null)
 75                {
 276                    AvatarSystemUtils.PrepareMaterialColors(rendereable, currentSettings.skinColor, currentSettings.hair
 277                    status = IWearableLoader.Status.Defaulted;
 78                }
 79                else
 280                    status = IWearableLoader.Status.Failed;
 481            }
 182            catch (OperationCanceledException)
 83            {
 184                Dispose();
 185                throw;
 86            }
 1387        }
 88
 089        public void SetBones(Transform rootBone, Transform[] bones) { AvatarSystemUtils.CopyBones(rootBone, bones, rende
 90
 91        private async UniTask FallbackToDefault(GameObject container, CancellationToken ct)
 92        {
 293            ct.ThrowIfCancellationRequested();
 94
 95            try
 96            {
 297                string wearableId = WearableLiterals.DefaultWearables.GetDefaultWearable(currentSettings.bodyshapeId, we
 298                Debug.Log($"Falling back {wearable.id} to wearable {wearableId}");
 99
 2100                WearableItem defaultWearable = await defaultWearablesResolver.Resolve(wearableId, ct);
 101
 2102                await LoadWearable(container, defaultWearable, currentSettings.bodyshapeId, ct);
 2103            }
 0104            catch (OperationCanceledException)
 105            {
 106                //No disposing required
 0107                throw;
 108            }
 109
 2110        }
 111
 112        private async UniTask LoadWearable(GameObject container, WearableItem wearableToLoad, string bodyshapeId, Cancel
 113        {
 16114            ct.ThrowIfCancellationRequested();
 115
 16116            WearableItem.Representation representation = wearableToLoad.GetRepresentation(bodyshapeId);
 16117            if (representation == null)
 118            {
 0119                Debug.Log($"No representation for {bodyshapeId} of {wearableToLoad.id}");
 0120                return;
 121            }
 122
 32123            await retriever.Retrieve(container, wearableToLoad.GetContentProvider(bodyshapeId), wearableToLoad.baseUrlBu
 13124        }
 125
 16126        public void Dispose() { retriever?.Dispose(); }
 127    }
 128}