< Summary

Class:AvatarSystem.AvatarWithHologram
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarWithHologram.cs
Covered lines:58
Uncovered lines:15
Coverable lines:73
Total lines:145
Line coverage:79.4% (58 of 73)
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%
AddVisibilityConstrain(...)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;
 624        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; }
 129        public int lodLevel => lod?.lodIndex ?? 0;
 30
 631        public AvatarWithHologram(IBaseAvatar baseAvatar, IAvatarCurator avatarCurator, ILoader loader, IAnimator animat
 32        {
 633            this.baseAvatar = baseAvatar;
 634            this.avatarCurator = avatarCurator;
 635            this.loader = loader;
 636            this.animator = animator;
 637            this.visibility = visibility;
 638            this.lod = lod;
 639            this.gpuSkinning = gpuSkinning;
 640            this.gpuSkinningThrottler = gpuSkinningThrottler;
 641            this.emoteAnimationEquipper = emoteAnimationEquipper;
 642        }
 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, AvatarSettings settings, CancellationToken ct = default)
 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;
 91
 192                await baseAvatar.FadeOut(loader.combinedRenderer.GetComponent<MeshRenderer>(), lodLevel <= 1, linkedCt);
 93
 194            }
 095            catch (OperationCanceledException)
 96            {
 097                Dispose();
 098                throw;
 99            }
 2100            catch (Exception e)
 101            {
 2102                Dispose();
 2103                Debug.Log($"Avatar.Load failed with wearables:[{string.Join(",", wearablesIds)}] for bodyshape:{settings
 2104                if (e.InnerException != null)
 0105                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
 106                else
 2107                    throw;
 0108            }
 109            finally
 110            {
 3111                disposeCts?.Dispose();
 3112                disposeCts = null;
 113            }
 1114        }
 115
 0116        public void AddVisibilityConstrain(string key) { visibility.AddGlobalConstrain(key); }
 117
 0118        public void RemoveVisibilityConstrain(string key) { visibility.RemoveGlobalConstrain(key); }
 119
 0120        public void PlayEmote(string emoteId, long timestamps) { animator?.PlayEmote(emoteId, timestamps); }
 121
 0122        public void SetLODLevel(int lodIndex) { lod.SetLodIndex(lodIndex); }
 123
 0124        public void SetAnimationThrottling(int framesBetweenUpdate) { gpuSkinningThrottler.SetThrottling(framesBetweenUp
 125
 0126        public void SetImpostorTexture(Texture2D impostorTexture) { lod.SetImpostorTexture(impostorTexture); }
 127
 0128        public void SetImpostorTint(Color color) { lod.SetImpostorTint(color); }
 129
 0130        public Transform[] GetBones() => loader.GetBones();
 131
 132        public void Dispose()
 133        {
 6134            status = IAvatar.Status.Idle;
 6135            disposeCts?.Cancel();
 6136            disposeCts?.Dispose();
 6137            disposeCts = null;
 6138            avatarCurator?.Dispose();
 6139            loader?.Dispose();
 6140            visibility?.Dispose();
 6141            lod?.Dispose();
 6142            gpuSkinningThrottler?.Dispose();
 6143        }
 144    }
 145}