| | 1 | | using Cysharp.Threading.Tasks; |
| | 2 | | using DCL; |
| | 3 | | using DCL.Helpers; |
| | 4 | | using DCLServices.MapRendererV2.CommonBehavior; |
| | 5 | | using DCLServices.MapRendererV2.ComponentsFactory; |
| | 6 | | using DCLServices.MapRendererV2.Culling; |
| | 7 | | using DCLServices.MapRendererV2.MapCameraController; |
| | 8 | | using DCLServices.MapRendererV2.MapLayers; |
| | 9 | | using MainScripts.DCL.Helpers.Utils; |
| | 10 | | using System; |
| | 11 | | using System.Collections.Generic; |
| | 12 | | using System.Threading; |
| | 13 | | using UnityEngine; |
| | 14 | | using UnityEngine.Pool; |
| | 15 | |
|
| | 16 | | namespace DCLServices.MapRendererV2 |
| | 17 | | { |
| | 18 | | public partial class MapRenderer : IMapRenderer |
| | 19 | | { |
| | 20 | | private class MapLayerStatus |
| | 21 | | { |
| | 22 | | public readonly IMapLayerController MapLayerController; |
| 792 | 23 | | public readonly List<IMapActivityOwner> ActivityOwners = new (); |
| | 24 | |
|
| | 25 | | public bool? SharedActive; |
| | 26 | | public CancellationTokenSource CTS; |
| | 27 | |
|
| 792 | 28 | | public MapLayerStatus(IMapLayerController mapLayerController) |
| | 29 | | { |
| 792 | 30 | | MapLayerController = mapLayerController; |
| 792 | 31 | | } |
| | 32 | | } |
| | 33 | |
|
| 1 | 34 | | private static readonly MapLayer[] ALL_LAYERS = EnumUtils.Values<MapLayer>(); |
| | 35 | |
|
| | 36 | | private CancellationToken cancellationToken; |
| | 37 | |
|
| | 38 | | private readonly IMapRendererComponentsFactory componentsFactory; |
| | 39 | |
|
| | 40 | | private Dictionary<MapLayer, MapLayerStatus> layers; |
| | 41 | | private List<IZoomScalingLayer> zoomScalingLayers; |
| | 42 | |
|
| | 43 | | private MapRendererConfiguration configurationInstance; |
| | 44 | |
|
| | 45 | | private IObjectPool<IMapCameraControllerInternal> mapCameraPool; |
| | 46 | |
|
| 185 | 47 | | internal IMapCullingController cullingController { get; private set; } |
| | 48 | |
|
| 97 | 49 | | public MapRenderer(IMapRendererComponentsFactory componentsFactory) |
| | 50 | | { |
| 97 | 51 | | this.componentsFactory = componentsFactory; |
| 97 | 52 | | } |
| | 53 | |
|
| 97 | 54 | | public void Initialize() { } |
| | 55 | |
|
| | 56 | | public async UniTask InitializeAsync(CancellationToken cancellationToken) |
| | 57 | | { |
| 97 | 58 | | this.cancellationToken = cancellationToken; |
| 97 | 59 | | layers = new Dictionary<MapLayer, MapLayerStatus>(); |
| 97 | 60 | | zoomScalingLayers = new List<IZoomScalingLayer>(); |
| | 61 | |
|
| | 62 | | try |
| | 63 | | { |
| 291 | 64 | | MapRendererComponents components = await componentsFactory.Create(cancellationToken); |
| 88 | 65 | | cullingController = components.CullingController; |
| 88 | 66 | | mapCameraPool = components.MapCameraControllers; |
| 88 | 67 | | configurationInstance = components.ConfigurationInstance; |
| | 68 | |
|
| 1056 | 69 | | foreach (IZoomScalingLayer zoomScalingLayer in components.ZoomScalingLayers) |
| 440 | 70 | | zoomScalingLayers.Add(zoomScalingLayer); |
| | 71 | |
|
| 1760 | 72 | | foreach (KeyValuePair<MapLayer, IMapLayerController> pair in components.Layers) |
| | 73 | | { |
| 792 | 74 | | pair.Value.Disable(cancellationToken); |
| 792 | 75 | | layers[pair.Key] = new MapLayerStatus(pair.Value); |
| | 76 | | } |
| | 77 | |
|
| 88 | 78 | | if (DataStore.i.featureFlags.flags.Get().IsInitialized) |
| 0 | 79 | | OnFeatureFlagsChanged(null, null); |
| | 80 | | else |
| 88 | 81 | | DataStore.i.featureFlags.flags.OnChange += OnFeatureFlagsChanged; |
| 88 | 82 | | } |
| 9 | 83 | | catch |
| | 84 | | (OperationCanceledException) |
| | 85 | | { |
| | 86 | | // just ignore |
| 9 | 87 | | } |
| 0 | 88 | | catch (Exception e) { Debug.LogException(e); } |
| 97 | 89 | | } |
| | 90 | |
|
| | 91 | | private void OnFeatureFlagsChanged(FeatureFlag _, FeatureFlag __) |
| | 92 | | { |
| 250 | 93 | | bool satelliteEnabled = DataStore.i.featureFlags.flags.Get().IsFeatureEnabled("navmap-satellite-view"); // f |
| 250 | 94 | | layers[MapLayer.SatelliteAtlas].SharedActive = satelliteEnabled; |
| 250 | 95 | | layers[MapLayer.ParcelsAtlas].SharedActive = !satelliteEnabled; |
| 250 | 96 | | } |
| | 97 | |
|
| | 98 | | public IMapCameraController RentCamera(in MapCameraInput cameraInput) |
| | 99 | | { |
| | 100 | | const int MIN_ZOOM = 5; |
| | 101 | | const int MAX_ZOOM = 300; |
| | 102 | |
|
| | 103 | | // Clamp texture to the maximum size allowed, preserving aspect ratio |
| 0 | 104 | | Vector2Int zoomValues = cameraInput.ZoomValues; |
| 0 | 105 | | zoomValues.x = Mathf.Max(zoomValues.x, MIN_ZOOM); |
| 0 | 106 | | zoomValues.y = Mathf.Min(zoomValues.y, MAX_ZOOM); |
| | 107 | |
|
| 0 | 108 | | EnableLayers(cameraInput.ActivityOwner, cameraInput.EnabledLayers); |
| 0 | 109 | | IMapCameraControllerInternal mapCameraController = mapCameraPool.Get(); |
| 0 | 110 | | mapCameraController.Initialize(cameraInput.TextureResolution, zoomValues, cameraInput.EnabledLayers); |
| 0 | 111 | | mapCameraController.OnReleasing += ReleaseCamera; |
| | 112 | |
|
| 0 | 113 | | if (DataStore.i.featureFlags.flags.Get().IsFeatureEnabled("map_focus_home_or_user")) |
| 0 | 114 | | mapCameraController.ZoomChanged += OnCameraZoomChanged; |
| | 115 | |
|
| 0 | 116 | | mapCameraController.SetPositionAndZoom(cameraInput.Position, cameraInput.Zoom); |
| | 117 | |
|
| 0 | 118 | | return mapCameraController; |
| | 119 | | } |
| | 120 | |
|
| | 121 | | private void ReleaseCamera(IMapActivityOwner owner, IMapCameraControllerInternal mapCameraController) |
| | 122 | | { |
| 0 | 123 | | mapCameraController.OnReleasing -= ReleaseCamera; |
| | 124 | |
|
| 0 | 125 | | if (DataStore.i.featureFlags.flags.Get().IsFeatureEnabled("map_focus_home_or_user")) |
| | 126 | | { |
| 0 | 127 | | mapCameraController.ZoomChanged -= OnCameraZoomChanged; |
| | 128 | |
|
| 0 | 129 | | foreach (IZoomScalingLayer layer in zoomScalingLayers) |
| 0 | 130 | | layer.ResetToBaseScale(); |
| | 131 | | } |
| | 132 | |
|
| 0 | 133 | | DisableLayers(owner, mapCameraController.EnabledLayers); |
| 0 | 134 | | mapCameraPool.Release(mapCameraController); |
| 0 | 135 | | } |
| | 136 | |
|
| | 137 | | private void OnCameraZoomChanged(float baseZoom, float newZoom) |
| | 138 | | { |
| 0 | 139 | | foreach (IZoomScalingLayer layer in zoomScalingLayers) |
| 0 | 140 | | layer.ApplyCameraZoom(baseZoom, newZoom); |
| 0 | 141 | | } |
| | 142 | |
|
| | 143 | | public void SetSharedLayer(MapLayer mask, bool active) |
| | 144 | | { |
| 0 | 145 | | foreach (MapLayer mapLayer in ALL_LAYERS) |
| | 146 | | { |
| 0 | 147 | | if (!EnumUtils.HasFlag(mask, mapLayer) || !layers.TryGetValue(mapLayer, out MapLayerStatus mapLayerStatu |
| | 148 | | continue; |
| | 149 | |
|
| 0 | 150 | | mapLayerStatus.SharedActive = active; |
| | 151 | |
|
| | 152 | | // Cancel activation/deactivation flow |
| 0 | 153 | | ResetCancellationSource(mapLayerStatus); |
| | 154 | |
|
| 0 | 155 | | if (active) |
| 0 | 156 | | mapLayerStatus.MapLayerController.Enable(mapLayerStatus.CTS.Token).SuppressCancellationThrow().Forge |
| | 157 | | else |
| 0 | 158 | | mapLayerStatus.MapLayerController.Disable(mapLayerStatus.CTS.Token).SuppressCancellationThrow().Forg |
| | 159 | | } |
| 0 | 160 | | } |
| | 161 | |
|
| | 162 | | private void EnableLayers(IMapActivityOwner owner, MapLayer mask) |
| | 163 | | { |
| 0 | 164 | | foreach (MapLayer mapLayer in ALL_LAYERS) |
| | 165 | | { |
| 0 | 166 | | if (!EnumUtils.HasFlag(mask, mapLayer) || !layers.TryGetValue(mapLayer, out MapLayerStatus mapLayerStatu |
| | 167 | |
|
| 0 | 168 | | if (owner.LayersParameters.TryGetValue(mapLayer, out IMapLayerParameter parameter)) |
| 0 | 169 | | mapLayerStatus.MapLayerController.SetParameter(parameter); |
| | 170 | |
|
| 0 | 171 | | if (mapLayerStatus.ActivityOwners.Count == 0 && mapLayerStatus.SharedActive != false) |
| | 172 | | { |
| | 173 | | // Cancel deactivation flow |
| 0 | 174 | | ResetCancellationSource(mapLayerStatus); |
| 0 | 175 | | mapLayerStatus.MapLayerController.Enable(mapLayerStatus.CTS.Token).SuppressCancellationThrow().Forge |
| | 176 | | } |
| | 177 | |
|
| 0 | 178 | | mapLayerStatus.ActivityOwners.Add(owner); |
| | 179 | | } |
| 0 | 180 | | } |
| | 181 | |
|
| | 182 | | private void DisableLayers(IMapActivityOwner owner, MapLayer mask) |
| | 183 | | { |
| 0 | 184 | | foreach (MapLayer mapLayer in ALL_LAYERS) |
| | 185 | | { |
| 0 | 186 | | if (!EnumUtils.HasFlag(mask, mapLayer) || !layers.TryGetValue(mapLayer, out MapLayerStatus mapLayerStatu |
| | 187 | |
|
| 0 | 188 | | if (mapLayerStatus.ActivityOwners.Contains(owner)) |
| 0 | 189 | | mapLayerStatus.ActivityOwners.Remove(owner); |
| | 190 | |
|
| 0 | 191 | | if (mapLayerStatus.ActivityOwners.Count == 0) |
| | 192 | | { |
| | 193 | | // Cancel activation flow |
| 0 | 194 | | ResetCancellationSource(mapLayerStatus); |
| 0 | 195 | | mapLayerStatus.MapLayerController.Disable(mapLayerStatus.CTS.Token).SuppressCancellationThrow().Forg |
| | 196 | | } |
| | 197 | | else |
| | 198 | | { |
| 0 | 199 | | var currentOwner = mapLayerStatus.ActivityOwners[^1]; |
| 0 | 200 | | IReadOnlyDictionary<MapLayer, IMapLayerParameter> parametersByLayer = currentOwner.LayersParameters; |
| | 201 | |
|
| 0 | 202 | | if (parametersByLayer.ContainsKey(mapLayer)) |
| 0 | 203 | | mapLayerStatus.MapLayerController.SetParameter(parametersByLayer[mapLayer]); |
| | 204 | | } |
| | 205 | | } |
| 0 | 206 | | } |
| | 207 | |
|
| | 208 | | private void ResetCancellationSource(MapLayerStatus mapLayerStatus) |
| | 209 | | { |
| 0 | 210 | | if (mapLayerStatus.CTS != null) |
| | 211 | | { |
| 0 | 212 | | mapLayerStatus.CTS.Cancel(); |
| 0 | 213 | | mapLayerStatus.CTS.Dispose(); |
| | 214 | | } |
| | 215 | |
|
| 0 | 216 | | mapLayerStatus.CTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); |
| 0 | 217 | | } |
| | 218 | |
|
| | 219 | | public void Dispose() |
| | 220 | | { |
| 302 | 221 | | foreach (MapLayerStatus status in layers.Values) |
| | 222 | | { |
| 54 | 223 | | if (status.CTS != null) |
| | 224 | | { |
| 0 | 225 | | status.CTS.Cancel(); |
| 0 | 226 | | status.CTS.Dispose(); |
| 0 | 227 | | status.CTS = null; |
| | 228 | | } |
| | 229 | |
|
| 54 | 230 | | status.MapLayerController.Dispose(); |
| | 231 | | } |
| | 232 | |
|
| 97 | 233 | | cullingController?.Dispose(); |
| | 234 | |
|
| 97 | 235 | | if (configurationInstance) |
| 6 | 236 | | Utils.SafeDestroy(configurationInstance.gameObject); |
| 97 | 237 | | } |
| | 238 | | } |
| | 239 | | } |