< Summary

Class:AvatarSystem.Avatar
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Avatar.cs
Covered lines:58
Uncovered lines:13
Coverable lines:71
Total lines:142
Line coverage:81.6% (58 of 71)
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%
AddVisibilityConstraint(...)0%110100%
RemoveVisibilityConstrain(...)0%2100%
PlayEmote(...)0%220100%
SetLODLevel(...)0%2100%
SetAnimationThrottling(...)0%2100%
SetImpostorTexture(...)0%2100%
SetImpostorTint(...)0%2100%
GetBones()0%2100%
GetMainRenderer()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;
 65624        private CancellationTokenSource disposeCts = new CancellationTokenSource();
 25
 66926        public IAvatar.Status status { get; private set; } = IAvatar.Status.Idle;
 227        public Vector3 extents { get; private set; }
 028        public int lodLevel => lod?.lodIndex ?? 0;
 29
 65630        internal Avatar(IAvatarCurator avatarCurator, ILoader loader, IAnimator animator, IVisibility visibility, ILOD l
 31        {
 65632            this.avatarCurator = avatarCurator;
 65633            this.loader = loader;
 65634            this.animator = animator;
 65635            this.visibility = visibility;
 65636            this.lod = lod;
 65637            this.gpuSkinning = gpuSkinning;
 65638            this.gpuSkinningThrottler = gpuSkinningThrottler;
 65639            this.emoteAnimationEquipper = emoteAnimationEquipper;
 65640        }
 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, List<string> emotesIds, AvatarSettings settings, Cancellati
 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)}] " +
 97                          $"for bodyshape:{settings.bodyshapeId} and player {settings.playerName}");
 298                if (e.InnerException != null)
 099                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 100                else
 2101                    throw;
 0102            }
 103            finally
 104            {
 3105                disposeCts?.Dispose();
 3106                disposeCts = null;
 107            }
 1108        }
 109
 2110        public void AddVisibilityConstraint(string key) { visibility.AddGlobalConstrain(key); }
 111
 0112        public void RemoveVisibilityConstrain(string key) { visibility.RemoveGlobalConstrain(key); }
 113
 4114        public void PlayEmote(string emoteId, long timestamps) { animator?.PlayEmote(emoteId, timestamps); }
 115
 0116        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 117
 0118        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 119
 0120        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 121
 0122        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 123
 0124        public Transform[] GetBones() => loader.GetBones();
 125
 126        public Renderer GetMainRenderer() =>
 0127            gpuSkinning.renderer;
 128
 129        public void Dispose()
 130        {
 663131            status = IAvatar.Status.Idle;
 663132            disposeCts?.Cancel();
 663133            disposeCts?.Dispose();
 663134            disposeCts = null;
 663135            avatarCurator?.Dispose();
 663136            loader?.Dispose();
 663137            visibility?.Dispose();
 663138            lod?.Dispose();
 663139            gpuSkinningThrottler?.Dispose();
 663140        }
 141    }
 142}