< 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:140
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;
 101924        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
 101930        public Avatar(IAvatarCurator avatarCurator, ILoader loader, IAnimator animator, IVisibility visibility, ILOD lod
 31        {
 101932            this.avatarCurator = avatarCurator;
 101933            this.loader = loader;
 101934            this.animator = animator;
 101935            this.visibility = visibility;
 101936            this.lod = lod;
 101937            this.gpuSkinning = gpuSkinning;
 101938            this.gpuSkinningThrottler = gpuSkinningThrottler;
 101939            this.emoteAnimationEquipper = emoteAnimationEquipper;
 101940        }
 41
 42        /// <summary>
 43        /// Starts the loading process for the Avatar.
 44        /// </summary>
 45        /// <param name="wearablesIds"></param>
 46        /// <param name="emotesIds"></param>
 47        /// <param name="settings"></param>
 48        /// <param name="ct"></param>
 49        public async UniTask Load(List<string> wearablesIds, List<string> emotesIds, AvatarSettings settings, Cancellati
 50        {
 451            disposeCts ??= new CancellationTokenSource();
 52
 453            status = IAvatar.Status.Idle;
 454            CancellationToken linkedCt = CancellationTokenSource.CreateLinkedTokenSource(ct, disposeCts.Token).Token;
 55
 456            linkedCt.ThrowIfCancellationRequested();
 57
 58            try
 59            {
 360                WearableItem bodyshape = null;
 361                WearableItem eyes = null;
 362                WearableItem eyebrows = null;
 363                WearableItem mouth = null;
 364                List<WearableItem> wearables = null;
 365                List<WearableItem> emotes = null;
 66
 367                (bodyshape, eyes, eyebrows, mouth, wearables, emotes) = await avatarCurator.Curate(settings, wearablesId
 268                if (!loader.IsValidForBodyShape(bodyshape, eyes, eyebrows, mouth))
 69                {
 270                    visibility.AddGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 71                }
 272                await loader.Load(bodyshape, eyes, eyebrows, mouth, wearables, settings, linkedCt);
 73
 74                //Scale the bounds due to the giant avatar not being skinned yet
 275                extents = loader.combinedRenderer.localBounds.extents * 2f / RESCALING_BOUNDS_FACTOR;
 176                animator.Prepare(settings.bodyshapeId, loader.bodyshapeContainer);
 177                emoteAnimationEquipper.SetEquippedEmotes(settings.bodyshapeId, emotes);
 178                gpuSkinning.Prepare(loader.combinedRenderer);
 179                gpuSkinningThrottler.Bind(gpuSkinning);
 80
 181                visibility.Bind(gpuSkinning.renderer, loader.facialFeaturesRenderers);
 182                visibility.RemoveGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 83
 184                lod.Bind(gpuSkinning.renderer);
 185                gpuSkinningThrottler.Start();
 86
 187                status = IAvatar.Status.Loaded;
 188            }
 089            catch (OperationCanceledException)
 90            {
 091                Dispose();
 092                throw;
 93            }
 294            catch (Exception e)
 95            {
 296                Dispose();
 297                Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] " +
 98                          $"for bodyshape:{settings.bodyshapeId} and player {settings.playerName}");
 299                if (e.InnerException != null)
 0100                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 101                else
 2102                    throw;
 0103            }
 104            finally
 105            {
 3106                disposeCts?.Dispose();
 3107                disposeCts = null;
 108            }
 1109        }
 110
 10111        public void AddVisibilityConstrain(string key) { visibility.AddGlobalConstrain(key); }
 112
 2113        public void RemoveVisibilityConstrain(string key) { visibility.RemoveGlobalConstrain(key); }
 114
 4115        public void PlayEmote(string emoteId, long timestamps) { animator?.PlayEmote(emoteId, timestamps); }
 116
 0117        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 118
 0119        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 120
 0121        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 122
 0123        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 124
 0125        public Transform[] GetBones() => loader.GetBones();
 126
 127        public void Dispose()
 128        {
 1032129            status = IAvatar.Status.Idle;
 1032130            disposeCts?.Cancel();
 1032131            disposeCts?.Dispose();
 1032132            disposeCts = null;
 1032133            avatarCurator?.Dispose();
 1032134            loader?.Dispose();
 1032135            visibility?.Dispose();
 1032136            lod?.Dispose();
 1032137            gpuSkinningThrottler?.Dispose();
 1032138        }
 139    }
 140}