< Summary

Class:AvatarSystem.AvatarWithHologram
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs
Covered lines:57
Uncovered lines:19
Coverable lines:76
Total lines:150
Line coverage:75% (57 of 76)
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%
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.Threading;
 5using Cysharp.Threading.Tasks;
 6using GPUSkinning;
 7using UnityEngine;
 8
 9namespace AvatarSystem
 10{
 11    // [ADR 65 - https://github.com/decentraland/adr]
 12    public class AvatarWithHologram : 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;
 2424        private CancellationTokenSource disposeCts = new CancellationTokenSource();
 25        private readonly IBaseAvatar baseAvatar;
 26
 027        public IAvatar.Status status { get; private set; } = IAvatar.Status.Idle;
 028        public Vector3 extents { get; private set; }
 029        public int lodLevel => lod?.lodIndex ?? 0;
 30
 2431        public AvatarWithHologram(IBaseAvatar baseAvatar, IAvatarCurator avatarCurator, ILoader loader, IAnimator animat
 32        {
 2433            this.baseAvatar = baseAvatar;
 2434            this.avatarCurator = avatarCurator;
 2435            this.loader = loader;
 2436            this.animator = animator;
 2437            this.visibility = visibility;
 2438            this.lod = lod;
 2439            this.gpuSkinning = gpuSkinning;
 2440            this.gpuSkinningThrottler = gpuSkinningThrottler;
 2441            this.emoteAnimationEquipper = emoteAnimationEquipper;
 2442        }
 43
 44        /// <summary>
 45        /// Starts the loading process for the Avatar.
 46        /// </summary>
 47        /// <param name="wearablesIds"></param>
 48        /// <param name="settings"></param>
 49        /// <param name="ct"></param>
 50        public async UniTask Load(List<string> wearablesIds, List<string> emotesIds, AvatarSettings settings, Cancellati
 51        {
 452            disposeCts ??= new CancellationTokenSource();
 53
 454            status = IAvatar.Status.Idle;
 455            CancellationToken linkedCt = CancellationTokenSource.CreateLinkedTokenSource(ct, disposeCts.Token).Token;
 56
 457            linkedCt.ThrowIfCancellationRequested();
 58
 59            try
 60            {
 361                WearableItem bodyshape = null;
 362                WearableItem eyes = null;
 363                WearableItem eyebrows = null;
 364                WearableItem mouth = null;
 365                List<WearableItem> wearables = null;
 366                List<WearableItem> emotes = null;
 67
 368                baseAvatar.Initialize();
 369                animator.Prepare(settings.bodyshapeId, baseAvatar.GetArmatureContainer());
 370                (bodyshape, eyes, eyebrows, mouth, wearables, emotes) = await avatarCurator.Curate(settings, wearablesId
 271                if (!loader.IsValidForBodyShape(bodyshape, eyes, eyebrows, mouth))
 72                {
 273                    visibility.AddGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 74                }
 275                await loader.Load(bodyshape, eyes, eyebrows, mouth, wearables, settings, baseAvatar.GetMainRenderer(), l
 76
 77                //Scale the bounds due to the giant avatar not being skinned yet
 178                extents = loader.combinedRenderer.localBounds.extents * 2f / RESCALING_BOUNDS_FACTOR;
 79
 180                emoteAnimationEquipper.SetEquippedEmotes(settings.bodyshapeId, emotes);
 181                gpuSkinning.Prepare(loader.combinedRenderer);
 182                gpuSkinningThrottler.Bind(gpuSkinning);
 83
 184                visibility.Bind(gpuSkinning.renderer, loader.facialFeaturesRenderers);
 185                visibility.RemoveGlobalConstrain(LOADING_VISIBILITY_CONSTRAIN);
 86
 187                lod.Bind(gpuSkinning.renderer);
 188                gpuSkinningThrottler.Start();
 89
 190                status = IAvatar.Status.Loaded;
 191                await baseAvatar.FadeOut(loader.combinedRenderer.GetComponent<MeshRenderer>(), visibility.IsMainRenderVi
 192            }
 093            catch (OperationCanceledException)
 94            {
 095                Dispose();
 096                throw;
 97            }
 298            catch (Exception e)
 99            {
 2100                Dispose();
 2101                Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] for bodyshape:{settings
 2102                if (e.InnerException != null)
 0103                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 104                else
 2105                    throw;
 0106            }
 107            finally
 108            {
 3109                disposeCts?.Dispose();
 3110                disposeCts = null;
 111            }
 1112        }
 113
 114        public void AddVisibilityConstraint(string key)
 115        {
 0116            visibility.AddGlobalConstrain(key);
 0117            baseAvatar.CancelTransition();
 0118        }
 119
 120        public void RemoveVisibilityConstrain(string key)
 121        {
 0122            visibility.RemoveGlobalConstrain(key);
 0123        }
 124
 0125        public void PlayEmote(string emoteId, long timestamps) { animator?.PlayEmote(emoteId, timestamps); }
 126
 0127        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 128
 0129        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 130
 0131        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 132
 0133        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 134
 0135        public Transform[] GetBones() => loader.GetBones();
 136
 137        public void Dispose()
 138        {
 19139            status = IAvatar.Status.Idle;
 19140            disposeCts?.Cancel();
 19141            disposeCts?.Dispose();
 19142            disposeCts = null;
 19143            avatarCurator?.Dispose();
 19144            loader?.Dispose();
 19145            visibility?.Dispose();
 19146            lod?.Dispose();
 19147            gpuSkinningThrottler?.Dispose();
 19148        }
 149    }
 150}