[TASK] Initial commit with basic product setup
This commit is contained in:
990
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMap.cs
Normal file
990
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMap.cs
Normal file
@@ -0,0 +1,990 @@
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using Mapbox.Unity.Map.Strategies;
|
||||
using Mapbox.Unity.Map.TileProviders;
|
||||
|
||||
namespace Mapbox.Unity.Map
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using Utils;
|
||||
using UnityEngine;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Factories;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract map.
|
||||
/// This is the main monobehavior which controls the map. It controls the visualization of map data.
|
||||
/// Abstract map encapsulates the image, terrain and vector sources and provides a centralized interface to control the visualization of the map.
|
||||
/// </summary>
|
||||
public class AbstractMap : MonoBehaviour, IMap
|
||||
{
|
||||
#region Private Fields
|
||||
[SerializeField] private MapOptions _options = new MapOptions();
|
||||
[SerializeField] private bool _initializeOnStart = true;
|
||||
[SerializeField] protected ImageryLayer _imagery = new ImageryLayer();
|
||||
[SerializeField] protected TerrainLayer _terrain = new TerrainLayer();
|
||||
[SerializeField] protected VectorLayer _vectorData = new VectorLayer();
|
||||
[SerializeField] protected AbstractTileProvider _tileProvider;
|
||||
[SerializeField] protected HashSet<UnwrappedTileId> _currentExtent;
|
||||
|
||||
protected AbstractMapVisualizer _mapVisualizer;
|
||||
protected float _unityTileSize = 1;
|
||||
protected bool _worldHeightFixed = false;
|
||||
protected MapboxAccess _fileSource;
|
||||
protected int _initialZoom;
|
||||
protected Vector2d _centerLatitudeLongitude;
|
||||
protected Vector2d _centerMercator;
|
||||
protected float _worldRelativeScale;
|
||||
protected Vector3 _mapScaleFactor;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public AbstractMapVisualizer MapVisualizer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _mapVisualizer;
|
||||
}
|
||||
set
|
||||
{
|
||||
_mapVisualizer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractTileProvider TileProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tileProvider;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_tileProvider != null)
|
||||
{
|
||||
_tileProvider.ExtentChanged -= OnMapExtentChanged;
|
||||
}
|
||||
_tileProvider = value;
|
||||
_tileProvider.ExtentChanged += OnMapExtentChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The map options.
|
||||
/// Options to control the behaviour of the map like location,extent, scale and placement.
|
||||
/// </summary>
|
||||
public MapOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
set
|
||||
{
|
||||
_options = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options to control the imagery component of the map.
|
||||
/// </summary>
|
||||
[NodeEditorElement("Layers")]
|
||||
public IImageryLayer ImageLayer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _imagery;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options to control the terrain/ elevation component of the map.
|
||||
/// </summary>
|
||||
[NodeEditorElement("Layers")]
|
||||
public ITerrainLayer Terrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return _terrain;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vector data.
|
||||
/// Options to control the vector data component of the map.
|
||||
/// Adds a vector source and visualizers to define the rendering behaviour of vector data layers.
|
||||
/// </summary>
|
||||
[NodeEditorElement("Layers")]
|
||||
public IVectorDataLayer VectorData
|
||||
{
|
||||
get
|
||||
{
|
||||
return _vectorData;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2d CenterLatitudeLongitude
|
||||
{
|
||||
get
|
||||
{
|
||||
return _centerLatitudeLongitude;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2d CenterMercator
|
||||
{
|
||||
get
|
||||
{
|
||||
return _centerMercator;
|
||||
}
|
||||
}
|
||||
|
||||
public float WorldRelativeScale
|
||||
{
|
||||
get
|
||||
{
|
||||
return _worldRelativeScale;
|
||||
}
|
||||
}
|
||||
|
||||
public float UnityTileSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _unityTileSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute zoom of the tiles being currently rendered.
|
||||
/// <seealso cref="Zoom"/>
|
||||
/// </summary>
|
||||
/// <value>The absolute zoom.</value>
|
||||
public int AbsoluteZoom
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)Math.Floor(Options.locationOptions.zoom);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current zoom value of the map.
|
||||
/// Use <c>AbsoluteZoom</c> to get the zoom level of the tileset.
|
||||
/// <seealso cref="AbsoluteZoom"/>
|
||||
/// </summary>
|
||||
/// <value>The zoom.</value>
|
||||
public float Zoom
|
||||
{
|
||||
get
|
||||
{
|
||||
return Options.locationOptions.zoom;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetZoom(float zoom)
|
||||
{
|
||||
Options.locationOptions.zoom = zoom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial zoom at which the map was initialized.
|
||||
/// This parameter is useful in calculating the scale of the tiles and the map.
|
||||
/// </summary>
|
||||
/// <value>The initial zoom.</value>
|
||||
public int InitialZoom
|
||||
{
|
||||
get
|
||||
{
|
||||
return _initialZoom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Transform Root
|
||||
{
|
||||
get
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting to trigger map initialization in Unity's Start method.
|
||||
/// if set to false, Initialize method should be called explicitly to initialize the map.
|
||||
/// </summary>
|
||||
public bool InitializeOnStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return _initializeOnStart;
|
||||
}
|
||||
set
|
||||
{
|
||||
_initializeOnStart = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<UnwrappedTileId> CurrentExtent
|
||||
{
|
||||
get
|
||||
{
|
||||
return _currentExtent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the loading texture used as a placeholder while the image tile is loading.
|
||||
/// </summary>
|
||||
/// <value>The loading texture.</value>
|
||||
public Texture2D LoadingTexture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _options.loadingTexture;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tile material used for map tiles.
|
||||
/// </summary>
|
||||
/// <value>The tile material.</value>
|
||||
public Material TileMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
return _options.tileMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
public Type ExtentCalculatorType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tileProvider.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Initialize the map using the specified latLon and zoom.
|
||||
/// Map will automatically get initialized in the <c>Start</c> method.
|
||||
/// Use this method to explicitly initialize the map and disable intialize on <c>Start</c>
|
||||
/// </summary>
|
||||
/// <returns>The initialize.</returns>
|
||||
/// <param name="latLon">Lat lon.</param>
|
||||
/// <param name="zoom">Zoom.</param>
|
||||
public virtual void Initialize(Vector2d latLon, int zoom)
|
||||
{
|
||||
_initializeOnStart = false;
|
||||
if (_options == null)
|
||||
{
|
||||
_options = new MapOptions();
|
||||
}
|
||||
_options.locationOptions.latitudeLongitude = String.Format(CultureInfo.InvariantCulture, "{0},{1}", latLon.x, latLon.y);
|
||||
_options.locationOptions.zoom = zoom;
|
||||
|
||||
SetUpMap();
|
||||
}
|
||||
|
||||
public virtual void UpdateMap()
|
||||
{
|
||||
UpdateMap(Conversions.StringToLatLon(_options.locationOptions.latitudeLongitude), Zoom);
|
||||
}
|
||||
|
||||
public virtual void UpdateMap(Vector2d latLon)
|
||||
{
|
||||
UpdateMap(latLon, Zoom);
|
||||
}
|
||||
|
||||
public virtual void UpdateMap(float zoom)
|
||||
{
|
||||
UpdateMap(Conversions.StringToLatLon(_options.locationOptions.latitudeLongitude), zoom);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the map.
|
||||
/// Use this method to update the location of the map.
|
||||
/// Update method should be used when panning, zooming or changing location of the map.
|
||||
/// This method avoid startup delays that might occur on re-initializing the map.
|
||||
/// </summary>
|
||||
/// <param name="latLon">LatitudeLongitude.</param>
|
||||
/// <param name="zoom">Zoom level.</param>
|
||||
public virtual void UpdateMap(Vector2d latLon, float zoom)
|
||||
{
|
||||
//so map will be snapped to zero using next new tile loaded
|
||||
_worldHeightFixed = false;
|
||||
float differenceInZoom = 0.0f;
|
||||
bool isAtInitialZoom = false;
|
||||
// Update map zoom, if it has changed.
|
||||
if (Math.Abs(Zoom - zoom) > Constants.EpsilonFloatingPoint)
|
||||
{
|
||||
SetZoom(zoom);
|
||||
}
|
||||
|
||||
// Compute difference in zoom. Will be used to calculate correct scale of the map.
|
||||
differenceInZoom = Zoom - InitialZoom;
|
||||
isAtInitialZoom = (differenceInZoom - 0.0 < Constants.EpsilonFloatingPoint);
|
||||
|
||||
//Update center latitude longitude
|
||||
var centerLatitudeLongitude = latLon;
|
||||
double xDelta = centerLatitudeLongitude.x;
|
||||
double zDelta = centerLatitudeLongitude.y;
|
||||
|
||||
xDelta = xDelta > 0 ? Mathd.Min(xDelta, Mapbox.Utils.Constants.LatitudeMax) : Mathd.Max(xDelta, -Mapbox.Utils.Constants.LatitudeMax);
|
||||
zDelta = zDelta > 0 ? Mathd.Min(zDelta, Mapbox.Utils.Constants.LongitudeMax) : Mathd.Max(zDelta, -Mapbox.Utils.Constants.LongitudeMax);
|
||||
|
||||
//Set Center in Latitude Longitude and Mercator.
|
||||
SetCenterLatitudeLongitude(new Vector2d(xDelta, zDelta));
|
||||
Options.scalingOptions.scalingStrategy.SetUpScaling(this);
|
||||
Options.placementOptions.placementStrategy.SetUpPlacement(this);
|
||||
|
||||
//Scale the map accordingly.
|
||||
if (Math.Abs(differenceInZoom) > Constants.EpsilonFloatingPoint || isAtInitialZoom)
|
||||
{
|
||||
_mapScaleFactor = Vector3.one * Mathf.Pow(2, differenceInZoom);
|
||||
Root.localScale = _mapScaleFactor;
|
||||
}
|
||||
|
||||
//Update Tile extent.
|
||||
_tileProvider.UpdateTileExtent();
|
||||
|
||||
if (OnUpdated != null)
|
||||
{
|
||||
OnUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the map.
|
||||
/// Use this method to reset the map to and reset all parameters.
|
||||
/// </summary>
|
||||
[ContextMenu("ResetMap")]
|
||||
public void ResetMap()
|
||||
{
|
||||
//Initialize(Conversions.StringToLatLon(_options.locationOptions.latitudeLongitude), (int)_options.locationOptions.zoom);
|
||||
|
||||
_mapVisualizer.UnregisterAllTiles();
|
||||
_mapVisualizer.ClearCaches();
|
||||
_mapVisualizer.ReregisterAllTiles();
|
||||
}
|
||||
|
||||
public bool IsAccessTokenValid
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isAccessTokenValid = false;
|
||||
try
|
||||
{
|
||||
var accessTokenCheck = Unity.MapboxAccess.Instance;
|
||||
if (Unity.MapboxAccess.Instance.Configuration == null || string.IsNullOrEmpty(Unity.MapboxAccess.Instance.Configuration.AccessToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
isAccessTokenValid = true;
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
isAccessTokenValid = false;
|
||||
}
|
||||
return isAccessTokenValid;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private/Protected Methods
|
||||
protected virtual void Awake()
|
||||
{
|
||||
// Setup a visualizer to get a "Starter" map.
|
||||
_mapVisualizer = ScriptableObject.CreateInstance<MapVisualizer>();
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
protected virtual void Start()
|
||||
{
|
||||
StartCoroutine("SetupAccess");
|
||||
if (_initializeOnStart)
|
||||
{
|
||||
SetUpMap();
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerator SetupAccess()
|
||||
{
|
||||
_fileSource = MapboxAccess.Instance;
|
||||
|
||||
yield return new WaitUntil(() => MapboxAccess.Configured);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets up map.
|
||||
/// This method uses the mapOptions and layer properties to setup the map to be rendered.
|
||||
/// Override <c>SetUpMap</c> to write custom behavior to map setup.
|
||||
/// </summary>
|
||||
protected virtual void SetUpMap()
|
||||
{
|
||||
SetPlacementStrategy();
|
||||
|
||||
SetScalingStrategy();
|
||||
|
||||
SetTileProvider();
|
||||
|
||||
if (_imagery == null)
|
||||
{
|
||||
_imagery = new ImageryLayer();
|
||||
}
|
||||
_imagery.Initialize();
|
||||
|
||||
if (_terrain == null)
|
||||
{
|
||||
_terrain = new TerrainLayer();
|
||||
}
|
||||
_terrain.Initialize();
|
||||
|
||||
if (_vectorData == null)
|
||||
{
|
||||
_vectorData = new VectorLayer();
|
||||
}
|
||||
_vectorData.Initialize();
|
||||
|
||||
_mapVisualizer.Factories = new List<AbstractTileFactory>
|
||||
{
|
||||
_terrain.Factory,
|
||||
_imagery.Factory,
|
||||
_vectorData.Factory
|
||||
};
|
||||
|
||||
InitializeMap(_options);
|
||||
}
|
||||
|
||||
protected virtual void TileProvider_OnTileAdded(UnwrappedTileId tileId)
|
||||
{
|
||||
var tile = _mapVisualizer.LoadTile(tileId);
|
||||
|
||||
if (Options.placementOptions.snapMapToZero && !_worldHeightFixed)
|
||||
{
|
||||
_worldHeightFixed = true;
|
||||
if (tile.HeightDataState == MeshGeneration.Enums.TilePropertyState.Loaded)
|
||||
{
|
||||
ApplySnapWorldToZero(tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile.OnHeightDataChanged += (s) =>
|
||||
{
|
||||
ApplySnapWorldToZero(tile);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void TileProvider_OnTileRemoved(UnwrappedTileId tileId)
|
||||
{
|
||||
_mapVisualizer.DisposeTile(tileId);
|
||||
}
|
||||
|
||||
protected virtual void TileProvider_OnTileRepositioned(UnwrappedTileId tileId)
|
||||
{
|
||||
_mapVisualizer.RepositionTile(tileId);
|
||||
}
|
||||
|
||||
protected void SendInitialized()
|
||||
{
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply Snap World to Zero setting by moving map in Y Axis such that
|
||||
/// center of the given tile will be at y=0.
|
||||
/// </summary>
|
||||
/// <param name="referenceTile">Tile to use for Y axis correction.</param>
|
||||
private void ApplySnapWorldToZero(UnityTile referenceTile)
|
||||
{
|
||||
if (_options.placementOptions.snapMapToZero)
|
||||
{
|
||||
var h = referenceTile.QueryHeightData(.5f, .5f);
|
||||
Root.transform.position = new Vector3(
|
||||
Root.transform.position.x,
|
||||
-h,
|
||||
Root.transform.position.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
Root.transform.position = new Vector3(
|
||||
Root.transform.position.x,
|
||||
0,
|
||||
Root.transform.position.z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the map using the mapOptions.
|
||||
/// </summary>
|
||||
/// <param name="options">Options.</param>
|
||||
protected virtual void InitializeMap(MapOptions options)
|
||||
{
|
||||
Options = options;
|
||||
_worldHeightFixed = false;
|
||||
_fileSource = MapboxAccess.Instance;
|
||||
_centerLatitudeLongitude = Conversions.StringToLatLon(options.locationOptions.latitudeLongitude);
|
||||
_initialZoom = (int)options.locationOptions.zoom;
|
||||
|
||||
options.scalingOptions.scalingStrategy.SetUpScaling(this);
|
||||
options.placementOptions.placementStrategy.SetUpPlacement(this);
|
||||
|
||||
|
||||
//Set up events for changes.
|
||||
_imagery.UpdateLayer += OnImageOrTerrainUpdateLayer;
|
||||
_terrain.UpdateLayer += OnImageOrTerrainUpdateLayer;
|
||||
|
||||
_vectorData.SubLayerRemoved += OnVectorDataSubLayerRemoved;
|
||||
_vectorData.SubLayerAdded += OnVectorDataSubLayerAdded;
|
||||
_vectorData.UpdateLayer += OnVectorDataUpdateLayer;
|
||||
|
||||
_options.locationOptions.PropertyHasChanged += (object sender, System.EventArgs eventArgs) =>
|
||||
{
|
||||
//take care of redraw map business...
|
||||
UpdateMap();
|
||||
};
|
||||
|
||||
_options.extentOptions.PropertyHasChanged += (object sender, System.EventArgs eventArgs) =>
|
||||
{
|
||||
//take care of redraw map business...
|
||||
OnTileProviderChanged();
|
||||
};
|
||||
|
||||
_options.extentOptions.defaultExtents.PropertyHasChanged += (object sender, System.EventArgs eventArgs) =>
|
||||
{
|
||||
//take care of redraw map business...
|
||||
_tileProvider.UpdateTileExtent();
|
||||
};
|
||||
|
||||
_options.placementOptions.PropertyHasChanged += (object sender, System.EventArgs eventArgs) =>
|
||||
{
|
||||
//take care of redraw map business...
|
||||
SetPlacementStrategy();
|
||||
UpdateMap();
|
||||
};
|
||||
|
||||
_options.scalingOptions.PropertyHasChanged += (object sender, System.EventArgs eventArgs) =>
|
||||
{
|
||||
//take care of redraw map business...
|
||||
SetScalingStrategy();
|
||||
UpdateMap();
|
||||
};
|
||||
|
||||
_mapVisualizer.Initialize(this, _fileSource);
|
||||
_tileProvider.Initialize(this);
|
||||
|
||||
SendInitialized();
|
||||
|
||||
_tileProvider.UpdateTileExtent();
|
||||
}
|
||||
|
||||
private void SetScalingStrategy()
|
||||
{
|
||||
switch (_options.scalingOptions.scalingType)
|
||||
{
|
||||
case MapScalingType.WorldScale:
|
||||
_options.scalingOptions.scalingStrategy = new MapScalingAtWorldScaleStrategy();
|
||||
break;
|
||||
case MapScalingType.Custom:
|
||||
_options.scalingOptions.scalingStrategy = new MapScalingAtUnityScaleStrategy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPlacementStrategy()
|
||||
{
|
||||
switch (_options.placementOptions.placementType)
|
||||
{
|
||||
case MapPlacementType.AtTileCenter:
|
||||
_options.placementOptions.placementStrategy = new MapPlacementAtTileCenterStrategy();
|
||||
break;
|
||||
case MapPlacementType.AtLocationCenter:
|
||||
_options.placementOptions.placementStrategy = new MapPlacementAtLocationCenterStrategy();
|
||||
break;
|
||||
default:
|
||||
_options.placementOptions.placementStrategy = new MapPlacementAtTileCenterStrategy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTileProvider()
|
||||
{
|
||||
if (_options.extentOptions.extentType != MapExtentType.Custom)
|
||||
{
|
||||
ITileProviderOptions tileProviderOptions = _options.extentOptions.GetTileProviderOptions();
|
||||
// Setup tileprovider based on type.
|
||||
switch (_options.extentOptions.extentType)
|
||||
{
|
||||
case MapExtentType.CameraBounds:
|
||||
TileProvider = gameObject.AddComponent<QuadTreeTileProvider>();
|
||||
break;
|
||||
case MapExtentType.RangeAroundCenter:
|
||||
TileProvider = gameObject.AddComponent<RangeTileProvider>();
|
||||
break;
|
||||
case MapExtentType.RangeAroundTransform:
|
||||
TileProvider = gameObject.AddComponent<RangeAroundTransformTileProvider>();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TileProvider.SetOptions(tileProviderOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
TileProvider = _tileProvider;
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerTileRedrawForExtent(ExtentArgs currentExtent)
|
||||
{
|
||||
var _activeTiles = _mapVisualizer.ActiveTiles;
|
||||
_currentExtent = new HashSet<UnwrappedTileId>(currentExtent.activeTiles);
|
||||
|
||||
List<UnwrappedTileId> _toRemove = new List<UnwrappedTileId>();
|
||||
foreach (var item in _activeTiles)
|
||||
{
|
||||
if (_tileProvider.Cleanup(item.Key)) //(!_currentExtent.Contains(item.Key))
|
||||
{
|
||||
_toRemove.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var t2r in _toRemove)
|
||||
{
|
||||
TileProvider_OnTileRemoved(t2r);
|
||||
}
|
||||
|
||||
foreach (var tile in _activeTiles)
|
||||
{
|
||||
// Reposition tiles in case we panned.
|
||||
TileProvider_OnTileRepositioned(tile.Key);
|
||||
}
|
||||
|
||||
foreach (var tile in _currentExtent)
|
||||
{
|
||||
if (!_activeTiles.ContainsKey(tile))
|
||||
{
|
||||
// Change Map Visualizer state
|
||||
_mapVisualizer.State = ModuleState.Working;
|
||||
TileProvider_OnTileAdded(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapExtentChanged(object sender, ExtentArgs currentExtent)
|
||||
{
|
||||
TriggerTileRedrawForExtent(currentExtent);
|
||||
}
|
||||
|
||||
// TODO: implement IDisposable, instead?
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (_tileProvider != null)
|
||||
{
|
||||
_tileProvider.ExtentChanged -= OnMapExtentChanged;
|
||||
}
|
||||
|
||||
_mapVisualizer.Destroy();
|
||||
}
|
||||
|
||||
private void OnImageOrTerrainUpdateLayer(object sender, System.EventArgs eventArgs)
|
||||
{
|
||||
LayerUpdateArgs layerUpdateArgs = eventArgs as LayerUpdateArgs;
|
||||
if (layerUpdateArgs != null)
|
||||
{
|
||||
_mapVisualizer.UpdateTileForProperty(layerUpdateArgs.factory, layerUpdateArgs);
|
||||
if (layerUpdateArgs.effectsVectorLayer)
|
||||
{
|
||||
RedrawVectorDataLayer();
|
||||
}
|
||||
OnMapRedrawn();
|
||||
}
|
||||
}
|
||||
|
||||
private void RedrawVectorDataLayer()
|
||||
{
|
||||
_mapVisualizer.UnregisterTilesFrom(_vectorData.Factory);
|
||||
_vectorData.UnbindAllEvents();
|
||||
_vectorData.UpdateFactorySettings();
|
||||
_mapVisualizer.ReregisterTilesTo(_vectorData.Factory);
|
||||
}
|
||||
|
||||
private void OnVectorDataSubLayerRemoved(object sender, EventArgs eventArgs)
|
||||
{
|
||||
VectorLayerUpdateArgs layerUpdateArgs = eventArgs as VectorLayerUpdateArgs;
|
||||
|
||||
if (layerUpdateArgs.visualizer != null)
|
||||
{
|
||||
_mapVisualizer.RemoveTilesFromLayer((VectorTileFactory)layerUpdateArgs.factory, layerUpdateArgs.visualizer);
|
||||
}
|
||||
OnMapRedrawn();
|
||||
}
|
||||
|
||||
private void OnVectorDataSubLayerAdded(object sender, EventArgs eventArgs)
|
||||
{
|
||||
RedrawVectorDataLayer();
|
||||
OnMapRedrawn();
|
||||
}
|
||||
|
||||
private void OnVectorDataUpdateLayer(object sender, System.EventArgs eventArgs)
|
||||
{
|
||||
|
||||
VectorLayerUpdateArgs layerUpdateArgs = eventArgs as VectorLayerUpdateArgs;
|
||||
|
||||
if (layerUpdateArgs.visualizer != null)
|
||||
{
|
||||
//we got a visualizer. Update only the visualizer.
|
||||
// No need to unload the entire factory to apply changes.
|
||||
_mapVisualizer.UnregisterAndRedrawTilesFromLayer((VectorTileFactory)layerUpdateArgs.factory, layerUpdateArgs.visualizer);
|
||||
}
|
||||
else
|
||||
{
|
||||
//We are updating a core property of vector section.
|
||||
//All vector features need to get unloaded and re-created.
|
||||
RedrawVectorDataLayer();
|
||||
}
|
||||
OnMapRedrawn();
|
||||
}
|
||||
|
||||
private void OnTileProviderChanged()
|
||||
{
|
||||
var currentTileProvider = gameObject.GetComponent<AbstractTileProvider>();
|
||||
|
||||
if (currentTileProvider != null)
|
||||
{
|
||||
Destroy(currentTileProvider);
|
||||
}
|
||||
SetTileProvider();
|
||||
_tileProvider.Initialize(this);
|
||||
_tileProvider.UpdateTileExtent();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Conversion and Height Query Methods
|
||||
private Vector3 GeoToWorldPositionXZ(Vector2d latitudeLongitude)
|
||||
{
|
||||
// For quadtree implementation of the map, the map scale needs to be compensated for.
|
||||
var scaleFactor = Mathf.Pow(2, (InitialZoom - AbsoluteZoom));
|
||||
var worldPos = Conversions.GeoToWorldPosition(latitudeLongitude, CenterMercator, WorldRelativeScale * scaleFactor).ToVector3xz();
|
||||
return Root.TransformPoint(worldPos);
|
||||
}
|
||||
|
||||
protected virtual float QueryElevationAtInternal(Vector2d latlong, out float tileScale)
|
||||
{
|
||||
var _meters = Conversions.LatLonToMeters(latlong.x, latlong.y);
|
||||
UnityTile tile;
|
||||
bool foundTile = MapVisualizer.ActiveTiles.TryGetValue(Conversions.LatitudeLongitudeToTileId(latlong.x, latlong.y, (int)Zoom), out tile);
|
||||
if (foundTile)
|
||||
{
|
||||
tileScale = tile.TileScale;
|
||||
var _rect = tile.Rect;
|
||||
return tile.QueryHeightData((float)((_meters - _rect.Min).x / _rect.Size.x), (float)((_meters.y - _rect.Max.y) / _rect.Size.y));
|
||||
}
|
||||
else
|
||||
{
|
||||
tileScale = 1f;
|
||||
return 0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a latitude longitude into map space position.
|
||||
/// </summary>
|
||||
/// <returns>Position in map space.</returns>
|
||||
/// <param name="latitudeLongitude">Latitude longitude.</param>
|
||||
/// <param name="queryHeight">If set to <c>true</c> will return the terrain height(in Unity units) at that point.</param>
|
||||
public virtual Vector3 GeoToWorldPosition(Vector2d latitudeLongitude, bool queryHeight = true)
|
||||
{
|
||||
Vector3 worldPos = GeoToWorldPositionXZ(latitudeLongitude);
|
||||
|
||||
if (queryHeight)
|
||||
{
|
||||
//Query Height.
|
||||
float tileScale = 1f;
|
||||
float height = QueryElevationAtInternal(latitudeLongitude, out tileScale);
|
||||
|
||||
// Apply height inside the unity tile space
|
||||
UnityTile tile;
|
||||
if (MapVisualizer.ActiveTiles.TryGetValue(Conversions.LatitudeLongitudeToTileId(latitudeLongitude.x, latitudeLongitude.y, (int)Zoom), out tile))
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
// Calculate height in the local space of the tile gameObject.
|
||||
// Height is aligned with the y axis in local space.
|
||||
// This also helps us avoid scale values when setting the height.
|
||||
var localPos = tile.gameObject.transform.InverseTransformPoint(worldPos);
|
||||
localPos.y = height;
|
||||
worldPos = tile.gameObject.transform.TransformPoint(localPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a position in map space into a laitude longitude.
|
||||
/// </summary>
|
||||
/// <returns>Position in Latitude longitude.</returns>
|
||||
/// <param name="realworldPoint">Realworld point.</param>
|
||||
public virtual Vector2d WorldToGeoPosition(Vector3 realworldPoint)
|
||||
{
|
||||
// For quadtree implementation of the map, the map scale needs to be compensated for.
|
||||
var scaleFactor = Mathf.Pow(2, (InitialZoom - AbsoluteZoom));
|
||||
|
||||
return (Root.InverseTransformPoint(realworldPoint)).GetGeoPosition(CenterMercator, WorldRelativeScale * scaleFactor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the real world elevation data in Unity units at a given latitude longitude.
|
||||
/// </summary>
|
||||
/// <returns>The height data.</returns>
|
||||
/// <param name="latlong">Latlong.</param>
|
||||
public virtual float QueryElevationInUnityUnitsAt(Vector2d latlong)
|
||||
{
|
||||
float tileScale = 1f;
|
||||
return QueryElevationAtInternal(latlong, out tileScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the real world elevation data in Meters at a given latitude longitude.
|
||||
/// </summary>
|
||||
/// <returns>The height data.</returns>
|
||||
/// <param name="latlong">Latlong.</param>
|
||||
public virtual float QueryElevationInMetersAt(Vector2d latlong)
|
||||
{
|
||||
float tileScale = 1f;
|
||||
float height = QueryElevationAtInternal(latlong, out tileScale);
|
||||
return (height / tileScale);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Map Property Related Changes Methods
|
||||
public virtual void SetCenterMercator(Vector2d centerMercator)
|
||||
{
|
||||
_centerMercator = centerMercator;
|
||||
}
|
||||
|
||||
public virtual void SetCenterLatitudeLongitude(Vector2d centerLatitudeLongitude)
|
||||
{
|
||||
_options.locationOptions.latitudeLongitude = string.Format("{0}, {1}", centerLatitudeLongitude.x, centerLatitudeLongitude.y);
|
||||
_centerLatitudeLongitude = centerLatitudeLongitude;
|
||||
}
|
||||
|
||||
public virtual void SetWorldRelativeScale(float scale)
|
||||
{
|
||||
_worldRelativeScale = scale;
|
||||
}
|
||||
|
||||
public virtual void SetLoadingTexture(Texture2D loadingTexture)
|
||||
{
|
||||
Options.loadingTexture = loadingTexture;
|
||||
}
|
||||
|
||||
public virtual void SetTileMaterial(Material tileMaterial)
|
||||
{
|
||||
Options.tileMaterial = tileMaterial;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extent type and parameters to control the maps extent.
|
||||
/// </summary>
|
||||
/// <param name="extentType">Extent type.</param>
|
||||
/// <param name="extentOptions">Extent options.</param>
|
||||
public virtual void SetExtent(MapExtentType extentType, ExtentOptions extentOptions = null)
|
||||
{
|
||||
_options.extentOptions.extentType = extentType;
|
||||
|
||||
if (extentOptions != null)
|
||||
{
|
||||
var currentOptions = _options.extentOptions.GetTileProviderOptions();
|
||||
if (currentOptions.GetType() == extentOptions.GetType())
|
||||
{
|
||||
currentOptions = extentOptions;
|
||||
}
|
||||
}
|
||||
OnTileProviderChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters for current extent calculator strategy.
|
||||
/// </summary>
|
||||
/// <param name="extentOptions">Parameters to control the map extent.</param>
|
||||
public virtual void SetExtentOptions(ExtentOptions extentOptions)
|
||||
{
|
||||
_options.extentOptions.GetTileProviderOptions().SetOptions(extentOptions);
|
||||
_options.extentOptions.defaultExtents.HasChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the positions of the map's root transform.
|
||||
/// Use <paramref name="placementType"/> = <c> MapPlacementType.AtTileCenter</c> to place map root at the center of tile containing the latitude,longitude.
|
||||
/// Use <paramref name="placementType"/> = <c> MapPlacementType.AtLocationCenter</c> to place map root at the latitude,longitude.
|
||||
/// </summary>
|
||||
/// <param name="placementType">Placement type.</param>
|
||||
public virtual void SetPlacementType(MapPlacementType placementType)
|
||||
{
|
||||
_options.placementOptions.placementType = placementType;
|
||||
_options.placementOptions.HasChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates map root by the terrain elevation at the center geo location.
|
||||
/// Use this method with <c>TerrainWithElevation</c>
|
||||
/// </summary>
|
||||
/// <param name="active">If set to <c>true</c> active.</param>
|
||||
public virtual void SnapMapToZero(bool active)
|
||||
{
|
||||
_options.placementOptions.snapMapToZero = active;
|
||||
_options.placementOptions.HasChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the map to use real world scale for map tile.
|
||||
/// Use world scale for AR use cases or applications that need true world scale.
|
||||
/// </summary>
|
||||
public virtual void UseWorldScale()
|
||||
{
|
||||
_options.scalingOptions.scalingType = MapScalingType.WorldScale;
|
||||
_options.scalingOptions.HasChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the map to use custom scale for map tiles.
|
||||
/// </summary>
|
||||
/// <param name="tileSizeInUnityUnits">Tile size in unity units to scale each Web Mercator tile.</param>
|
||||
public virtual void UseCustomScale(float tileSizeInUnityUnits)
|
||||
{
|
||||
_options.scalingOptions.scalingType = MapScalingType.Custom;
|
||||
_options.scalingOptions.unityTileSize = tileSizeInUnityUnits;
|
||||
_options.scalingOptions.HasChanged = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Event delegate, gets called after map is initialized
|
||||
/// <seealso cref="OnUpdated"/>
|
||||
/// </summary>
|
||||
public event Action OnInitialized = delegate { };
|
||||
/// <summary>
|
||||
/// Event delegate, gets called after map is updated.
|
||||
/// <c>UpdateMap</c> will trigger this event.
|
||||
/// <seealso cref="OnInitialized"/>
|
||||
/// </summary>
|
||||
public event Action OnUpdated = delegate { };
|
||||
public event Action OnMapRedrawn = delegate { };
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMap.cs.meta
Normal file
13
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMap.cs.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd961b1c9541a4cee99686069ecce852
|
||||
timeCreated: 1520299462
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
356
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMapVisualizer.cs
Normal file
356
Assets/Mapbox SDK/Mapbox/Unity/Map/AbstractMapVisualizer.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
|
||||
namespace Mapbox.Unity.Map
|
||||
{
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Factories;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using System;
|
||||
using Mapbox.Platform;
|
||||
using UnityEngine.Serialization;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using Mapbox.Unity.MeshGeneration.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Map Visualizer
|
||||
/// Represents a map.Doesn’t contain much logic and at the moment, it creates requested tiles and relays them to the factories
|
||||
/// under itself.It has a caching mechanism to reuse tiles and does the tile positioning in unity world.
|
||||
/// Later we’ll most likely keep track of map features here as well to allow devs to query for features easier
|
||||
/// (i.e.query all buildings x meters around any restaurant etc).
|
||||
/// </summary>
|
||||
public abstract class AbstractMapVisualizer : ScriptableObject
|
||||
{
|
||||
[SerializeField]
|
||||
[NodeEditorElementAttribute("Factories")]
|
||||
[FormerlySerializedAs("_factories")]
|
||||
public List<AbstractTileFactory> Factories;
|
||||
|
||||
protected IMapReadable _map;
|
||||
protected Dictionary<UnwrappedTileId, UnityTile> _activeTiles = new Dictionary<UnwrappedTileId, UnityTile>();
|
||||
protected Queue<UnityTile> _inactiveTiles = new Queue<UnityTile>();
|
||||
private int _counter;
|
||||
|
||||
private ModuleState _state;
|
||||
public ModuleState State
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
if (_state != value)
|
||||
{
|
||||
_state = value;
|
||||
OnMapVisualizerStateChanged(_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IMapReadable Map { get { return _map; } }
|
||||
public Dictionary<UnwrappedTileId, UnityTile> ActiveTiles { get { return _activeTiles; } }
|
||||
public Dictionary<UnwrappedTileId, int> _tileProgress;
|
||||
|
||||
public event Action<ModuleState> OnMapVisualizerStateChanged = delegate { };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unity tile from unwrapped tile identifier.
|
||||
/// </summary>
|
||||
/// <returns>The unity tile from unwrapped tile identifier.</returns>
|
||||
/// <param name="tileId">Tile identifier.</param>
|
||||
public UnityTile GetUnityTileFromUnwrappedTileId(UnwrappedTileId tileId)
|
||||
{
|
||||
return _activeTiles[tileId];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the factories by passing the file source down, which is necessary for data (web/file) calls
|
||||
/// </summary>
|
||||
/// <param name="fileSource"></param>
|
||||
public virtual void Initialize(IMapReadable map, IFileSource fileSource)
|
||||
{
|
||||
_map = map;
|
||||
_tileProgress = new Dictionary<UnwrappedTileId, int>();
|
||||
|
||||
// Allow for map re-use by recycling any active tiles.
|
||||
var activeTiles = _activeTiles.Keys.ToList();
|
||||
foreach (var tile in activeTiles)
|
||||
{
|
||||
DisposeTile(tile);
|
||||
}
|
||||
|
||||
State = ModuleState.Initialized;
|
||||
|
||||
foreach (var factory in Factories)
|
||||
{
|
||||
if (null == factory)
|
||||
{
|
||||
Debug.LogError("AbstractMapVisualizer: Factory is NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
factory.Initialize(fileSource);
|
||||
UnregisterEvents(factory);
|
||||
RegisterEvents(factory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterEvents(AbstractTileFactory factory)
|
||||
{
|
||||
//directly relaying to map visualizer event for now, nothing doing special
|
||||
factory.OnTileError += Factory_OnTileError;
|
||||
}
|
||||
|
||||
private void UnregisterEvents(AbstractTileFactory factory)
|
||||
{
|
||||
factory.OnTileError -= Factory_OnTileError;
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
if (Factories != null)
|
||||
{
|
||||
_counter = Factories.Count;
|
||||
for (int i = 0; i < _counter; i++)
|
||||
{
|
||||
if (Factories[i] != null)
|
||||
{
|
||||
UnregisterEvents(Factories[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inform all downstream nodes that we no longer need to process these tiles.
|
||||
// This scriptable object may be re-used, but it's gameobjects are likely
|
||||
// to be destroyed by a scene change, for example.
|
||||
foreach (var tileId in _activeTiles.Keys.ToList())
|
||||
{
|
||||
DisposeTile(tileId);
|
||||
}
|
||||
|
||||
_activeTiles.Clear();
|
||||
_inactiveTiles.Clear();
|
||||
}
|
||||
|
||||
#region Factory event callbacks
|
||||
//factory event callback, not relaying this up for now
|
||||
|
||||
public virtual void TileStateChanged(UnityTile tile)
|
||||
{
|
||||
bool rasterDone = (tile.RasterDataState == TilePropertyState.None ||
|
||||
tile.RasterDataState == TilePropertyState.Loaded ||
|
||||
tile.RasterDataState == TilePropertyState.Error ||
|
||||
tile.RasterDataState == TilePropertyState.Cancelled);
|
||||
|
||||
bool terrainDone = (tile.HeightDataState == TilePropertyState.None ||
|
||||
tile.HeightDataState == TilePropertyState.Loaded ||
|
||||
tile.HeightDataState == TilePropertyState.Error ||
|
||||
tile.HeightDataState == TilePropertyState.Cancelled);
|
||||
bool vectorDone = (tile.VectorDataState == TilePropertyState.None ||
|
||||
tile.VectorDataState == TilePropertyState.Loaded ||
|
||||
tile.VectorDataState == TilePropertyState.Error ||
|
||||
tile.VectorDataState == TilePropertyState.Cancelled);
|
||||
|
||||
if (rasterDone && terrainDone && vectorDone)
|
||||
{
|
||||
tile.TileState = MeshGeneration.Enums.TilePropertyState.Loaded;
|
||||
//tile.gameObject.SetActive(true);
|
||||
|
||||
// Check if all tiles in extent are active tiles
|
||||
if (_map.CurrentExtent.Count == _activeTiles.Count)
|
||||
{
|
||||
bool allDone = true;
|
||||
// Check if all tiles are loaded.
|
||||
foreach (var currentTile in _map.CurrentExtent)
|
||||
{
|
||||
allDone = allDone && (_activeTiles.ContainsKey(currentTile) && _activeTiles[currentTile].TileState == TilePropertyState.Loaded);
|
||||
}
|
||||
|
||||
if (allDone)
|
||||
{
|
||||
State = ModuleState.Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
State = ModuleState.Working;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
State = ModuleState.Working;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Registers requested tiles to the factories
|
||||
/// </summary>
|
||||
/// <param name="tileId"></param>
|
||||
public virtual UnityTile LoadTile(UnwrappedTileId tileId)
|
||||
{
|
||||
UnityTile unityTile = null;
|
||||
|
||||
if (_inactiveTiles.Count > 0)
|
||||
{
|
||||
unityTile = _inactiveTiles.Dequeue();
|
||||
}
|
||||
|
||||
if (unityTile == null)
|
||||
{
|
||||
unityTile = new GameObject().AddComponent<UnityTile>();
|
||||
unityTile.MeshRenderer.material = _map.TileMaterial;
|
||||
unityTile.transform.SetParent(_map.Root, false);
|
||||
}
|
||||
|
||||
unityTile.Initialize(_map, tileId, _map.WorldRelativeScale, _map.AbsoluteZoom, _map.LoadingTexture);
|
||||
PlaceTile(tileId, unityTile, _map);
|
||||
|
||||
// Don't spend resources naming objects, as you shouldn't find objects by name anyway!
|
||||
#if UNITY_EDITOR
|
||||
unityTile.gameObject.name = unityTile.CanonicalTileId.ToString();
|
||||
#endif
|
||||
unityTile.OnHeightDataChanged += TileStateChanged;
|
||||
unityTile.OnRasterDataChanged += TileStateChanged;
|
||||
unityTile.OnVectorDataChanged += TileStateChanged;
|
||||
|
||||
unityTile.TileState = MeshGeneration.Enums.TilePropertyState.Loading;
|
||||
ActiveTiles.Add(tileId, unityTile);
|
||||
|
||||
foreach (var factory in Factories)
|
||||
{
|
||||
factory.Register(unityTile);
|
||||
}
|
||||
|
||||
return unityTile;
|
||||
}
|
||||
|
||||
public virtual void DisposeTile(UnwrappedTileId tileId)
|
||||
{
|
||||
var unityTile = ActiveTiles[tileId];
|
||||
|
||||
foreach (var factory in Factories)
|
||||
{
|
||||
factory.Unregister(unityTile);
|
||||
}
|
||||
|
||||
unityTile.Recycle();
|
||||
ActiveTiles.Remove(tileId);
|
||||
_inactiveTiles.Enqueue(unityTile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repositions active tiles instead of recreating them. Useful for panning the map
|
||||
/// </summary>
|
||||
/// <param name="tileId"></param>
|
||||
public virtual void RepositionTile(UnwrappedTileId tileId)
|
||||
{
|
||||
UnityTile currentTile;
|
||||
if (ActiveTiles.TryGetValue(tileId, out currentTile))
|
||||
{
|
||||
PlaceTile(tileId, currentTile, _map);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void PlaceTile(UnwrappedTileId tileId, UnityTile tile, IMapReadable map);
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// The <c>OnTileError</c> event triggers when there's a <c>Tile</c> error.
|
||||
/// Returns a <see cref="T:Mapbox.Map.TileErrorEventArgs"/> instance as a parameter, for the tile on which error occurred.
|
||||
/// </summary>
|
||||
public event EventHandler<TileErrorEventArgs> OnTileError;
|
||||
private void Factory_OnTileError(object sender, TileErrorEventArgs e)
|
||||
{
|
||||
EventHandler<TileErrorEventArgs> handler = OnTileError;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReregisterAllTiles()
|
||||
{
|
||||
foreach (var activeTile in _activeTiles)
|
||||
{
|
||||
foreach (var abstractTileFactory in Factories)
|
||||
{
|
||||
abstractTileFactory.Register(activeTile.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterAllTiles()
|
||||
{
|
||||
foreach (var activeTile in _activeTiles)
|
||||
{
|
||||
foreach (var abstractTileFactory in Factories)
|
||||
{
|
||||
abstractTileFactory.Unregister(activeTile.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterTilesFrom(AbstractTileFactory factory)
|
||||
{
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.Unregister(tileBundle.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterAndRedrawTilesFromLayer(VectorTileFactory factory, LayerVisualizerBase layerVisualizer)
|
||||
{
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.UnregisterLayer(tileBundle.Value, layerVisualizer);
|
||||
}
|
||||
layerVisualizer.UnbindSubLayerEvents();
|
||||
layerVisualizer.SetProperties(layerVisualizer.SubLayerProperties);
|
||||
layerVisualizer.InitializeStack();
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.RedrawSubLayer(tileBundle.Value, layerVisualizer);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveTilesFromLayer(VectorTileFactory factory, LayerVisualizerBase layerVisualizer)
|
||||
{
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.UnregisterLayer(tileBundle.Value, layerVisualizer);
|
||||
}
|
||||
factory.RemoveVectorLayerVisualizer(layerVisualizer);
|
||||
}
|
||||
|
||||
public void ReregisterTilesTo(VectorTileFactory factory)
|
||||
{
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.Register(tileBundle.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTileForProperty(AbstractTileFactory factory, LayerUpdateArgs updateArgs)
|
||||
{
|
||||
foreach (KeyValuePair<UnwrappedTileId, UnityTile> tileBundle in _activeTiles)
|
||||
{
|
||||
factory.UpdateTileProperty(tileBundle.Value, updateArgs);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCaches()
|
||||
{
|
||||
foreach (var abstractTileFactory in Factories)
|
||||
{
|
||||
abstractTileFactory.Reset();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cefaf3a12c7842d499a032db9077170d
|
||||
timeCreated: 1504617939
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Mapbox.Unity.Map
|
||||
{
|
||||
using System.Collections;
|
||||
using Mapbox.Unity.Location;
|
||||
using UnityEngine;
|
||||
|
||||
public class InitializeMapWithLocationProvider : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
AbstractMap _map;
|
||||
|
||||
ILocationProvider _locationProvider;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Prevent double initialization of the map.
|
||||
_map.InitializeOnStart = false;
|
||||
}
|
||||
|
||||
protected virtual IEnumerator Start()
|
||||
{
|
||||
yield return null;
|
||||
_locationProvider = LocationProviderFactory.Instance.DefaultLocationProvider;
|
||||
_locationProvider.OnLocationUpdated += LocationProvider_OnLocationUpdated; ;
|
||||
}
|
||||
|
||||
void LocationProvider_OnLocationUpdated(Unity.Location.Location location)
|
||||
{
|
||||
_locationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
|
||||
_map.Initialize(location.LatitudeLongitude, _map.AbsoluteZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96f0fa82f89d64bb9a6524c72d538179
|
||||
timeCreated: 1506092731
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces.meta
Normal file
8
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3f7157c1c1f94f4aaac6081e3449f9b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
49
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IMap.cs
Normal file
49
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IMap.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.Interfaces
|
||||
{
|
||||
public interface IMap : IMapReadable, IMapWritable, IUnifiedMap { }
|
||||
|
||||
public interface IMapReadable
|
||||
{
|
||||
Vector2d CenterMercator { get; }
|
||||
float WorldRelativeScale { get; }
|
||||
Vector2d CenterLatitudeLongitude { get; }
|
||||
/// <summary>
|
||||
/// Gets the zoom value of the map.
|
||||
/// This allows for zoom values in between actual zoom level "AbsoluteZoom" requested from the service.
|
||||
/// </summary>
|
||||
float Zoom { get; }
|
||||
/// <summary>
|
||||
/// Gets the zoom value at which the map was intialized.
|
||||
/// </summary>
|
||||
int InitialZoom { get; }
|
||||
/// <summary>
|
||||
/// Gets the zoom value at which the tiles will be requested from the service.
|
||||
/// Use this only for calls which require an integer value of zoom to be passed in.
|
||||
/// </summary>
|
||||
int AbsoluteZoom { get; }
|
||||
Transform Root { get; }
|
||||
float UnityTileSize { get; }
|
||||
Texture2D LoadingTexture { get; }
|
||||
Material TileMaterial { get; }
|
||||
|
||||
HashSet<UnwrappedTileId> CurrentExtent { get; }
|
||||
event Action OnInitialized;
|
||||
event Action OnUpdated;
|
||||
Vector2d WorldToGeoPosition(Vector3 realworldPoint);
|
||||
Vector3 GeoToWorldPosition(Vector2d latitudeLongitude, bool queryHeight = true);
|
||||
}
|
||||
|
||||
public interface IMapWritable
|
||||
{
|
||||
void SetCenterMercator(Vector2d centerMercator);
|
||||
void SetCenterLatitudeLongitude(Vector2d centerLatitudeLongitude);
|
||||
void SetZoom(float zoom);
|
||||
void SetWorldRelativeScale(float scale);
|
||||
}
|
||||
}
|
||||
12
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IMap.cs.meta
Normal file
12
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IMap.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5a989744ad8746e5bc533ee230d00c6
|
||||
timeCreated: 1494990683
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Mapbox.Unity.Map.Interfaces
|
||||
{
|
||||
public interface IMapPlacementStrategy
|
||||
{
|
||||
void SetUpPlacement(AbstractMap map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa6c9ee2f3b546dc9df96694c85e82c5
|
||||
timeCreated: 1538658253
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Mapbox.Unity.Map.Interfaces
|
||||
{
|
||||
public interface IMapScalingStrategy
|
||||
{
|
||||
void SetUpScaling(AbstractMap map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3d0db333c6d474aa152ccac7439e444
|
||||
timeCreated: 1538658226
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map.TileProviders;
|
||||
|
||||
namespace Mapbox.Unity.Map.Interfaces
|
||||
{
|
||||
public interface ITileProvider
|
||||
{
|
||||
event EventHandler<ExtentArgs> ExtentChanged;
|
||||
ITileProviderOptions Options { get; }
|
||||
|
||||
// TODO: add cancel event?
|
||||
// Alternatively, give mapvisualizer an object recycling strategy that can separately determine when to change gameobjects.
|
||||
// This removal would essentially lead to a cancel request and nothing more.
|
||||
|
||||
void Initialize(IMap map);
|
||||
// TODO: Maybe combine both these methods.
|
||||
void SetOptions(ITileProviderOptions options);
|
||||
|
||||
// TODO: add reset/clear method?
|
||||
}
|
||||
|
||||
public interface IUnifiedTileProvider
|
||||
{
|
||||
event Action<UnwrappedTileId> OnTileAdded;
|
||||
event Action<UnwrappedTileId> OnTileRemoved;
|
||||
|
||||
// TODO: add cancel event?
|
||||
// Alternatively, give mapvisualizer an object recycling strategy that can separately determine when to change gameobjects.
|
||||
// This removal would essentially lead to a cancel request and nothing more.
|
||||
|
||||
void Initialize(IUnifiedMap map);
|
||||
|
||||
// TODO: add reset/clear method?
|
||||
}
|
||||
public class TileStateChangedEventArgs : EventArgs
|
||||
{
|
||||
public UnwrappedTileId TileId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21517bafda8f54be39ccf7c230b76f9c
|
||||
timeCreated: 1494606252
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IUnifiedMap.cs
Normal file
11
Assets/Mapbox SDK/Mapbox/Unity/Map/Interfaces/IUnifiedMap.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Mapbox.Utils;
|
||||
|
||||
namespace Mapbox.Unity.Map.Interfaces
|
||||
{
|
||||
public interface IUnifiedMap
|
||||
{
|
||||
//void InitializeMap(MapOptions options);
|
||||
void UpdateMap(Vector2d latLon, float zoom);
|
||||
void ResetMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be115c5fdb26480791b43d27c2bc1bfb
|
||||
timeCreated: 1538657911
|
||||
51
Assets/Mapbox SDK/Mapbox/Unity/Map/MapVisualizer.cs
Normal file
51
Assets/Mapbox SDK/Mapbox/Unity/Map/MapVisualizer.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
|
||||
namespace Mapbox.Unity.Map
|
||||
{
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Map;
|
||||
|
||||
public enum ModuleState
|
||||
{
|
||||
Initialized,
|
||||
Working,
|
||||
Finished
|
||||
}
|
||||
|
||||
public class AssignmentTypeAttribute : PropertyAttribute
|
||||
{
|
||||
public System.Type Type;
|
||||
|
||||
public AssignmentTypeAttribute(System.Type t)
|
||||
{
|
||||
Type = t;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map Visualizer
|
||||
/// Represents a map.Doesn't contain much logic and at the moment, it creates requested tiles and relays them to the factories
|
||||
/// under itself.It has a caching mechanism to reuse tiles and does the tile positioning in unity world.
|
||||
/// Later we'll most likely keep track of map features here as well to allow devs to query for features easier
|
||||
/// (i.e.query all buildings x meters around any restaurant etc).
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Mapbox/MapVisualizer/BasicMapVisualizer")]
|
||||
public class MapVisualizer : AbstractMapVisualizer
|
||||
{
|
||||
protected override void PlaceTile(UnwrappedTileId tileId, UnityTile tile, IMapReadable map)
|
||||
{
|
||||
var rect = tile.Rect;
|
||||
|
||||
// TODO: this is constant for all tiles--cache.
|
||||
var scale = tile.TileScale;
|
||||
var scaleFactor = Mathf.Pow(2, (map.InitialZoom - map.AbsoluteZoom));
|
||||
|
||||
var position = new Vector3(
|
||||
(float)(rect.Center.x - map.CenterMercator.x) * scale * scaleFactor,
|
||||
0,
|
||||
(float)(rect.Center.y - map.CenterMercator.y) * scale * scaleFactor);
|
||||
tile.transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Mapbox SDK/Mapbox/Unity/Map/MapVisualizer.cs.meta
Normal file
12
Assets/Mapbox SDK/Mapbox/Unity/Map/MapVisualizer.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 526c8a90df31d41fe8057a6f85c7a3e4
|
||||
timeCreated: 1494993890
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Mapbox SDK/Mapbox/Unity/Map/Strategies.meta
Normal file
8
Assets/Mapbox SDK/Mapbox/Unity/Map/Strategies.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 817a1846479397d458272568e8bb804f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using Mapbox.Unity.Utilities;
|
||||
|
||||
namespace Mapbox.Unity.Map.Strategies
|
||||
{
|
||||
public class MapPlacementAtLocationCenterStrategy : IMapPlacementStrategy
|
||||
{
|
||||
public void SetUpPlacement(AbstractMap map)
|
||||
{
|
||||
map.SetCenterMercator(Conversions.LatLonToMeters(map.CenterLatitudeLongitude));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d44d0606bd83495bab6d3da0a48ad090
|
||||
timeCreated: 1538658271
|
||||
@@ -0,0 +1,15 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using Mapbox.Unity.Utilities;
|
||||
|
||||
namespace Mapbox.Unity.Map.Strategies
|
||||
{
|
||||
public class MapPlacementAtTileCenterStrategy : IMapPlacementStrategy
|
||||
{
|
||||
public void SetUpPlacement(AbstractMap map)
|
||||
{
|
||||
var referenceTileRect = Conversions.TileBounds(TileCover.CoordinateToTileId(map.CenterLatitudeLongitude, map.AbsoluteZoom));
|
||||
map.SetCenterMercator(referenceTileRect.Center);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 559d97f03cf14bf79a007b09ad4f1336
|
||||
timeCreated: 1538658263
|
||||
@@ -0,0 +1,15 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using Mapbox.Unity.Utilities;
|
||||
|
||||
namespace Mapbox.Unity.Map.Strategies
|
||||
{
|
||||
public class MapScalingAtUnityScaleStrategy : IMapScalingStrategy
|
||||
{
|
||||
public void SetUpScaling(AbstractMap map)
|
||||
{
|
||||
var referenceTileRect = Conversions.TileBounds(TileCover.CoordinateToTileId(map.CenterLatitudeLongitude, map.AbsoluteZoom));
|
||||
map.SetWorldRelativeScale((float)(map.Options.scalingOptions.unityTileSize / referenceTileRect.Size.x));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f52911bb8a44f60a4ef4feb3602d386
|
||||
timeCreated: 1538658244
|
||||
@@ -0,0 +1,14 @@
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.Strategies
|
||||
{
|
||||
public class MapScalingAtWorldScaleStrategy : IMapScalingStrategy
|
||||
{
|
||||
public void SetUpScaling(AbstractMap map)
|
||||
{
|
||||
var scaleFactor = Mathf.Pow(2, (map.AbsoluteZoom - map.InitialZoom));
|
||||
map.SetWorldRelativeScale(scaleFactor * Mathf.Cos(Mathf.Deg2Rad * (float)map.CenterLatitudeLongitude.x));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc8da5d9c56144fc8758276cc931710e
|
||||
timeCreated: 1538658236
|
||||
8
Assets/Mapbox SDK/Mapbox/Unity/Map/TileProviders.meta
Normal file
8
Assets/Mapbox SDK/Mapbox/Unity/Map/TileProviders.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59af73b59e6beff4abd67db34649e6e1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
public class ExtentArgs : EventArgs
|
||||
{
|
||||
//TODO: Override GetHashCode for UnwrappedTileId
|
||||
public HashSet<UnwrappedTileId> activeTiles;
|
||||
}
|
||||
|
||||
public abstract class AbstractTileProvider : MonoBehaviour, ITileProvider
|
||||
{
|
||||
public event EventHandler<ExtentArgs> ExtentChanged;
|
||||
|
||||
protected IMap _map;
|
||||
protected ExtentArgs _currentExtent = new ExtentArgs();
|
||||
|
||||
protected ITileProviderOptions _options;
|
||||
public ITileProviderOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialize(IMap map)
|
||||
{
|
||||
_map = map;
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
public virtual void OnExtentChanged()
|
||||
{
|
||||
ExtentChanged(this, _currentExtent);
|
||||
}
|
||||
|
||||
public abstract void OnInitialized();
|
||||
public abstract void UpdateTileExtent();
|
||||
|
||||
public abstract bool Cleanup(UnwrappedTileId tile);
|
||||
|
||||
public virtual void SetOptions(ITileProviderOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7386ebbea7d44bb29c2107b2c909409
|
||||
timeCreated: 1494606252
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Utils;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
public class GlobeTileProvider : AbstractTileProvider
|
||||
{
|
||||
public override void OnInitialized()
|
||||
{
|
||||
_currentExtent.activeTiles = new HashSet<UnwrappedTileId>();
|
||||
}
|
||||
|
||||
public override void UpdateTileExtent()
|
||||
{
|
||||
// HACK: don't allow too many tiles to be requested.
|
||||
if (_map.AbsoluteZoom > 5)
|
||||
{
|
||||
throw new System.Exception("Too many tiles! Use a lower zoom level!");
|
||||
}
|
||||
|
||||
var tileCover = TileCover.Get(Vector2dBounds.World(), _map.AbsoluteZoom);
|
||||
foreach (var tile in tileCover)
|
||||
{
|
||||
_currentExtent.activeTiles.Add(new UnwrappedTileId(tile.Z, tile.X, tile.Y));
|
||||
}
|
||||
OnExtentChanged();
|
||||
}
|
||||
public override bool Cleanup(UnwrappedTileId tile)
|
||||
{
|
||||
return (!_currentExtent.activeTiles.Contains(tile));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a718f313c2f574a4aad42d7b52867205
|
||||
timeCreated: 1500047799
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map.Interfaces;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using Mapbox.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
//TODO : obsolete.
|
||||
[CreateAssetMenu(menuName = "Mapbox/MapVisualizer/QuadTreeMapVisualizer")]
|
||||
public class QuadTreeMapVisualizer : AbstractMapVisualizer
|
||||
{
|
||||
protected override void PlaceTile(UnwrappedTileId tileId, UnityTile tile, IMapReadable map)
|
||||
{
|
||||
//get the tile covering the center (Unity 0,0,0) of current extent
|
||||
UnwrappedTileId centerTile = TileCover.CoordinateToTileId(map.CenterLatitudeLongitude, map.AbsoluteZoom);
|
||||
//get center WebMerc corrdinates of tile covering the center (Unity 0,0,0)
|
||||
Vector2d centerTileCenter = Conversions.TileIdToCenterWebMercator(centerTile.X, centerTile.Y, map.AbsoluteZoom);
|
||||
//calculate distance between WebMerc center coordinates of center tile and WebMerc coordinates exactly at center
|
||||
Vector2d shift = map.CenterMercator - centerTileCenter;
|
||||
var unityTileSize = map.UnityTileSize;
|
||||
// get factor at equator to avoid shifting errors at higher latitudes
|
||||
float factor = Conversions.GetTileScaleInMeters(0f, map.AbsoluteZoom) * 256.0f / unityTileSize;
|
||||
var scaleFactor = Mathf.Pow(2, (map.InitialZoom - map.AbsoluteZoom));
|
||||
|
||||
//position the tile relative to the center tile of the current viewport using the tile id
|
||||
//multiply by tile size Unity units (unityTileScale)
|
||||
//shift by distance of current viewport center to center of center tile
|
||||
float shiftX = (float)shift.x / factor;
|
||||
float shiftY = (float)shift.y / factor;
|
||||
Vector3 position = new Vector3(
|
||||
((tileId.X - centerTile.X) * unityTileSize - shiftX) * scaleFactor
|
||||
, 0
|
||||
, ((centerTile.Y - tileId.Y) * unityTileSize - shiftY) * scaleFactor);
|
||||
tile.transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dfd965733118434481fedf30fa380c1
|
||||
timeCreated: 1508892338
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using Mapbox.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
public class QuadTreeTileProvider : AbstractTileProvider
|
||||
{
|
||||
private Plane _groundPlane;
|
||||
private bool _shouldUpdate;
|
||||
private CameraBoundsTileProviderOptions _cbtpOptions;
|
||||
|
||||
//private List<UnwrappedTileId> _toRemove;
|
||||
//private HashSet<UnwrappedTileId> _tilesToRequest;
|
||||
private Vector2dBounds _viewPortWebMercBounds;
|
||||
|
||||
#region Tile decision and raycasting fields
|
||||
private HashSet<UnwrappedTileId> _tiles;
|
||||
private HashSet<CanonicalTileId> _canonicalTiles;
|
||||
|
||||
private Ray _ray00;
|
||||
private Ray _ray01;
|
||||
private Ray _ray10;
|
||||
private Ray _ray11;
|
||||
private Vector3[] _hitPnt = new Vector3[4];
|
||||
private bool _isFirstLoad;
|
||||
#endregion
|
||||
|
||||
public override void OnInitialized()
|
||||
{
|
||||
_tiles = new HashSet<UnwrappedTileId>();
|
||||
_canonicalTiles = new HashSet<CanonicalTileId>();
|
||||
_cbtpOptions = (CameraBoundsTileProviderOptions)_options;
|
||||
|
||||
if (_cbtpOptions.camera == null)
|
||||
{
|
||||
_cbtpOptions.camera = Camera.main;
|
||||
}
|
||||
_cbtpOptions.camera.transform.hasChanged = false;
|
||||
_groundPlane = new Plane(Vector3.up, 0);
|
||||
_shouldUpdate = true;
|
||||
_currentExtent.activeTiles = new HashSet<UnwrappedTileId>();
|
||||
}
|
||||
|
||||
public override void UpdateTileExtent()
|
||||
{
|
||||
if (!_shouldUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//update viewport in case it was changed by switching zoom level
|
||||
_viewPortWebMercBounds = getcurrentViewPortWebMerc();
|
||||
_currentExtent.activeTiles = GetWithWebMerc(_viewPortWebMercBounds, _map.AbsoluteZoom);
|
||||
|
||||
OnExtentChanged();
|
||||
}
|
||||
|
||||
public HashSet<UnwrappedTileId> GetWithWebMerc(Vector2dBounds bounds, int zoom)
|
||||
{
|
||||
_tiles.Clear();
|
||||
_canonicalTiles.Clear();
|
||||
|
||||
if (bounds.IsEmpty()) { return _tiles; }
|
||||
|
||||
//stay within WebMerc bounds
|
||||
Vector2d swWebMerc = new Vector2d(Math.Max(bounds.SouthWest.x, -Utils.Constants.WebMercMax), Math.Max(bounds.SouthWest.y, -Utils.Constants.WebMercMax));
|
||||
Vector2d neWebMerc = new Vector2d(Math.Min(bounds.NorthEast.x, Utils.Constants.WebMercMax), Math.Min(bounds.NorthEast.y, Utils.Constants.WebMercMax));
|
||||
|
||||
//UnityEngine.Debug.LogFormat("swWebMerc:{0}/{1} neWebMerc:{2}/{3}", swWebMerc.x, swWebMerc.y, neWebMerc.x, neWebMerc.y);
|
||||
|
||||
UnwrappedTileId swTile = WebMercatorToTileId(swWebMerc, zoom);
|
||||
UnwrappedTileId neTile = WebMercatorToTileId(neWebMerc, zoom);
|
||||
|
||||
//UnityEngine.Debug.LogFormat("swTile:{0} neTile:{1}", swTile, neTile);
|
||||
|
||||
for (int x = swTile.X; x <= neTile.X; x++)
|
||||
{
|
||||
for (int y = neTile.Y; y <= swTile.Y; y++)
|
||||
{
|
||||
UnwrappedTileId uwtid = new UnwrappedTileId(zoom, x, y);
|
||||
//hack: currently too many tiles are created at lower zoom levels
|
||||
//investigate formulas, this worked before
|
||||
if (!_canonicalTiles.Contains(uwtid.Canonical))
|
||||
{
|
||||
//Debug.LogFormat("TileCover.GetWithWebMerc: {0}/{1}/{2}", zoom, x, y);
|
||||
_tiles.Add(uwtid);
|
||||
_canonicalTiles.Add(uwtid.Canonical);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _tiles;
|
||||
}
|
||||
|
||||
public UnwrappedTileId WebMercatorToTileId(Vector2d webMerc, int zoom)
|
||||
{
|
||||
var tileCount = Math.Pow(2, zoom);
|
||||
|
||||
var dblX = webMerc.x / Utils.Constants.WebMercMax;
|
||||
var dblY = webMerc.y / Utils.Constants.WebMercMax;
|
||||
|
||||
int x = (int)Math.Floor((1 + dblX) / 2 * tileCount);
|
||||
int y = (int)Math.Floor((1 - dblY) / 2 * tileCount);
|
||||
return new UnwrappedTileId(zoom, x, y);
|
||||
}
|
||||
private Vector2dBounds getcurrentViewPortWebMerc(bool useGroundPlane = true)
|
||||
{
|
||||
if (useGroundPlane)
|
||||
{
|
||||
// rays from camera to groundplane: lower left and upper right
|
||||
_ray00 = _cbtpOptions.camera.ViewportPointToRay(new Vector3(0, 0));
|
||||
_ray01 = _cbtpOptions.camera.ViewportPointToRay(new Vector3(0, 1));
|
||||
_ray10 = _cbtpOptions.camera.ViewportPointToRay(new Vector3(1, 0));
|
||||
_ray11 = _cbtpOptions.camera.ViewportPointToRay(new Vector3(1, 1));
|
||||
_hitPnt[0] = getGroundPlaneHitPoint(_ray00);
|
||||
_hitPnt[1] = getGroundPlaneHitPoint(_ray01);
|
||||
_hitPnt[2] = getGroundPlaneHitPoint(_ray10);
|
||||
_hitPnt[3] = getGroundPlaneHitPoint(_ray11);
|
||||
}
|
||||
|
||||
// Find min max bounding box.
|
||||
// TODO : Find a better way of doing this.
|
||||
float minX = float.MaxValue;
|
||||
float minZ = float.MaxValue;
|
||||
float maxX = float.MinValue;
|
||||
float maxZ = float.MinValue;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (_hitPnt[i] == Vector3.zero)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (minX > _hitPnt[i].x)
|
||||
{
|
||||
minX = _hitPnt[i].x;
|
||||
}
|
||||
|
||||
if (minZ > _hitPnt[i].z)
|
||||
{
|
||||
minZ = _hitPnt[i].z;
|
||||
}
|
||||
|
||||
if (maxX < _hitPnt[i].x)
|
||||
{
|
||||
maxX = _hitPnt[i].x;
|
||||
}
|
||||
|
||||
if (maxZ < _hitPnt[i].z)
|
||||
{
|
||||
maxZ = _hitPnt[i].z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 hitPntLL = new Vector3(minX, 0, minZ);
|
||||
Vector3 hitPntUR = new Vector3(maxX, 0, maxZ);
|
||||
|
||||
//Debug.Log(hitPntLL + " - " + hitPntUR);
|
||||
|
||||
var llLatLong = _map.WorldToGeoPosition(hitPntLL);
|
||||
var urLatLong = _map.WorldToGeoPosition(hitPntUR);
|
||||
|
||||
Vector2dBounds tileBounds = new Vector2dBounds(Conversions.LatLonToMeters(llLatLong), Conversions.LatLonToMeters(urLatLong));
|
||||
|
||||
// Bounds debugging.
|
||||
#if UNITY_EDITOR
|
||||
Debug.DrawLine(_cbtpOptions.camera.transform.position, hitPntLL, Color.blue);
|
||||
Debug.DrawLine(_cbtpOptions.camera.transform.position, hitPntUR, Color.red);
|
||||
#endif
|
||||
return tileBounds;
|
||||
}
|
||||
private Vector3 getGroundPlaneHitPoint(Ray ray)
|
||||
{
|
||||
float distance;
|
||||
if (!_groundPlane.Raycast(ray, out distance)) { return Vector3.zero; }
|
||||
return ray.GetPoint(distance);
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (_cbtpOptions != null && _cbtpOptions.camera != null && _cbtpOptions.camera.transform.hasChanged)
|
||||
{
|
||||
UpdateTileExtent();
|
||||
_cbtpOptions.camera.transform.hasChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Cleanup(UnwrappedTileId tile)
|
||||
{
|
||||
return (!_currentExtent.activeTiles.Contains(tile));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 756a01a914208439d8d2fc8dcd68b229
|
||||
timeCreated: 1508278498
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
public class RangeAroundTransformTileProvider : AbstractTileProvider
|
||||
{
|
||||
private RangeAroundTransformTileProviderOptions _rangeTileProviderOptions;
|
||||
|
||||
private bool _initialized = false;
|
||||
private UnwrappedTileId _currentTile;
|
||||
private bool _waitingForTargetTransform = false;
|
||||
|
||||
public override void OnInitialized()
|
||||
{
|
||||
_rangeTileProviderOptions = (RangeAroundTransformTileProviderOptions)Options;
|
||||
|
||||
if (_rangeTileProviderOptions.targetTransform == null)
|
||||
{
|
||||
Debug.LogError("TransformTileProvider: No location marker transform specified.");
|
||||
_waitingForTargetTransform = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
//_toRemove = new List<UnwrappedTileId>(((_rangeTileProviderOptions.visibleBuffer * 2) + 1) * ((_rangeTileProviderOptions.visibleBuffer * 2) + 1));
|
||||
_currentExtent.activeTiles = new HashSet<UnwrappedTileId>();
|
||||
_map.OnInitialized += UpdateTileExtent;
|
||||
_map.OnUpdated += UpdateTileExtent;
|
||||
}
|
||||
|
||||
public override void UpdateTileExtent()
|
||||
{
|
||||
if (!_initialized) return;
|
||||
|
||||
_currentExtent.activeTiles.Clear();
|
||||
//_toRemove.Clear();
|
||||
_currentTile = TileCover.CoordinateToTileId(_map.WorldToGeoPosition(_rangeTileProviderOptions.targetTransform.localPosition), _map.AbsoluteZoom);
|
||||
|
||||
for (int x = _currentTile.X - _rangeTileProviderOptions.visibleBuffer; x <= (_currentTile.X + _rangeTileProviderOptions.visibleBuffer); x++)
|
||||
{
|
||||
for (int y = _currentTile.Y - _rangeTileProviderOptions.visibleBuffer; y <= (_currentTile.Y + _rangeTileProviderOptions.visibleBuffer); y++)
|
||||
{
|
||||
_currentExtent.activeTiles.Add(new UnwrappedTileId(_map.AbsoluteZoom, x, y));
|
||||
}
|
||||
}
|
||||
OnExtentChanged();
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (_waitingForTargetTransform && !_initialized)
|
||||
{
|
||||
if (_rangeTileProviderOptions.targetTransform != null)
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rangeTileProviderOptions != null && _rangeTileProviderOptions.targetTransform != null && _rangeTileProviderOptions.targetTransform.hasChanged)
|
||||
{
|
||||
UpdateTileExtent();
|
||||
_rangeTileProviderOptions.targetTransform.hasChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Cleanup(UnwrappedTileId tile)
|
||||
{
|
||||
bool dispose = false;
|
||||
dispose = tile.X > _currentTile.X + _rangeTileProviderOptions.disposeBuffer || tile.X < _currentTile.X - _rangeTileProviderOptions.disposeBuffer;
|
||||
dispose = dispose || tile.Y > _currentTile.Y + _rangeTileProviderOptions.disposeBuffer || tile.Y < _currentTile.Y - _rangeTileProviderOptions.disposeBuffer;
|
||||
|
||||
|
||||
return (dispose);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15eed3c0528a3498dae4ff8f7b8ae77f
|
||||
timeCreated: 1505936421
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using Mapbox.Map;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
public class RangeTileProvider : AbstractTileProvider
|
||||
{
|
||||
private RangeTileProviderOptions _rangeTileProviderOptions;
|
||||
private bool _initialized = false;
|
||||
|
||||
//private List<UnwrappedTileId> _toRemove;
|
||||
//private HashSet<UnwrappedTileId> _tilesToRequest;
|
||||
|
||||
public override void OnInitialized()
|
||||
{
|
||||
if (Options != null)
|
||||
{
|
||||
_rangeTileProviderOptions = (RangeTileProviderOptions)Options;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rangeTileProviderOptions = new RangeTileProviderOptions();
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
//_toRemove = new List<UnwrappedTileId>((_rangeTileProviderOptions.east + _rangeTileProviderOptions.west) * (_rangeTileProviderOptions.north + _rangeTileProviderOptions.south));
|
||||
_currentExtent.activeTiles = new HashSet<UnwrappedTileId>();
|
||||
}
|
||||
|
||||
public override void UpdateTileExtent()
|
||||
{
|
||||
if (!_initialized || Options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_currentExtent.activeTiles.Clear();
|
||||
//_toRemove.Clear();
|
||||
var centerTile = TileCover.CoordinateToTileId(_map.CenterLatitudeLongitude, _map.AbsoluteZoom);
|
||||
_currentExtent.activeTiles.Add(new UnwrappedTileId(_map.AbsoluteZoom, centerTile.X, centerTile.Y));
|
||||
|
||||
for (int x = (centerTile.X - _rangeTileProviderOptions.west); x <= (centerTile.X + _rangeTileProviderOptions.east); x++)
|
||||
{
|
||||
for (int y = (centerTile.Y - _rangeTileProviderOptions.north); y <= (centerTile.Y + _rangeTileProviderOptions.south); y++)
|
||||
{
|
||||
_currentExtent.activeTiles.Add(new UnwrappedTileId(_map.AbsoluteZoom, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
OnExtentChanged();
|
||||
}
|
||||
public override bool Cleanup(UnwrappedTileId tile)
|
||||
{
|
||||
return (!_currentExtent.activeTiles.Contains(tile));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d7ff8ed3b76a4ee5a451d64a5393e3f
|
||||
timeCreated: 1494606252
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mapbox.Map;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Mapbox.Unity.Map.TileProviders
|
||||
{
|
||||
/// <summary>
|
||||
/// Monobehavior Script to handle TileErrors.
|
||||
/// There's an OnTileError event on AbstractMapVisualizer, AbstractTileFactory and UnityTile classes that one can subscribe to to listen to tile errors
|
||||
/// </summary>
|
||||
public class TileErrorHandler : MonoBehaviour
|
||||
{
|
||||
|
||||
[SerializeField]
|
||||
private AbstractMap _mapInstance;
|
||||
public TileErrorEvent OnTileError;
|
||||
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_mapInstance == null)
|
||||
{
|
||||
_mapInstance = GetComponent<AbstractMap>();
|
||||
}
|
||||
|
||||
_mapInstance.OnInitialized += MapInstance_OnInitialized;
|
||||
}
|
||||
|
||||
|
||||
private void MapInstance_OnInitialized()
|
||||
{
|
||||
_mapInstance.OnInitialized -= MapInstance_OnInitialized;
|
||||
_mapInstance.MapVisualizer.OnTileError += _OnTileErrorHandler;
|
||||
}
|
||||
|
||||
|
||||
private void _OnTileErrorHandler(object sender, TileErrorEventArgs e)
|
||||
{
|
||||
// check if request has been aborted: show warning not error
|
||||
if (e.Exceptions.Count > 0)
|
||||
{
|
||||
// 1. aborted is always the first exception
|
||||
// additional exceptions are always caused by the request being aborted
|
||||
// show all of them as warnings
|
||||
// 2. 'Unable to write data' is another exception associated
|
||||
// with aborted requests: request finshed successfully but
|
||||
// was aborted during filling of local buffer, also show as warning
|
||||
if (
|
||||
e.Exceptions[0].Message.Contains("Request aborted")
|
||||
|| e.Exceptions[0].Message.Equals("Unable to write data")
|
||||
)
|
||||
{
|
||||
Debug.LogWarning(printMessage(e.Exceptions, e));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(printMessage(e.Exceptions, e));
|
||||
}
|
||||
}
|
||||
|
||||
if (OnTileError != null)
|
||||
{
|
||||
OnTileError.Invoke(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string printMessage(List<Exception> exceptions, TileErrorEventArgs e)
|
||||
{
|
||||
return string.Format(
|
||||
"{0} Exception(s) caused on the tile. Tile ID:{1} Tile Type:{4}{2}{3}"
|
||||
, exceptions.Count
|
||||
, e.TileId
|
||||
, Environment.NewLine
|
||||
, string.Join(Environment.NewLine, exceptions.Select(ex => ex.Message).ToArray())
|
||||
, e.TileType
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
_mapInstance.MapVisualizer.OnTileError -= _OnTileErrorHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class TileErrorEvent : UnityEvent<TileErrorEventArgs> { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76a256726e16d4966a3f30b97a17e1d5
|
||||
timeCreated: 1509146285
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user