< Summary

Class:AvatarSystem.AvatarWithHologram
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs
Covered lines:59
Uncovered lines:19
Coverable lines:78
Total lines:157
Line coverage:75.6% (59 of 78)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarWithHologram(...)0%110100%
Load()0%15.3113076.09%
AddVisibilityConstraint(...)0%2100%
RemoveVisibilityConstrain(...)0%2100%
PlayEmote(...)0%6200%
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/AvatarWithHologram.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Runtime.ExceptionServices;
 4using System.Security.Cryptography;
 5using System.Threading;
 6using Cysharp.Threading.Tasks;
 7using GPUSkinning;
 8using UnityEngine;
 9
 10namespace AvatarSystem
 11{
 12    // [ADR 65 - https://github.com/decentraland/adr]
 13    public class AvatarWithHologram : IAvatar
 14    {
 15        private const float RESCALING_BOUNDS_FACTOR = 100f;
 16        internal const string LOADING_VISIBILITY_CONSTRAIN = "Loading";
 17        private readonly IAvatarCurator avatarCurator;
 18        private readonly ILoader loader;
 19        private readonly IAnimator animator;
 20        private readonly IVisibility visibility;
 21        private readonly ILOD lod;
 22        private readonly IGPUSkinning gpuSkinning;
 23        private readonly IGPUSkinningThrottler gpuSkinningThrottler;
 24        private readonly IEmoteAnimationEquipper emoteAnimationEquipper;
 1425        private CancellationTokenSource disposeCts = new CancellationTokenSource();
 26        private readonly IBaseAvatar baseAvatar;
 27
 1528        public IAvatar.Status status { get; private set; } = IAvatar.Status.Idle;
 229        public Vector3 extents { get; private set; }
 030        public int lodLevel => lod?.lodIndex ?? 0;
 31
 1432        public AvatarWithHologram(IBaseAvatar baseAvatar, IAvatarCurator avatarCurator, ILoader loader, IAnimator animat
 33        {
 1434            this.baseAvatar = baseAvatar;
 1435            this.avatarCurator = avatarCurator;
 1436            this.loader = loader;
 1437            this.animator = animator;
 1438            this.visibility = visibility;
 1439            this.lod = lod;
 1440            this.gpuSkinning = gpuSkinning;
 1441            this.gpuSkinningThrottler = gpuSkinningThrottler;
 1442            this.emoteAnimationEquipper = emoteAnimationEquipper;
 1443        }
 44
 45        /// <summary>
 46        /// Starts the loading process for the Avatar.
 47        /// </summary>
 48        /// <param name="wearablesIds"></param>
 49        /// <param name="settings"></param>
 50        /// <param name="ct"></param>
 51        public async UniTask Load(List<string> wearablesIds, List<string> emotesIds, AvatarSettings settings, Cancellati
 52        {
 453            disposeCts ??= new CancellationTokenSource();
 54
 455            status = IAvatar.Status.Idle;
 456            CancellationToken linkedCt = CancellationTokenSource.CreateLinkedTokenSource(ct, disposeCts.Token).Token;
 57
 458            linkedCt.ThrowIfCancellationRequested();
 59
 60            try
 61            {
 362                WearableItem bodyshape = null;
 363                WearableItem eyes = null;
 364                WearableItem eyebrows = null;
 365                WearableItem mouth = null;
 366                List<WearableItem> wearables = null;
 367                List<WearableItem> emotes = null;
 68
 369                baseAvatar.Initialize();
 370                animator.Prepare(settings.bodyshapeId, baseAvatar.GetArmatureContainer());
 371                (bodyshape, eyes, eyebrows, mouth, wearables, emotes) = await avatarCurator.Curate(settings, wearablesId
 272                if (!loader.IsValidForBodyShape(bodyshape, eyes, eyebrows, mouth))
 73                {
 274                    visibility.AddGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 75                }
 276                await loader.Load(bodyshape, eyes, eyebrows, mouth, wearables, settings, baseAvatar.GetMainRenderer(), l
 77
 78                //Scale the bounds due to the giant avatar not being skinned yet
 179                extents = loader.combinedRenderer.localBounds.extents * 2f / RESCALING_BOUNDS_FACTOR;
 80
 181                emoteAnimationEquipper.SetEquippedEmotes(settings.bodyshapeId, emotes);
 182                gpuSkinning.Prepare(loader.combinedRenderer);
 183                gpuSkinningThrottler.Bind(gpuSkinning);
 84
 185                visibility.Bind(gpuSkinning.renderer, loader.facialFeaturesRenderers);
 186                visibility.RemoveGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 87
 188                lod.Bind(gpuSkinning.renderer);
 189                gpuSkinningThrottler.Start();
 90
 191                status = IAvatar.Status.Loaded;
 192                await baseAvatar.FadeOut(loader.combinedRenderer.GetComponent<MeshRenderer>(), visibility.IsMainRenderVi
 193            }
 094            catch (OperationCanceledException)
 95            {
 096                Dispose();
 097                throw;
 98            }
 299            catch (Exception e)
 100            {
 2101                Dispose();
 2102                Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] for bodyshape:{settings
 2103                if (e.InnerException != null)
 0104                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 105                else
 2106                    throw;
 0107            }
 108            finally
 109            {
 3110                disposeCts?.Dispose();
 3111                disposeCts = null;
 112            }
 1113        }
 114
 115        public void AddVisibilityConstraint(string key)
 116        {
 0117            visibility.AddGlobalConstrain(key);
 0118            baseAvatar.CancelTransition();
 0119        }
 120
 121        public void RemoveVisibilityConstrain(string key)
 122        {
 0123            visibility.RemoveGlobalConstrain(key);
 0124        }
 125
 126        public void PlayEmote(string emoteId, long timestamps)
 127        {
 0128            animator?.PlayEmote(emoteId, timestamps);
 0129        }
 130
 0131        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 132
 0133        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 134
 0135        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 136
 0137        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 138
 0139        public Transform[] GetBones() => loader.GetBones();
 140
 141        public Renderer GetMainRenderer() =>
 0142            gpuSkinning.renderer;
 143
 144        public void Dispose()
 145        {
 9146            status = IAvatar.Status.Idle;
 9147            disposeCts?.Cancel();
 9148            disposeCts?.Dispose();
 9149            disposeCts = null;
 9150            avatarCurator?.Dispose();
 9151            loader?.Dispose();
 9152            visibility?.Dispose();
 9153            lod?.Dispose();
 9154            gpuSkinningThrottler?.Dispose();
 9155        }
 156    }
 157}