< Summary

Class:DCLServices.MapRendererV2.MapLayers.PointsOfInterest.ScenesOfInterestMarkersController
Assembly:MapRendererV2
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLServices/MapRendererV2/MapLayers/PointsOfInterest/ScenesOfInterestMarkersController.cs
Covered lines:20
Uncovered lines:45
Coverable lines:65
Total lines:171
Line coverage:30.7% (20 of 65)
Covered branches:0
Total branches:0
Covered methods:5
Total methods:13
Method coverage:38.4% (5 of 13)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ScenesOfInterestMarkersController(...)0%110100%
Initialize(...)0%3.333066.67%
DisposeImpl()0%2.062075%
OnMapObjectBecameVisible(...)0%2100%
OnMapObjectCulled(...)0%2100%
OnMinimapSceneInfoUpdated(...)0%20.745014.29%
GetParcelsCenter(...)0%20400%
IsEmptyParcel(...)0%2100%
ApplyCameraZoom(...)0%6200%
ResetToBaseScale()0%6200%
Disable(...)0%2.312057.14%
Enable(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLServices/MapRendererV2/MapLayers/PointsOfInterest/ScenesOfInterestMarkersController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCLServices.MapRendererV2.CoordsUtils;
 3using DCLServices.MapRendererV2.Culling;
 4using DCLServices.MapRendererV2.MapCameraController;
 5using MainScripts.DCL.Helpers.Utils;
 6using System;
 7using System.Collections.Generic;
 8using System.Threading;
 9using UnityEngine;
 10
 11namespace DCLServices.MapRendererV2.MapLayers.PointsOfInterest
 12{
 13    internal class ScenesOfInterestMarkersController : MapLayerControllerBase, IMapCullingListener<ISceneOfInterestMarke
 14    {
 15        internal const int PREWARM_PER_FRAME = 20;
 16        private const string EMPTY_PARCEL_NAME = "Empty parcel";
 17
 18        internal delegate ISceneOfInterestMarker SceneOfInterestMarkerBuilder(
 19            IUnityObjectPool<SceneOfInterestMarkerObject> objectsPool,
 20            IMapCullingController cullingController);
 21
 22        private readonly MinimapMetadata minimapMetadata;
 23        private readonly IUnityObjectPool<SceneOfInterestMarkerObject> objectsPool;
 24        private readonly SceneOfInterestMarkerBuilder builder;
 25        private readonly int prewarmCount;
 26
 9627        private readonly Dictionary<MinimapMetadata.MinimapSceneInfo, ISceneOfInterestMarker> markers = new ();
 28
 29        private bool isEnabled;
 30
 031        public IReadOnlyDictionary<MinimapMetadata.MinimapSceneInfo, ISceneOfInterestMarker> Markers => markers;
 32
 33        public ScenesOfInterestMarkersController(MinimapMetadata minimapMetadata,
 34            IUnityObjectPool<SceneOfInterestMarkerObject> objectsPool, SceneOfInterestMarkerBuilder builder,
 35            int prewarmCount, Transform instantiationParent, ICoordsUtils coordsUtils, IMapCullingController cullingCont
 9636            : base(instantiationParent, coordsUtils, cullingController)
 37        {
 9638            this.minimapMetadata = minimapMetadata;
 9639            this.objectsPool = objectsPool;
 9640            this.builder = builder;
 9641            this.prewarmCount = prewarmCount;
 9642        }
 43
 44        public UniTask Initialize(CancellationToken cancellationToken)
 45        {
 46            // non-blocking retrieval of scenes of interest happens independently on the minimap rendering
 19247            foreach (MinimapMetadata.MinimapSceneInfo sceneInfo in minimapMetadata.SceneInfos)
 048                OnMinimapSceneInfoUpdated(sceneInfo);
 49
 9650            minimapMetadata.OnSceneInfoUpdated += OnMinimapSceneInfoUpdated;
 9651            return objectsPool.PrewarmAsync(prewarmCount, PREWARM_PER_FRAME, LinkWithDisposeToken(cancellationToken).Tok
 52        }
 53
 54        protected override void DisposeImpl()
 55        {
 656            objectsPool.Clear();
 57
 1258            foreach (ISceneOfInterestMarker marker in markers.Values)
 059                marker.Dispose();
 60
 661            markers.Clear();
 62
 663            minimapMetadata.OnSceneInfoUpdated -= OnMinimapSceneInfoUpdated;
 664        }
 65
 66        public void OnMapObjectBecameVisible(ISceneOfInterestMarker marker)
 67        {
 068            marker.OnBecameVisible();
 069        }
 70
 71        public void OnMapObjectCulled(ISceneOfInterestMarker marker)
 72        {
 073            marker.OnBecameInvisible();
 074        }
 75
 76        private void OnMinimapSceneInfoUpdated(MinimapMetadata.MinimapSceneInfo sceneInfo)
 77        {
 78            // Markers are not really updated, they can be just reported several times with essentially the same data
 79
 9080            if (!sceneInfo.isPOI)
 9081                return;
 82
 83            // if it was possible to update them then we need to cache by parcel coordinates instead
 84            // and recalculate the parcels centers accordingly
 085            if (markers.ContainsKey(sceneInfo))
 086                return;
 87
 088            if (IsEmptyParcel(sceneInfo))
 089                return;
 90
 091            var marker = builder(objectsPool, mapCullingController);
 92
 093            var centerParcel = GetParcelsCenter(sceneInfo);
 094            var position = coordsUtils.CoordsToPosition(centerParcel, marker);
 95
 096            marker.SetData(sceneInfo.name, position);
 97
 098            markers.Add(sceneInfo, marker);
 99
 0100            if (isEnabled)
 0101                mapCullingController.StartTracking(marker, this);
 0102        }
 103
 104        private static Vector2Int GetParcelsCenter(MinimapMetadata.MinimapSceneInfo sceneInfo)
 105        {
 0106            Vector2 centerTile = Vector2.zero;
 107
 0108            for (var i = 0; i < sceneInfo.parcels.Count; i++)
 109            {
 0110                Vector2Int parcel = sceneInfo.parcels[i];
 0111                centerTile += parcel;
 112            }
 113
 0114            centerTile /= sceneInfo.parcels.Count;
 0115            float distance = float.PositiveInfinity;
 0116            Vector2Int centerParcel = Vector2Int.zero;
 117
 0118            for (var i = 0; i < sceneInfo.parcels.Count; i++)
 119            {
 0120                var parcel = sceneInfo.parcels[i];
 121
 0122                if (Vector2.Distance(centerTile, parcel) < distance)
 123                {
 0124                    distance = Vector2Int.Distance(centerParcel, parcel);
 0125                    centerParcel = parcel;
 126                }
 127            }
 128
 0129            return centerParcel;
 130        }
 131
 132        private static bool IsEmptyParcel(MinimapMetadata.MinimapSceneInfo sceneInfo) =>
 0133            sceneInfo.name is EMPTY_PARCEL_NAME;
 134
 135        public void ApplyCameraZoom(float baseZoom, float zoom)
 136        {
 0137            foreach (ISceneOfInterestMarker marker in markers.Values)
 0138                marker.SetZoom(coordsUtils.ParcelSize, baseZoom, zoom);
 0139        }
 140
 141        public void ResetToBaseScale()
 142        {
 0143            foreach (var marker in markers.Values)
 0144                marker.ResetScale(coordsUtils.ParcelSize);
 0145        }
 146
 147        public UniTask Disable(CancellationToken cancellationToken)
 148        {
 149            // Make markers invisible to release everything to the pool and stop tracking
 176150            foreach (ISceneOfInterestMarker marker in markers.Values)
 151            {
 0152                mapCullingController.StopTracking(marker);
 0153                marker.OnBecameInvisible();
 154            }
 155
 88156            isEnabled = false;
 157
 88158            return UniTask.CompletedTask;
 159        }
 160
 161        public UniTask Enable(CancellationToken cancellationToken)
 162        {
 0163            foreach (ISceneOfInterestMarker marker in markers.Values)
 0164                mapCullingController.StartTracking(marker, this);
 165
 0166            isEnabled = true;
 167
 0168            return UniTask.CompletedTask;
 169        }
 170    }
 171}