< Summary

Class:AvatarSystem.BodyShapeLoader
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/BodyShapeLoader.cs
Covered lines:106
Uncovered lines:15
Coverable lines:121
Total lines:202
Line coverage:87.6% (106 of 121)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
BodyShapeLoader(...)0%110100%
Load()0%11.3810076%
SetBones(...)0%2100%
LoadMouth()0%8.66058.33%
LoadEyebrows()0%8.66058.33%
LoadEyes()0%8.66058.33%
UpdateColors(...)0%770100%
LoadWearable()0%5.395075%
IsValid(...)0%3801900%
DisableFacialRenderers()0%440100%
Dispose()0%990100%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5using Cysharp.Threading.Tasks;
 6using DCL;
 7using DCL.Helpers;
 8using UnityEngine;
 9using DCL.Shaders;
 10using Object = UnityEngine.Object;
 11
 12namespace AvatarSystem
 13{
 14    public class BodyShapeLoader : IBodyshapeLoader
 15    {
 4916        public WearableItem wearable { get; }
 117        public Rendereable rendereable => bodyshapeRetriever?.rendereable;
 4718        public IWearableLoader.Status status { get; private set; }
 319        public WearableItem eyes { get; }
 320        public WearableItem eyebrows { get; }
 321        public WearableItem mouth { get; }
 4922        public SkinnedMeshRenderer eyesRenderer { get; internal set; }
 4923        public SkinnedMeshRenderer eyebrowsRenderer { get; internal set; }
 4924        public SkinnedMeshRenderer mouthRenderer { get; internal set; }
 2025        public SkinnedMeshRenderer headRenderer { get; private set; }
 2026        public SkinnedMeshRenderer feetRenderer { get; private set; }
 2027        public SkinnedMeshRenderer upperBodyRenderer { get; private set; }
 2028        public SkinnedMeshRenderer lowerBodyRenderer { get; private set; }
 29
 30        internal readonly IWearableRetriever bodyshapeRetriever;
 31        internal readonly IFacialFeatureRetriever eyesRetriever;
 32        internal readonly IFacialFeatureRetriever eyebrowsRetriever;
 33        internal readonly IFacialFeatureRetriever mouthRetriever;
 34
 1235        private readonly Dictionary<SkinnedMeshRenderer, (Transform rootBone, Transform[] bones)> originalBones = new Di
 36
 1237        public BodyShapeLoader(IRetrieverFactory retrieverFactory, WearableItem bodyshape, WearableItem eyes, WearableIt
 38        {
 1239            wearable = bodyshape;
 1240            this.eyes = eyes;
 1241            this.eyebrows = eyebrows;
 1242            this.mouth = mouth;
 43
 1244            bodyshapeRetriever = retrieverFactory.GetWearableRetriever();
 1245            eyesRetriever = retrieverFactory.GetFacialFeatureRetriever();
 1246            eyebrowsRetriever = retrieverFactory.GetFacialFeatureRetriever();
 1247            mouthRetriever = retrieverFactory.GetFacialFeatureRetriever();
 1248        }
 49
 50        public async UniTask Load(GameObject container, AvatarSettings avatarSettings, CancellationToken ct = default)
 51        {
 1052            ct.ThrowIfCancellationRequested();
 53
 54            try
 55            {
 956                if (status == IWearableLoader.Status.Succeeded)
 57                {
 058                    UpdateColors(avatarSettings);
 059                    return;
 60                }
 61
 962                status = IWearableLoader.Status.Idle;
 963                await LoadWearable(container, ct);
 64                // Store the original bones.
 165                originalBones.Clear();
 1666                foreach (SkinnedMeshRenderer skm in bodyshapeRetriever.rendereable.renderers.OfType<SkinnedMeshRenderer>
 67                {
 768                    originalBones[skm] = (skm.rootBone, skm.bones);
 69                }
 70
 171                (headRenderer, upperBodyRenderer, lowerBodyRenderer, feetRenderer, eyesRenderer, eyebrowsRenderer, mouth
 72
 173                await (LoadEyes(ct), LoadEyebrows(ct), LoadMouth(ct));
 74
 175                UpdateColors(avatarSettings);
 176                status = IWearableLoader.Status.Succeeded;
 177            }
 878            catch (Exception)
 79            {
 880                status = IWearableLoader.Status.Failed;
 881                Dispose();
 882                throw;
 83            }
 184        }
 85
 086        public void SetBones(Transform rootBone, Transform[] bones) { AvatarSystemUtils.CopyBones(rootBone, bones, rende
 87
 88        private async UniTask LoadMouth(CancellationToken ct)
 89        {
 190            if (mouth == null) return;
 191            (Texture main, Texture mask) = await mouthRetriever.Retrieve(mouth, wearable.id, ct);
 192            mouthRenderer.material = new Material(Resources.Load<Material>("Mouth Material"));
 193            if (main == null)
 094                throw new Exception($"Couldn't fetch main texture for {mouth.id}");
 195            mouthRenderer.material.SetTexture(ShaderUtils.BaseMap, main);
 196            if (mask != null)
 097                mouthRenderer.material.SetTexture(ShaderUtils.TintMask, mask);
 198        }
 99
 100        private async UniTask LoadEyebrows(CancellationToken ct)
 101        {
 1102            if (eyebrows == null) return;
 1103            (Texture main, Texture mask) = await eyebrowsRetriever.Retrieve(eyebrows, wearable.id, ct);
 1104            eyebrowsRenderer.material = new Material(Resources.Load<Material>("Eyebrow Material"));
 1105            if (main == null)
 0106                throw new Exception($"Couldn't fetch main texture for {eyebrows.id}");
 1107            eyebrowsRenderer.material.SetTexture(ShaderUtils.BaseMap, main);
 1108            if (mask != null)
 0109                eyebrowsRenderer.material.SetTexture(ShaderUtils.BaseMap, mask);
 1110        }
 111
 112        private async UniTask LoadEyes(CancellationToken ct)
 113        {
 1114            if (eyes == null) return;
 1115            (Texture main, Texture mask) = await eyesRetriever.Retrieve(eyes, wearable.id, ct);
 1116            eyesRenderer.material = new Material(Resources.Load<Material>("Eye Material"));
 1117            if (main == null)
 0118                throw new Exception($"Couldn't fetch main texture for {eyes.id}");
 1119            eyesRenderer.material.SetTexture(ShaderUtils.EyesTexture, main);
 1120            if (mask != null)
 0121                eyesRenderer.material.SetTexture(ShaderUtils.IrisMask, mask);
 1122        }
 123
 124        private void UpdateColors(AvatarSettings avatarSettings)
 125        {
 1126            AvatarSystemUtils.PrepareMaterialColors(rendereable, avatarSettings.skinColor, avatarSettings.hairColor);
 1127            eyesRenderer?.material?.SetColor(ShaderUtils.EyeTint, avatarSettings.eyesColor);
 1128            eyebrowsRenderer?.material?.SetColor(ShaderUtils.BaseColor, avatarSettings.hairColor);
 1129            mouthRenderer?.material?.SetColor(ShaderUtils.BaseColor, avatarSettings.skinColor);
 1130        }
 131
 132        private async UniTask<Rendereable> LoadWearable(GameObject container, CancellationToken ct)
 133        {
 9134            ct.ThrowIfCancellationRequested();
 135
 9136            bodyshapeRetriever.Dispose();
 137
 9138            WearableItem.Representation representation = wearable.GetRepresentation(wearable.id);
 9139            if (representation == null)
 0140                throw new Exception("Couldn't find a representation for this bodyshape");
 141
 9142            Rendereable bodyshapeRenderable = await bodyshapeRetriever.Retrieve(container, wearable.GetContentProvider(w
 143
 8144            if (bodyshapeRenderable == null) // fail safe, we shouldnt reach this since .Retrieve should throw if anythi
 7145                throw new Exception("Couldn't load bodyshape");
 146
 1147            return bodyshapeRenderable;
 1148        }
 149
 150        public bool IsValid(WearableItem bodyshape, WearableItem eyebrows, WearableItem eyes, WearableItem mouth)
 151        {
 0152            if (wearable.id != bodyshape?.id) return false;
 0153            if (this.eyebrows?.id != eyebrows?.id) return false;
 0154            if (this.mouth?.id != mouth?.id) return false;
 0155            if (this.eyes?.id != eyes?.id) return false;
 0156            return true;
 157        }
 158
 159        public void DisableFacialRenderers()
 160        {
 1161            if (eyesRenderer != null)
 1162                eyesRenderer.enabled = false;
 1163            if (eyebrowsRenderer != null)
 1164                eyebrowsRenderer.enabled = false;
 1165            if (mouthRenderer != null)
 1166                mouthRenderer.enabled = false;
 1167        }
 168
 169        public void Dispose()
 170        {
 19171            status = IWearableLoader.Status.Idle;
 172
 173            //Restore bones
 52174            foreach ((SkinnedMeshRenderer skm, (Transform rootBone, Transform[] bones)) in originalBones)
 175            {
 7176                skm.rootBone = rootBone;
 7177                skm.bones = bones;
 178            }
 19179            originalBones.Clear();
 180
 19181            bodyshapeRetriever?.Dispose();
 19182            eyesRetriever?.Dispose();
 19183            eyebrowsRetriever?.Dispose();
 19184            mouthRetriever?.Dispose();
 185
 19186            if (eyesRenderer != null)
 2187                Object.Destroy(eyesRenderer.material);
 19188            if (eyebrowsRenderer != null)
 2189                Object.Destroy(eyebrowsRenderer.material);
 19190            if (mouthRenderer != null)
 2191                Object.Destroy(mouthRenderer.material);
 192
 19193            upperBodyRenderer = null;
 19194            lowerBodyRenderer = null;
 19195            feetRenderer = null;
 19196            headRenderer = null;
 19197            eyesRenderer = null;
 19198            eyebrowsRenderer = null;
 19199            mouthRenderer = null;
 19200        }
 201    }
 202}