< 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:87
Uncovered lines:8
Coverable lines:95
Total lines:191
Line coverage:91.5% (87 of 95)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarsLODController()0%110100%
OnKernelConfigChanged(...)0%220100%
Initialize(...)0%5.065086.67%
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 float RENDERED_DOT_PRODUCT_ANGLE = 0.25f;
 12
 013        private BaseDictionary<string, Player> otherPlayers => DataStore.i.player.otherPlayers;
 014        private BaseVariable<float> simpleAvatarDistance => DataStore.i.avatarsLOD.simpleAvatarDistance;
 015        private BaseVariable<float> LODDistance => DataStore.i.avatarsLOD.LODDistance;
 016        private BaseVariable<int> maxAvatars => DataStore.i.avatarsLOD.maxAvatars;
 017        private BaseVariable<int> maxImpostors => DataStore.i.avatarsLOD.maxImpostors;
 018        private BaseHashSet<string> visibleNames => DataStore.i.avatarsLOD.visibleNames;
 19        private Vector3 cameraPosition;
 20        private Vector3 cameraForward;
 21        private GPUSkinningThrottlingCurveSO gpuSkinningThrottlingCurve;
 22
 68523        internal readonly Dictionary<string, IAvatarLODController> lodControllers = new Dictionary<string, IAvatarLODCon
 24        internal bool enabled;
 25
 68526        public AvatarsLODController()
 27        {
 68528            gpuSkinningThrottlingCurve = Resources.Load<GPUSkinningThrottlingCurveSO>("GPUSkinningThrottlingCurve");
 68529            KernelConfig.i.EnsureConfigInitialized()
 30                        .Then(config =>
 31                        {
 68532                            KernelConfig.i.OnChange += OnKernelConfigChanged;
 68533                            OnKernelConfigChanged(config, null);
 68534                        });
 68535        }
 36
 37        private void OnKernelConfigChanged(KernelConfigModel current, KernelConfigModel previous)
 38        {
 265039            if (enabled == current.features.enableAvatarLODs)
 263440                return;
 1641            Initialize(current);
 1642        }
 43
 44        internal void Initialize(KernelConfigModel config)
 45        {
 2046            enabled = config.features.enableAvatarLODs;
 2047            if (!enabled)
 1648                return;
 49
 850            foreach (IAvatarLODController lodController in lodControllers.Values)
 51            {
 052                lodController.Dispose();
 53            }
 454            lodControllers.Clear();
 55
 1256            foreach (var keyValuePair in otherPlayers.Get())
 57            {
 258                RegisterAvatar(keyValuePair.Key, keyValuePair.Value);
 59            }
 460            otherPlayers.OnAdded += RegisterAvatar;
 461            otherPlayers.OnRemoved += UnregisterAvatar;
 462        }
 63
 64        public void RegisterAvatar(string id, Player player)
 65        {
 566            if (!enabled || lodControllers.ContainsKey(id))
 167                return;
 68
 469            lodControllers.Add(id, CreateLodController(player));
 470        }
 71
 072        protected internal virtual IAvatarLODController CreateLodController(Player player) => new AvatarLODController(pl
 73
 74        public void UnregisterAvatar(string id, Player player)
 75        {
 376            if (!lodControllers.ContainsKey(id))
 177                return;
 78
 279            lodControllers[id].Dispose();
 280            lodControllers.Remove(id);
 281        }
 82
 83        public void Update()
 84        {
 1699385            if (!enabled)
 1698586                return;
 87
 888            cameraPosition = CommonScriptableObjects.cameraPosition.Get();
 889            cameraForward = CommonScriptableObjects.cameraForward.Get();
 90
 891            UpdateAllLODs(maxAvatars.Get(), maxImpostors.Get());
 892            UpdateLODsBillboard();
 893        }
 94
 95        internal void UpdateLODsBillboard()
 96        {
 7097            foreach (var kvp in lodControllers)
 98            {
 2799                Player player = kvp.Value.player;
 100
 27101                if (!IsInFrontOfCamera(player.worldPosition))
 102                    continue;
 103
 25104                Vector3 previousForward = player.forwardDirection;
 25105                Vector3 lookAtDir = (cameraPosition - player.worldPosition).normalized;
 106
 25107                lookAtDir.y = previousForward.y;
 25108                player.renderer.SetImpostorForward(lookAtDir);
 109            }
 8110        }
 111
 112        internal void UpdateAllLODs(int maxAvatars = DataStore.DataStore_AvatarsLOD.DEFAULT_MAX_AVATAR, int maxImpostors
 113        {
 10114            int avatarsCount = 0; //Full Avatar + Simple Avatar
 10115            int impostorCount = 0; //Impostor
 116
 10117            float lodDistance = LODDistance.Get();
 10118            float simpleAvatarDistance = this.simpleAvatarDistance.Get();
 10119            Vector3 ownPlayerPosition = CommonScriptableObjects.playerUnityPosition.Get();
 120
 10121            (IAvatarLODController lodController, float distance)[] lodControllersByDistance = ComposeLODControllersSorte
 82122            for (int index = 0; index < lodControllersByDistance.Length; index++)
 123            {
 31124                (IAvatarLODController lodController, float distance) = lodControllersByDistance[index];
 31125                if (distance < 0) //Behind camera
 126                {
 6127                    visibleNames.Remove(lodController.player.id);
 6128                    lodController.SetInvisible();
 6129                    continue;
 130                }
 131
 25132                if (avatarsCount < maxAvatars)
 133                {
 17134                    lodController.SetThrottling((int)gpuSkinningThrottlingCurve.curve.Evaluate(distance));
 17135                    if (distance < simpleAvatarDistance)
 10136                        lodController.SetFullAvatar();
 137                    else
 7138                        lodController.SetSimpleAvatar();
 17139                    avatarsCount++;
 17140                    visibleNames.Add(lodController.player.id);
 17141                    continue;
 142                }
 143
 8144                visibleNames.Remove(lodController.player.id);
 8145                if (impostorCount < maxImpostors)
 146                {
 7147                    lodController.SetImpostor();
 7148                    lodController.UpdateImpostorTint(distance);
 7149                    impostorCount++;
 7150                    continue;
 151                }
 152
 1153                lodController.SetInvisible();
 154            }
 10155        }
 156
 157        private (IAvatarLODController lodController, float distance)[] ComposeLODControllersSortedByDistance(IEnumerable
 158        {
 41159            (IAvatarLODController lodController, float distance)[] lodControllersWithDistance = lodControllers.Select(x 
 40160            Array.Sort(lodControllersWithDistance, (x, y) => x.distance.CompareTo(y.distance));
 10161            return lodControllersWithDistance;
 162        }
 163
 164        /// <summary>
 165        /// Returns -1 if player is not in front of camera or not found
 166        /// </summary>
 167        /// <param name="player"></param>
 168        /// <returns></returns>
 169        private float DistanceToOwnPlayer(Player player, Vector3 ownPlayerPosition)
 170        {
 31171            if (player == null || !IsInFrontOfCamera(player.worldPosition))
 6172                return -1;
 173
 25174            return Vector3.Distance(ownPlayerPosition, player.worldPosition);
 175        }
 176
 58177        private bool IsInFrontOfCamera(Vector3 position) { return Vector3.Dot(cameraForward, (position - cameraPosition)
 178
 179        public void Dispose()
 180        {
 705181            KernelConfig.i.OnChange -= OnKernelConfigChanged;
 1480182            foreach (IAvatarLODController lodController in lodControllers.Values)
 183            {
 35184                lodController.Dispose();
 185            }
 186
 705187            otherPlayers.OnAdded -= RegisterAvatar;
 705188            otherPlayers.OnRemoved -= UnregisterAvatar;
 705189        }
 190    }
 191}