< Summary

Class:DCL.AvatarsLODController
Assembly:AvatarShape
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarLOD/AvatarsLODController.cs
Covered lines:79
Uncovered lines:13
Coverable lines:92
Total lines:187
Line coverage:85.8% (79 of 92)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarsLODController()0%110100%
OnFeatureFlagChanged(...)0%6200%
Initialize(...)0%5.25080%
RegisterAvatar(...)0%330100%
CreateLodController(...)0%2100%
UnregisterAvatar(...)0%220100%
Update()0%220100%
UpdateLODsBillboard()0%330100%
UpdateAllLODs(...)0%660100%
ComposeLODControllersSortedByDistance(...)0%220100%
DistanceToOwnPlayer(...)0%330100%
IsInFrontOfCamera(...)0%110100%
Dispose()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarLOD/AvatarsLODController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using UnityEngine;
 5using DCL.Interface;
 6
 7namespace DCL
 8{
 9    public class AvatarsLODController : IAvatarsLODController
 10    {
 11        internal const string AVATAR_LODS_FLAG_NAME = "avatar_lods";
 12        internal const float RENDERED_DOT_PRODUCT_ANGLE = 0.25f;
 13
 014        private BaseDictionary<string, Player> otherPlayers => DataStore.i.player.otherPlayers;
 015        private BaseVariable<float> simpleAvatarDistance => DataStore.i.avatarsLOD.simpleAvatarDistance;
 016        private BaseVariable<float> LODDistance => DataStore.i.avatarsLOD.LODDistance;
 017        private BaseVariable<int> maxAvatars => DataStore.i.avatarsLOD.maxAvatars;
 018        private BaseVariable<int> maxImpostors => DataStore.i.avatarsLOD.maxImpostors;
 019        private BaseHashSet<string> visibleNames => DataStore.i.avatarsLOD.visibleNames;
 20        private Vector3 cameraPosition;
 21        private Vector3 cameraForward;
 22        private GPUSkinningThrottlingCurveSO gpuSkinningThrottlingCurve;
 23
 67824        internal readonly Dictionary<string, IAvatarLODController> lodControllers = new Dictionary<string, IAvatarLODCon
 25        internal bool enabled;
 26
 67827        public AvatarsLODController()
 28        {
 67829            gpuSkinningThrottlingCurve = Resources.Load<GPUSkinningThrottlingCurveSO>("GPUSkinningThrottlingCurve");
 67830            DataStore.i.featureFlags.flags.OnChange += OnFeatureFlagChanged;
 67831        }
 32
 33        private void OnFeatureFlagChanged(FeatureFlag current, FeatureFlag previous)
 34        {
 035            if (enabled == current.IsFeatureEnabled(AVATAR_LODS_FLAG_NAME))
 036                return;
 037            Initialize(current);
 038        }
 39
 40        internal void Initialize(FeatureFlag current)
 41        {
 442            enabled = current.IsFeatureEnabled(AVATAR_LODS_FLAG_NAME);
 443            if (!enabled)
 044                return;
 45
 846            foreach (IAvatarLODController lodController in lodControllers.Values)
 47            {
 048                lodController.Dispose();
 49            }
 450            lodControllers.Clear();
 51
 1252            foreach (var keyValuePair in otherPlayers.Get())
 53            {
 254                RegisterAvatar(keyValuePair.Key, keyValuePair.Value);
 55            }
 456            otherPlayers.OnAdded += RegisterAvatar;
 457            otherPlayers.OnRemoved += UnregisterAvatar;
 458        }
 59
 60        public void RegisterAvatar(string id, Player player)
 61        {
 562            if (!enabled || lodControllers.ContainsKey(id))
 163                return;
 64
 465            lodControllers.Add(id, CreateLodController(player));
 466        }
 67
 068        protected internal virtual IAvatarLODController CreateLodController(Player player) => new AvatarLODController(pl
 69
 70        public void UnregisterAvatar(string id, Player player)
 71        {
 372            if (!lodControllers.ContainsKey(id))
 173                return;
 74
 275            lodControllers[id].Dispose();
 276            lodControllers.Remove(id);
 277        }
 78
 79        public void Update()
 80        {
 1861281            if (!enabled)
 1860482                return;
 83
 884            cameraPosition = CommonScriptableObjects.cameraPosition.Get();
 885            cameraForward = CommonScriptableObjects.cameraForward.Get();
 86
 887            UpdateAllLODs(maxAvatars.Get(), maxImpostors.Get());
 888            UpdateLODsBillboard();
 889        }
 90
 91        internal void UpdateLODsBillboard()
 92        {
 7093            foreach (var kvp in lodControllers)
 94            {
 2795                Player player = kvp.Value.player;
 96
 2797                if (!IsInFrontOfCamera(player.worldPosition))
 98                    continue;
 99
 25100                Vector3 previousForward = player.forwardDirection;
 25101                Vector3 lookAtDir = (cameraPosition - player.worldPosition).normalized;
 102
 25103                lookAtDir.y = previousForward.y;
 25104                player.renderer.SetImpostorForward(lookAtDir);
 105            }
 8106        }
 107
 108        internal void UpdateAllLODs(int maxAvatars = DataStore.DataStore_AvatarsLOD.DEFAULT_MAX_AVATAR, int maxImpostors
 109        {
 10110            int avatarsCount = 0; //Full Avatar + Simple Avatar
 10111            int impostorCount = 0; //Impostor
 112
 10113            float lodDistance = LODDistance.Get();
 10114            float simpleAvatarDistance = this.simpleAvatarDistance.Get();
 10115            Vector3 ownPlayerPosition = CommonScriptableObjects.playerUnityPosition.Get();
 116
 10117            (IAvatarLODController lodController, float distance)[] lodControllersByDistance = ComposeLODControllersSorte
 82118            for (int index = 0; index < lodControllersByDistance.Length; index++)
 119            {
 31120                (IAvatarLODController lodController, float distance) = lodControllersByDistance[index];
 31121                if (distance < 0) //Behind camera
 122                {
 6123                    visibleNames.Remove(lodController.player.id);
 6124                    lodController.SetInvisible();
 6125                    continue;
 126                }
 127
 25128                if (avatarsCount < maxAvatars)
 129                {
 17130                    lodController.SetThrottling((int)gpuSkinningThrottlingCurve.curve.Evaluate(distance));
 17131                    if (distance < simpleAvatarDistance)
 10132                        lodController.SetFullAvatar();
 133                    else
 7134                        lodController.SetSimpleAvatar();
 17135                    avatarsCount++;
 17136                    visibleNames.Add(lodController.player.id);
 17137                    continue;
 138                }
 139
 8140                visibleNames.Remove(lodController.player.id);
 8141                if (impostorCount < maxImpostors)
 142                {
 7143                    lodController.SetImpostor();
 7144                    lodController.UpdateImpostorTint(distance);
 7145                    impostorCount++;
 7146                    continue;
 147                }
 148
 1149                lodController.SetInvisible();
 150            }
 10151        }
 152
 153        private (IAvatarLODController lodController, float distance)[] ComposeLODControllersSortedByDistance(IEnumerable
 154        {
 41155            (IAvatarLODController lodController, float distance)[] lodControllersWithDistance = lodControllers.Select(x 
 40156            Array.Sort(lodControllersWithDistance, (x, y) => x.distance.CompareTo(y.distance));
 10157            return lodControllersWithDistance;
 158        }
 159
 160        /// <summary>
 161        /// Returns -1 if player is not in front of camera or not found
 162        /// </summary>
 163        /// <param name="player"></param>
 164        /// <returns></returns>
 165        private float DistanceToOwnPlayer(Player player, Vector3 ownPlayerPosition)
 166        {
 31167            if (player == null || !IsInFrontOfCamera(player.worldPosition))
 6168                return -1;
 169
 25170            return Vector3.Distance(ownPlayerPosition, player.worldPosition);
 171        }
 172
 58173        private bool IsInFrontOfCamera(Vector3 position) { return Vector3.Dot(cameraForward, (position - cameraPosition)
 174
 175        public void Dispose()
 176        {
 700177            DataStore.i.featureFlags.flags.OnChange -= OnFeatureFlagChanged;
 1470178            foreach (IAvatarLODController lodController in lodControllers.Values)
 179            {
 35180                lodController.Dispose();
 181            }
 182
 700183            otherPlayers.OnAdded -= RegisterAvatar;
 700184            otherPlayers.OnRemoved -= UnregisterAvatar;
 700185        }
 186    }
 187}