< Summary

Class:AvatarSystem.Avatar
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs
Covered lines:57
Uncovered lines:13
Coverable lines:70
Total lines:138
Line coverage:81.4% (57 of 70)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Avatar(...)0%110100%
Load()0%12.1911078.57%
AddVisibilityConstrain(...)0%110100%
RemoveVisibilityConstrain(...)0%110100%
PlayEmote(...)0%220100%
SetLODLevel(...)0%2100%
SetAnimationThrottling(...)0%2100%
SetImpostorTexture(...)0%2100%
SetImpostorTint(...)0%2100%
GetBones()0%2100%
Dispose()0%880100%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Runtime.ExceptionServices;
 4using System.Threading;
 5using Cysharp.Threading.Tasks;
 6using GPUSkinning;
 7using UnityEngine;
 8
 9namespace AvatarSystem
 10{
 11    // [ADR 65 - https://github.com/decentraland/adr]
 12    public class Avatar : IAvatar
 13    {
 14        private const float RESCALING_BOUNDS_FACTOR = 100f;
 15        internal const string LOADING_VISIBILITY_CONSTRAIN = "Loading";
 16        private readonly IAvatarCurator avatarCurator;
 17        private readonly ILoader loader;
 18        private readonly IAnimator animator;
 19        private readonly IVisibility visibility;
 20        private readonly ILOD lod;
 21        private readonly IGPUSkinning gpuSkinning;
 22        private readonly IGPUSkinningThrottler gpuSkinningThrottler;
 23        private readonly IEmoteAnimationEquipper emoteAnimationEquipper;
 101724        private CancellationTokenSource disposeCts = new CancellationTokenSource();
 25
 026        public IAvatar.Status status { get; private set; } = IAvatar.Status.Idle;
 027        public Vector3 extents { get; private set; }
 028        public int lodLevel => lod?.lodIndex ?? 0;
 29
 101730        public Avatar(IAvatarCurator avatarCurator, ILoader loader, IAnimator animator, IVisibility visibility, ILOD lod
 31        {
 101732            this.avatarCurator = avatarCurator;
 101733            this.loader = loader;
 101734            this.animator = animator;
 101735            this.visibility = visibility;
 101736            this.lod = lod;
 101737            this.gpuSkinning = gpuSkinning;
 101738            this.gpuSkinningThrottler = gpuSkinningThrottler;
 101739            this.emoteAnimationEquipper = emoteAnimationEquipper;
 101740        }
 41
 42        /// <summary>
 43        /// Starts the loading process for the Avatar.
 44        /// </summary>
 45        /// <param name="wearablesIds"></param>
 46        /// <param name="settings"></param>
 47        /// <param name="ct"></param>
 48        public async UniTask Load(List<string> wearablesIds, AvatarSettings settings, CancellationToken ct = default)
 49        {
 450            disposeCts ??= new CancellationTokenSource();
 51
 452            status = IAvatar.Status.Idle;
 453            CancellationToken linkedCt = CancellationTokenSource.CreateLinkedTokenSource(ct, disposeCts.Token).Token;
 54
 455            linkedCt.ThrowIfCancellationRequested();
 56
 57            try
 58            {
 359                WearableItem bodyshape = null;
 360                WearableItem eyes = null;
 361                WearableItem eyebrows = null;
 362                WearableItem mouth = null;
 363                List<WearableItem> wearables = null;
 364                List<WearableItem> emotes = null;
 65
 366                (bodyshape, eyes, eyebrows, mouth, wearables, emotes) = await avatarCurator.Curate(settings, wearablesId
 267                if (!loader.IsValidForBodyShape(bodyshape, eyes, eyebrows, mouth))
 68                {
 269                    visibility.AddGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 70                }
 271                await loader.Load(bodyshape, eyes, eyebrows, mouth, wearables, settings, linkedCt);
 72
 73                //Scale the bounds due to the giant avatar not being skinned yet
 274                extents = loader.combinedRenderer.localBounds.extents * 2f / RESCALING_BOUNDS_FACTOR;
 175                animator.Prepare(settings.bodyshapeId, loader.bodyshapeContainer);
 176                emoteAnimationEquipper.SetEquippedEmotes(settings.bodyshapeId, emotes);
 177                gpuSkinning.Prepare(loader.combinedRenderer);
 178                gpuSkinningThrottler.Bind(gpuSkinning);
 79
 180                visibility.Bind(gpuSkinning.renderer, loader.facialFeaturesRenderers);
 181                visibility.RemoveGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 82
 183                lod.Bind(gpuSkinning.renderer);
 184                gpuSkinningThrottler.Start();
 85
 186                status = IAvatar.Status.Loaded;
 187            }
 088            catch (OperationCanceledException)
 89            {
 090                Dispose();
 091                throw;
 92            }
 293            catch (Exception e)
 94            {
 295                Dispose();
 296                Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] for bodyshape:{settings
 297                if (e.InnerException != null)
 098                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 99                else
 2100                    throw;
 0101            }
 102            finally
 103            {
 3104                disposeCts?.Dispose();
 3105                disposeCts = null;
 106            }
 1107        }
 108
 10109        public void AddVisibilityConstrain(string key) { visibility.AddGlobalConstrain(key); }
 110
 2111        public void RemoveVisibilityConstrain(string key) { visibility.RemoveGlobalConstrain(key); }
 112
 4113        public void PlayEmote(string emoteId, long timestamps) { animator?.PlayEmote(emoteId, timestamps); }
 114
 0115        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 116
 0117        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 118
 0119        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 120
 0121        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 122
 0123        public Transform[] GetBones() => loader.GetBones();
 124
 125        public void Dispose()
 126        {
 1030127            status = IAvatar.Status.Idle;
 1030128            disposeCts?.Cancel();
 1030129            disposeCts?.Dispose();
 1030130            disposeCts = null;
 1030131            avatarCurator?.Dispose();
 1030132            loader?.Dispose();
 1030133            visibility?.Dispose();
 1030134            lod?.Dispose();
 1030135            gpuSkinningThrottler?.Dispose();
 1030136        }
 137    }
 138}