You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							517 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
	
	
							517 lines
						
					
					
						
							14 KiB
						
					
					
				| using System.Collections.Generic;
 | |
| using UnityEngine;
 | |
| using Mapbox.Unity.MeshGeneration.Enums;
 | |
| using Mapbox.Unity.MeshGeneration.Data;
 | |
| using Mapbox.Unity.MeshGeneration.Interfaces;
 | |
| using Mapbox.Map;
 | |
| using Mapbox.Unity.Map;
 | |
| using System;
 | |
| 
 | |
| namespace Mapbox.Unity.MeshGeneration.Factories
 | |
| {
 | |
| 	/// <summary>
 | |
| 	///	Vector Tile Factory
 | |
| 	/// Vector data is much more detailed compared to terrain and image data so we have a different structure to process
 | |
| 	/// vector data(compared to other factories). First of all, how does the vector data itself structured? Vector tile
 | |
| 	/// data contains 'vector layers' as immediate children.And then each of these vector layers contains a number of
 | |
| 	/// 'features' inside.I.e.vector data for a tile has 'building', 'road', 'landuse' etc layers. Then building layer
 | |
| 	/// has a number of polygon features, road layer has line features etc.
 | |
| 	/// Similar to this, vector tile factory contains bunch of 'layer visualizers' and each one of them corresponds to
 | |
| 	/// one (or more) vector layers in data.So when data is received, factory goes through all layers inside and passes
 | |
| 	/// them to designated layer visualizers.We're using layer name as key here, to find the designated layer visualizer,
 | |
| 	/// like 'building', 'road'. (vector tile factory visual would help here). If it can't find a layer visualizer for
 | |
| 	/// that layer, it'll be skipped and not processed at all.If all you need is 1-2 layers, it's indeed a big waste to
 | |
| 	/// pull whole vector data and you can use 'Style Optimized Vector Tile Factory' to pull only the layer you want to use.
 | |
| 	/// </summary>
 | |
| 	//[CreateAssetMenu(menuName = "Mapbox/Factories/Vector Tile Factory")]
 | |
| 	public class VectorTileFactory : AbstractTileFactory
 | |
| 	{
 | |
| 		#region Private/Protected Fields
 | |
| 		private Dictionary<string, List<LayerVisualizerBase>> _layerBuilder;
 | |
| 		private VectorLayerProperties _properties;
 | |
| 		private Dictionary<UnityTile, HashSet<LayerVisualizerBase>> _layerProgress;
 | |
| 		protected VectorDataFetcher DataFetcher;
 | |
| 		#endregion
 | |
| 
 | |
| 		#region Properties
 | |
| 		public string TilesetId
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return _properties.sourceOptions.Id;
 | |
| 			}
 | |
| 
 | |
| 			set
 | |
| 			{
 | |
| 				_properties.sourceOptions.Id = value;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public VectorLayerProperties Properties
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return _properties;
 | |
| 			}
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 		#region Public Methods
 | |
| 		public void RedrawSubLayer(UnityTile tile, LayerVisualizerBase visualizer)
 | |
| 		{
 | |
| 			CreateFeatureWithBuilder(tile, visualizer.SubLayerProperties.coreOptions.layerName, visualizer);
 | |
| 		}
 | |
| 
 | |
| 		public void UnregisterLayer(UnityTile tile, LayerVisualizerBase visualizer)
 | |
| 		{
 | |
| 			if (_layerProgress.ContainsKey(tile))
 | |
| 			{
 | |
| 				_layerProgress.Remove(tile);
 | |
| 			}
 | |
| 			if (_tilesWaitingProcessing.Contains(tile))
 | |
| 			{
 | |
| 				_tilesWaitingProcessing.Remove(tile);
 | |
| 			}
 | |
| 
 | |
| 			if (visualizer != null)
 | |
| 			{
 | |
| 				visualizer.UnregisterTile(tile);
 | |
| 			}
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 		#region Public Layer Operation Api Methods for
 | |
| 		public virtual LayerVisualizerBase AddVectorLayerVisualizer(VectorSubLayerProperties subLayer)
 | |
| 		{
 | |
| 			//if its of type prefabitemoptions then separate the visualizer type
 | |
| 			LayerVisualizerBase visualizer = CreateInstance<VectorLayerVisualizer>();
 | |
| 
 | |
| 			//TODO : FIX THIS !!
 | |
| 			visualizer.LayerVisualizerHasChanged += UpdateTileFactory;
 | |
| 
 | |
| 			// Set honorBuildingSettings - need to set here in addition to the UI.
 | |
| 			// Not setting it here can lead to wrong filtering.
 | |
| 
 | |
| 			bool isPrimitiveTypeValidForBuidingIds = (subLayer.coreOptions.geometryType == VectorPrimitiveType.Polygon) || (subLayer.coreOptions.geometryType == VectorPrimitiveType.Custom);
 | |
| 			bool isSourceValidForBuildingIds = _properties.sourceType != VectorSourceType.MapboxStreets;
 | |
| 
 | |
| 			subLayer.honorBuildingIdSetting = isPrimitiveTypeValidForBuidingIds && isSourceValidForBuildingIds;
 | |
| 			// Setup visualizer.
 | |
| 			((VectorLayerVisualizer)visualizer).SetProperties(subLayer);
 | |
| 
 | |
| 			visualizer.Initialize();
 | |
| 			if (visualizer == null)
 | |
| 			{
 | |
| 				return visualizer;
 | |
| 			}
 | |
| 
 | |
| 			if (_layerBuilder.ContainsKey(visualizer.Key))
 | |
| 			{
 | |
| 				_layerBuilder[visualizer.Key].Add(visualizer);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				_layerBuilder.Add(visualizer.Key, new List<LayerVisualizerBase> { visualizer });
 | |
| 			}
 | |
| 			return visualizer;
 | |
| 		}
 | |
| 
 | |
| 		public virtual LayerVisualizerBase AddPOIVectorLayerVisualizer(PrefabItemOptions poiSubLayer)
 | |
| 		{
 | |
| 			LayerVisualizerBase visualizer = CreateInstance<LocationPrefabsLayerVisualizer>();
 | |
| 			poiSubLayer.performanceOptions = _properties.performanceOptions;
 | |
| 			((LocationPrefabsLayerVisualizer)visualizer).SetProperties((PrefabItemOptions)poiSubLayer);
 | |
| 
 | |
| 			visualizer.LayerVisualizerHasChanged += UpdateTileFactory;
 | |
| 
 | |
| 			visualizer.Initialize();
 | |
| 			if (visualizer == null)
 | |
| 			{
 | |
| 				return null;
 | |
| 			}
 | |
| 
 | |
| 			if (_layerBuilder.ContainsKey(visualizer.Key))
 | |
| 			{
 | |
| 				_layerBuilder[visualizer.Key].Add(visualizer);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				_layerBuilder.Add(visualizer.Key, new List<LayerVisualizerBase>() { visualizer });
 | |
| 			}
 | |
| 
 | |
| 			return visualizer;
 | |
| 		}
 | |
| 
 | |
| 		public virtual LayerVisualizerBase FindVectorLayerVisualizer(VectorSubLayerProperties subLayer)
 | |
| 		{
 | |
| 			if (_layerBuilder.ContainsKey(subLayer.Key))
 | |
| 			{
 | |
| 				var visualizer = _layerBuilder[subLayer.Key].Find((obj) => obj.SubLayerProperties == subLayer);
 | |
| 				return visualizer;
 | |
| 			}
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		public virtual void RemoveVectorLayerVisualizer(LayerVisualizerBase subLayer)
 | |
| 		{
 | |
| 			subLayer.Clear();
 | |
| 			if (_layerBuilder.ContainsKey(subLayer.Key))
 | |
| 			{
 | |
| 				if (Properties.vectorSubLayers.Contains(subLayer.SubLayerProperties))
 | |
| 				{
 | |
| 					Properties.vectorSubLayers.Remove(subLayer.SubLayerProperties);
 | |
| 				}
 | |
| 				else if (subLayer.SubLayerProperties is PrefabItemOptions && Properties.locationPrefabList.Contains(subLayer.SubLayerProperties as PrefabItemOptions))
 | |
| 				{
 | |
| 					Properties.locationPrefabList.Remove(subLayer.SubLayerProperties as PrefabItemOptions);
 | |
| 				}
 | |
| 				subLayer.LayerVisualizerHasChanged -= UpdateTileFactory;
 | |
| 				subLayer.UnbindSubLayerEvents();
 | |
| 				_layerBuilder[subLayer.Key].Remove(subLayer);
 | |
| 			}
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 		#region AbstractFactoryOverrides
 | |
| 		/// <summary>
 | |
| 		/// Set up sublayers using VectorLayerVisualizers.
 | |
| 		/// </summary>
 | |
| 		protected override void OnInitialized()
 | |
| 		{
 | |
| 			_layerProgress = new Dictionary<UnityTile, HashSet<LayerVisualizerBase>>();
 | |
| 			_layerBuilder = new Dictionary<string, List<LayerVisualizerBase>>();
 | |
| 
 | |
| 			DataFetcher = ScriptableObject.CreateInstance<VectorDataFetcher>();
 | |
| 			DataFetcher.DataRecieved += OnVectorDataRecieved;
 | |
| 			DataFetcher.FetchingError += OnDataError;
 | |
| 
 | |
| 			CreatePOILayerVisualizers();
 | |
| 
 | |
| 			CreateLayerVisualizers();
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnRegistered(UnityTile tile)
 | |
| 		{
 | |
| 			if (string.IsNullOrEmpty(TilesetId) || _properties.sourceOptions.isActive == false || (_properties.vectorSubLayers.Count + _properties.locationPrefabList.Count) == 0)
 | |
| 			{
 | |
| 				tile.VectorDataState = TilePropertyState.None;
 | |
| 				return;
 | |
| 			}
 | |
| 			tile.VectorDataState = TilePropertyState.Loading;
 | |
| 			_tilesWaitingResponse.Add(tile);
 | |
| 			VectorDataFetcherParameters parameters = new VectorDataFetcherParameters()
 | |
| 			{
 | |
| 				canonicalTileId = tile.CanonicalTileId,
 | |
| 				tilesetId = TilesetId,
 | |
| 				tile = tile,
 | |
| 				useOptimizedStyle = _properties.useOptimizedStyle,
 | |
| 				style = _properties.optimizedStyle
 | |
| 			};
 | |
| 			DataFetcher.FetchData(parameters);
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnUnregistered(UnityTile tile)
 | |
| 		{
 | |
| 			if (_layerProgress != null && _layerProgress.ContainsKey(tile))
 | |
| 			{
 | |
| 				_layerProgress.Remove(tile);
 | |
| 			}
 | |
| 			if (_tilesWaitingResponse != null && _tilesWaitingProcessing.Contains(tile))
 | |
| 			{
 | |
| 				_tilesWaitingProcessing.Remove(tile);
 | |
| 			}
 | |
| 
 | |
| 			if (_layerBuilder != null)
 | |
| 			{
 | |
| 				foreach (var layer in _layerBuilder.Values)
 | |
| 				{
 | |
| 					foreach (var visualizer in layer)
 | |
| 					{
 | |
| 						visualizer.UnregisterTile(tile);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public override void Clear()
 | |
| 		{
 | |
| 			DestroyImmediate(DataFetcher);
 | |
| 			if (_layerBuilder != null)
 | |
| 			{
 | |
| 				foreach (var layerList in _layerBuilder.Values)
 | |
| 				{
 | |
| 					foreach (var layerVisualizerBase in layerList)
 | |
| 					{
 | |
| 						layerVisualizerBase.Clear();
 | |
| 						DestroyImmediate(layerVisualizerBase);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				_layerProgress.Clear();
 | |
| 				_tilesWaitingResponse.Clear();
 | |
| 				_tilesWaitingProcessing.Clear();
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public override void SetOptions(LayerProperties options)
 | |
| 		{
 | |
| 			_properties = (VectorLayerProperties)options;
 | |
| 			if (_layerBuilder != null)
 | |
| 			{
 | |
| 				RemoveAllLayerVisualiers();
 | |
| 
 | |
| 				CreatePOILayerVisualizers();
 | |
| 
 | |
| 				CreateLayerVisualizers();
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public override void UpdateTileProperty(UnityTile tile, LayerUpdateArgs updateArgs)
 | |
| 		{
 | |
| 			updateArgs.property.UpdateProperty(tile);
 | |
| 
 | |
| 			if (updateArgs.property.NeedsForceUpdate())
 | |
| 			{
 | |
| 				Unregister(tile);
 | |
| 			}
 | |
| 			Register(tile);
 | |
| 		}
 | |
| 
 | |
| 		protected override void UpdateTileFactory(object sender, EventArgs args)
 | |
| 		{
 | |
| 			VectorLayerUpdateArgs layerUpdateArgs = args as VectorLayerUpdateArgs;
 | |
| 			layerUpdateArgs.factory = this;
 | |
| 			base.UpdateTileFactory(sender, layerUpdateArgs);
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Method to be called when a tile error has occurred.
 | |
| 		/// </summary>
 | |
| 		/// <param name="e"><see cref="T:Mapbox.Map.TileErrorEventArgs"/> instance/</param>
 | |
| 		protected override void OnErrorOccurred(UnityTile tile, TileErrorEventArgs e)
 | |
| 		{
 | |
| 			base.OnErrorOccurred(tile, e);
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnPostProcess(UnityTile tile)
 | |
| 		{
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		public override void UnbindEvents()
 | |
| 		{
 | |
| 			base.UnbindEvents();
 | |
| 		}
 | |
| 
 | |
| 		protected override void OnUnbindEvents()
 | |
| 		{
 | |
| 			if (_layerBuilder != null)
 | |
| 			{
 | |
| 				foreach (var layer in _layerBuilder.Values)
 | |
| 				{
 | |
| 					foreach (var visualizer in layer)
 | |
| 					{
 | |
| 						visualizer.LayerVisualizerHasChanged -= UpdateTileFactory;
 | |
| 						visualizer.UnbindSubLayerEvents();
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 		#region DataFetcherEvents
 | |
| 		private void OnVectorDataRecieved(UnityTile tile, Mapbox.Map.VectorTile vectorTile)
 | |
| 		{
 | |
| 			if (tile != null)
 | |
| 			{
 | |
| 				_tilesWaitingResponse.Remove(tile);
 | |
| 				if (tile.VectorDataState != TilePropertyState.Unregistered)
 | |
| 				{
 | |
| 					tile.SetVectorData(vectorTile);
 | |
| 					// FIXME: we can make the request BEFORE getting a response from these!
 | |
| 					if (tile.HeightDataState == TilePropertyState.Loading ||
 | |
| 							tile.RasterDataState == TilePropertyState.Loading)
 | |
| 					{
 | |
| 						tile.OnHeightDataChanged += DataChangedHandler;
 | |
| 						tile.OnRasterDataChanged += DataChangedHandler;
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						CreateMeshes(tile);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void DataChangedHandler(UnityTile tile)
 | |
| 		{
 | |
| 			if (tile.VectorDataState != TilePropertyState.Unregistered &&
 | |
| 				tile.RasterDataState != TilePropertyState.Loading &&
 | |
| 				tile.HeightDataState != TilePropertyState.Loading)
 | |
| 			{
 | |
| 				tile.OnHeightDataChanged -= DataChangedHandler;
 | |
| 				tile.OnRasterDataChanged -= DataChangedHandler;
 | |
| 				CreateMeshes(tile);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void OnDataError(UnityTile tile, Mapbox.Map.VectorTile vectorTile, TileErrorEventArgs e)
 | |
| 		{
 | |
| 			if (tile != null)
 | |
| 			{
 | |
| 				_tilesWaitingResponse.Remove(tile);
 | |
| 				if (tile.VectorDataState != TilePropertyState.Unregistered)
 | |
| 				{
 | |
| 					tile.SetVectorData(null);
 | |
| 					tile.VectorDataState = TilePropertyState.Error;
 | |
| 					OnErrorOccurred(e);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 		#region Private Methods
 | |
| 		private void CreateMeshes(UnityTile tile)
 | |
| 		{
 | |
| 			var nameList = new List<string>();
 | |
| 			var builderList = new List<LayerVisualizerBase>();
 | |
| 
 | |
| 			foreach (var layerName in tile.VectorData.Data.LayerNames())
 | |
| 			{
 | |
| 				if (_layerBuilder.ContainsKey(layerName))
 | |
| 				{
 | |
| 					//two loops; first one to add it to waiting/tracking list, second to start it
 | |
| 					foreach (var builder in _layerBuilder[layerName])
 | |
| 					{
 | |
| 						nameList.Add(layerName);
 | |
| 						builderList.Add(builder);
 | |
| 						TrackFeatureWithBuilder(tile, layerName, builder);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			for (int i = 0; i < nameList.Count; i++)
 | |
| 			{
 | |
| 				CreateFeatureWithBuilder(tile, nameList[i], builderList[i]);
 | |
| 			}
 | |
| 
 | |
| 			builderList.Clear();
 | |
| 			//emptylayer for visualizers that don't depend on outside data sources
 | |
| 			string emptyLayer = "";
 | |
| 			if (_layerBuilder.ContainsKey(emptyLayer))
 | |
| 			{
 | |
| 				//two loops; first one to add it to waiting/tracking list, second to start it
 | |
| 				foreach (var builder in _layerBuilder[emptyLayer])
 | |
| 				{
 | |
| 					builderList.Add(builder);
 | |
| 					TrackFeatureWithBuilder(tile, emptyLayer, builder);
 | |
| 				}
 | |
| 			}
 | |
| 			for (int i = 0; i < builderList.Count; i++)
 | |
| 			{
 | |
| 				CreateFeatureWithBuilder(tile, emptyLayer, builderList[i]);
 | |
| 			}
 | |
| 
 | |
| 			if (!_layerProgress.ContainsKey(tile))
 | |
| 			{
 | |
| 				tile.VectorDataState = TilePropertyState.Loaded;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void TrackFeatureWithBuilder(UnityTile tile, string layerName, LayerVisualizerBase builder)
 | |
| 		{
 | |
| 			if (builder.Active)
 | |
| 			{
 | |
| 				if (_layerProgress.ContainsKey(tile))
 | |
| 				{
 | |
| 					_layerProgress[tile].Add(builder);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					_layerProgress.Add(tile, new HashSet<LayerVisualizerBase> {builder});
 | |
| 					if (!_tilesWaitingProcessing.Contains(tile))
 | |
| 					{
 | |
| 						_tilesWaitingProcessing.Add(tile);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void CreateFeatureWithBuilder(UnityTile tile, string layerName, LayerVisualizerBase builder)
 | |
| 		{
 | |
| 			if (builder.Active)
 | |
| 			{
 | |
| 				if (_layerProgress.ContainsKey(tile))
 | |
| 				{
 | |
| 					_layerProgress[tile].Add(builder);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					_layerProgress.Add(tile, new HashSet<LayerVisualizerBase> { builder });
 | |
| 					if (!_tilesWaitingProcessing.Contains(tile))
 | |
| 					{
 | |
| 						_tilesWaitingProcessing.Add(tile);
 | |
| 					}
 | |
| 				}
 | |
| 				if (layerName != "")
 | |
| 				{
 | |
| 					builder.Create(tile.VectorData.Data.GetLayer(layerName), tile, DecreaseProgressCounter);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					//just pass the first available layer - we should create a static null layer for this
 | |
| 					builder.Create(tile.VectorData.Data.GetLayer(tile.VectorData.Data.LayerNames()[0]), tile, DecreaseProgressCounter);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void DecreaseProgressCounter(UnityTile tile, LayerVisualizerBase builder)
 | |
| 		{
 | |
| 			if (_layerProgress.ContainsKey(tile))
 | |
| 			{
 | |
| 				if (_layerProgress[tile].Contains(builder))
 | |
| 				{
 | |
| 					_layerProgress[tile].Remove(builder);
 | |
| 
 | |
| 				}
 | |
| 				if (_layerProgress[tile].Count == 0)
 | |
| 				{
 | |
| 					_layerProgress.Remove(tile);
 | |
| 					_tilesWaitingProcessing.Remove(tile);
 | |
| 					tile.VectorDataState = TilePropertyState.Loaded;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void CreatePOILayerVisualizers()
 | |
| 		{
 | |
| 			foreach (var item in _properties.locationPrefabList)
 | |
| 			{
 | |
| 				AddPOIVectorLayerVisualizer(item);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void CreateLayerVisualizers()
 | |
| 		{
 | |
| 			foreach (var sublayer in _properties.vectorSubLayers)
 | |
| 			{
 | |
| 				AddVectorLayerVisualizer(sublayer);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private void RemoveAllLayerVisualiers()
 | |
| 		{
 | |
| 			//Clearing gameobjects pooled and managed by modifiers to prevent zombie gameobjects.
 | |
| 			foreach (var pairs in _layerBuilder)
 | |
| 			{
 | |
| 				foreach (var layerVisualizerBase in pairs.Value)
 | |
| 				{
 | |
| 					layerVisualizerBase.Clear();
 | |
| 				}
 | |
| 			}
 | |
| 			_layerBuilder.Clear();
 | |
| 		}
 | |
| 		#endregion
 | |
| 
 | |
| 	}
 | |
| }
 | |
| 
 |