< 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:78
Uncovered lines:1
Coverable lines:79
Total lines:180
Line coverage:98.7% (78 of 79)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarsLODController()0%110100%
Initialize()0%4.474069.23%
RegisterAvatar(...)0%220100%
CreateLodController(...)0%110100%
UnregisterAvatar(...)0%220100%
Update()0%110100%
UpdateAllLODs(...)0%880100%
IsInInvisibleDistance(...)0%220100%
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 DCL.CameraTool;
 4using UnityEngine;
 5
 6namespace DCL
 7{
 8    public class AvatarsLODController : IAvatarsLODController
 9    {
 10        internal const float RENDERED_DOT_PRODUCT_ANGLE = 0.25f;
 11        internal const float AVATARS_INVISIBILITY_DISTANCE = 1.75f;
 12        private const float MIN_DISTANCE_BETWEEN_NAMES_PIXELS = 70f;
 13
 254514        private BaseDictionary<string, Player> otherPlayers => DataStore.i.player.otherPlayers;
 2645615        private BaseVariable<float> simpleAvatarDistance => DataStore.i.avatarsLOD.simpleAvatarDistance;
 016        private BaseVariable<float> LODDistance => DataStore.i.avatarsLOD.LODDistance;
 2645517        private BaseVariable<int> maxAvatars => DataStore.i.avatarsLOD.maxAvatars;
 2645518        private BaseVariable<int> maxImpostors => DataStore.i.avatarsLOD.maxImpostors;
 19        private Vector3 cameraPosition;
 20        private Vector3 cameraForward;
 21        private GPUSkinningThrottlingCurveSO gpuSkinningThrottlingCurve;
 50922        private SimpleOverlappingTracker overlappingTracker = new SimpleOverlappingTracker(MIN_DISTANCE_BETWEEN_NAMES_PI
 23
 50924        internal readonly Dictionary<string, IAvatarLODController> lodControllers = new Dictionary<string, IAvatarLODCon
 25        private UnityEngine.Camera mainCamera;
 26
 50927        private readonly List<(IAvatarLODController lodController, float distance)> lodControllersWithDistance = new ();
 28
 50929        public AvatarsLODController()
 30        {
 50931            gpuSkinningThrottlingCurve = Resources.Load<GPUSkinningThrottlingCurveSO>("GPUSkinningThrottlingCurve");
 50932        }
 33
 34        public void Initialize()
 35        {
 50936            Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 37
 101838            foreach (IAvatarLODController lodController in lodControllers.Values) { lodController.Dispose(); }
 39
 50940            lodControllers.Clear();
 41
 101842            foreach (var keyValuePair in otherPlayers.Get()) { RegisterAvatar(keyValuePair.Key, keyValuePair.Value); }
 43
 50944            otherPlayers.OnAdded += RegisterAvatar;
 50945            otherPlayers.OnRemoved += UnregisterAvatar;
 50946        }
 47
 48        public void RegisterAvatar(string id, Player player)
 49        {
 2550            if (lodControllers.ContainsKey(id))
 151                return;
 52
 2453            lodControllers.Add(id, CreateLodController(player));
 2454        }
 55
 56        protected internal virtual IAvatarLODController CreateLodController(Player player) =>
 2057            new AvatarLODController(player);
 58
 59        public void UnregisterAvatar(string id, Player player)
 60        {
 861            if (!lodControllers.ContainsKey(id))
 162                return;
 63
 764            lodControllers[id].Dispose();
 765            lodControllers.Remove(id);
 766        }
 67
 68        public void Update()
 69        {
 2645570            cameraPosition = CommonScriptableObjects.cameraPosition.Get();
 2645571            cameraForward = CommonScriptableObjects.cameraForward.Get();
 72
 2645573            UpdateAllLODs(maxAvatars.Get(), maxImpostors.Get());
 2645574        }
 75
 76        internal void UpdateAllLODs(int maxAvatars = DataStore_AvatarsLOD.DEFAULT_MAX_AVATAR, int maxImpostors = DataSto
 77        {
 2645678            if (mainCamera == null)
 1187279                mainCamera = UnityEngine.Camera.main;
 80
 2645681            var avatarsCount = 0; //Full Avatar + Simple Avatar
 2645682            var impostorCount = 0; //Impostor
 83
 2645684            float simpleAvatarDistance = this.simpleAvatarDistance.Get();
 2645685            Vector3 ownPlayerPosition = CommonScriptableObjects.playerUnityPosition.Get();
 86
 2645687            overlappingTracker.Reset();
 88
 2655689            foreach (var controllerDistancePair in
 2645690                     ComposeLODControllersSortedByDistance(lodControllers.Values, ownPlayerPosition))
 91            {
 5092                (IAvatarLODController lodController, float distance) = controllerDistancePair;
 93
 5094                if (IsInInvisibleDistance(distance))
 95                {
 496                    lodController.SetNameVisible(false);
 497                    lodController.SetInvisible();
 498                    continue;
 99                }
 100
 46101                if (avatarsCount < maxAvatars)
 102                {
 39103                    lodController.SetAnimationThrottling((int)gpuSkinningThrottlingCurve.curve.Evaluate(distance));
 104
 39105                    if (distance < simpleAvatarDistance)
 35106                        lodController.SetLOD0();
 107                    else
 4108                        lodController.SetLOD1();
 109
 39110                    avatarsCount++;
 111
 39112                    lodController.SetNameVisible(mainCamera == null || overlappingTracker.RegisterPosition(lodController
 113
 39114                    continue;
 115                }
 116
 7117                lodController.SetNameVisible(false);
 118
 7119                if (impostorCount < maxImpostors)
 120                {
 6121                    lodController.SetLOD2();
 6122                    lodController.UpdateImpostorTint(distance);
 6123                    impostorCount++;
 6124                    continue;
 125                }
 126
 1127                lodController.SetInvisible();
 128            }
 26456129        }
 130
 131        private bool IsInInvisibleDistance(float distance)
 132        {
 50133            bool firstPersonCamera = CommonScriptableObjects.cameraMode.Get() == CameraMode.ModeId.FirstPerson;
 134
 50135            return firstPersonCamera ? distance < AVATARS_INVISIBILITY_DISTANCE : distance < 0f; // < 0 is behind camera
 136        }
 137
 138        private List<(IAvatarLODController lodController, float distance)> ComposeLODControllersSortedByDistance(Diction
 139        {
 26456140            lodControllersWithDistance.Clear();
 141
 53012142            foreach (IAvatarLODController x in lodControllers)
 50143                lodControllersWithDistance.Add((x, DistanceToOwnPlayer(x.player, ownPlayerPosition)));
 144
 26456145            lodControllersWithDistance.Sort(CompareByDistance());
 146
 26456147            return lodControllersWithDistance;
 148
 149            Comparison<(IAvatarLODController lodController, float distance)> CompareByDistance() =>
 26495150                (x, y) => x.distance.CompareTo(y.distance);
 151        }
 152
 153        /// <summary>
 154        /// Returns -1 if player is not in front of camera or not found
 155        /// </summary>
 156        /// <param name="player"></param>
 157        /// <returns></returns>
 158        private float DistanceToOwnPlayer(Player player, Vector3 ownPlayerPosition)
 159        {
 50160            if (player == null || !IsInFrontOfCamera(player.worldPosition))
 3161                return -1;
 162
 47163            return Vector3.Distance(ownPlayerPosition, player.worldPosition);
 164        }
 165
 166        private bool IsInFrontOfCamera(Vector3 position)
 167        {
 50168            return Vector3.Dot(cameraForward, (position - cameraPosition).normalized) >= RENDERED_DOT_PRODUCT_ANGLE;
 169        }
 170
 171        public void Dispose()
 172        {
 1102173            foreach (IAvatarLODController lodController in lodControllers.Values) { lodController.Dispose(); }
 174
 509175            otherPlayers.OnAdded -= RegisterAvatar;
 509176            otherPlayers.OnRemoved -= UnregisterAvatar;
 509177            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 509178        }
 179    }
 180}