[TASK] Initial commit with basic product setup

This commit is contained in:
2019-08-18 13:50:14 +02:00
commit 01a66a8e1f
2548 changed files with 167528 additions and 0 deletions

View File

@@ -0,0 +1,388 @@
using System.Linq;
namespace Mapbox.Unity.MeshGeneration.Interfaces
{
using Mapbox.Unity.Map;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.MeshGeneration.Filters;
using Mapbox.Unity.MeshGeneration.Modifiers;
using Mapbox.Unity.Utilities;
using Mapbox.VectorTile;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class LocationPrefabsLayerVisualizer : VectorLayerVisualizer
{
private int maxDensity = 30; //This value is same as the density's max range value in PrefabItemOptions
private PrefabModifier _prefabModifier;
public override bool Active
{
get
{
return SubLayerProperties.coreOptions.isActive;
}
}
public override void SetProperties(VectorSubLayerProperties properties)
{
var item = properties as PrefabItemOptions;
SubLayerProperties = item;
//Active = item.isActive;
_performanceOptions = item.performanceOptions;
item.filterOptions.filters.Clear();
if (item.spawnPrefabOptions.prefab == null)
{
//item.spawnPrefabOptions.prefab = GameObject.CreatePrimitive(PrimitiveType.Cube);
item.spawnPrefabOptions.prefab = Resources.Load<GameObject>("MapboxPin");
Debug.LogError("No prefab found. Please assign a prefab to spawn it on the map");
}
//These are fixed properties
item.coreOptions.geometryType = item.primitiveType;
item.extrusionOptions = new GeometryExtrusionOptions
{
extrusionType = item.extrusionType
};
item.coreOptions.combineMeshes = item.combineMeshes;
item.moveFeaturePositionTo = item._movePrefabFeaturePositionTo;
string layerName = "";
if (item.layerNameFromFindByTypeDictionary.TryGetValue(item.findByType, out layerName))
{
item.coreOptions.layerName = layerName;
base.Key = layerName;
}
//These properties are dependent on user choices
if (item.findByType != LocationPrefabFindBy.AddressOrLatLon)
{
if (item.findByType == LocationPrefabFindBy.MapboxCategory)
{
SetCategoryFilterOptions(item);
}
if (item.findByType == LocationPrefabFindBy.POIName)
{
SetNameFilters(item);
}
SetDensityFilters(item);
}
switch (item.coreOptions.geometryType)
{
case VectorPrimitiveType.Point:
#if ENABLE_WINMD_SUPPORT
if (typeof(PrefabItemOptions).GetTypeInfo().IsAssignableFrom(item.GetType().GetTypeInfo())) //to check that the instance is of type PrefabItemOptions
#else
if (typeof(PrefabItemOptions).IsAssignableFrom(item.GetType())) //to check that the instance is of type PrefabItemOptions
#endif
{
PrefabItemOptions itemProperties = (PrefabItemOptions)item;
if (_defaultStack == null)
{
_defaultStack = ScriptableObject.CreateInstance<ModifierStack>();
}
(_defaultStack as ModifierStack).moveFeaturePositionTo = item.moveFeaturePositionTo;
if (itemProperties.snapToTerrain == true)
{
AddOrCreateMeshModifier<SnapTerrainModifier>();
}
if (_defaultStack.GoModifiers == null)
{
_defaultStack.GoModifiers = new List<GameObjectModifier>();
}
if (item.findByType == LocationPrefabFindBy.MapboxCategory)
{
if (_prefabModifier != null)
{
_prefabModifier.ClearCaches();
}
_defaultStack.GoModifiers.Clear();
}
if ((item.findByType == LocationPrefabFindBy.MapboxCategory && item.categories == LocationPrefabCategories.None))
{
itemProperties.spawnPrefabOptions.PropertyHasChanged += UpdatePois;
}
else
{
_prefabModifier = AddOrCreateGameObjectModifier<PrefabModifier>();
_prefabModifier.SetProperties(itemProperties.spawnPrefabOptions);
_prefabModifier.ModifierHasChanged += UpdatePois;
}
}
break;
default:
break;
}
item.coreOptions.PropertyHasChanged += UpdatePois;
(SubLayerProperties as PrefabItemOptions).PropertyHasChanged += UpdatePois;
}
private void UpdatePois(object sender, System.EventArgs eventArgs)
{
VectorLayerUpdateArgs layerUpdateArgs = eventArgs as VectorLayerUpdateArgs;
layerUpdateArgs.visualizer = this;
layerUpdateArgs.effectsVectorLayer = true;
if (layerUpdateArgs.modifier != null)
{
layerUpdateArgs.property.PropertyHasChanged -= layerUpdateArgs.modifier.UpdateModifier;
layerUpdateArgs.modifier.ModifierHasChanged -= UpdatePois;
}
else if (layerUpdateArgs.property != null)
{
layerUpdateArgs.property.PropertyHasChanged -= UpdatePois;
}
foreach (var modifier in _defaultStack.MeshModifiers)
{
modifier.UnbindProperties();
modifier.ModifierHasChanged -= UpdatePois;
}
foreach (var modifier in _defaultStack.GoModifiers)
{
modifier.UnbindProperties();
modifier.ModifierHasChanged -= UpdatePois;
}
SubLayerProperties.coreOptions.PropertyHasChanged -= UpdatePois;
(SubLayerProperties as PrefabItemOptions).PropertyHasChanged -= UpdatePois;
OnUpdateLayerVisualizer(layerUpdateArgs);
}
/// <summary>
/// Sets the category filter options.
/// </summary>
/// <param name="item">Item.</param>
private void SetCategoryFilterOptions(PrefabItemOptions item)
{
string propertyName = "";
item.categoryPropertyFromFindByTypeDictionary.TryGetValue(item.findByType, out propertyName);
string concatenatedString = "";
if (item.findByType == LocationPrefabFindBy.MapboxCategory)
{
List<LocationPrefabCategories> categoriesList = GetSelectedCategoriesList(item.categories);
if (categoriesList == null || categoriesList.Count == 0)
{
return;
}
else
{
List<string> stringsList = new List<string>();
foreach (LocationPrefabCategories category in categoriesList)
{
stringsList = LocationPrefabCategoryOptions.GetMakiListFromCategory(category);
if (string.IsNullOrEmpty(concatenatedString))
{
concatenatedString = string.Join(",", stringsList.ToArray());
}
else
{
concatenatedString += "," + string.Join(",", stringsList.ToArray());
}
}
LayerFilter filter = new LayerFilter(LayerFilterOperationType.Contains)
{
Key = propertyName,
PropertyValue = concatenatedString
};
AddFilterToItem(item, filter);
}
}
}
/// <summary>
/// Sets the density filters.
/// </summary>
/// <param name="item">Item.</param>
private void SetDensityFilters(PrefabItemOptions item)
{
if (item.density >= maxDensity) // decided that the max value for density
{
return;
}
string propertyName = "";
item.densityPropertyFromFindByTypeDictionary.TryGetValue(item.findByType, out propertyName);
if (item.findByType == LocationPrefabFindBy.MapboxCategory || item.findByType == LocationPrefabFindBy.POIName)
{
LayerFilter filter = new LayerFilter(LayerFilterOperationType.IsLess)
{
Key = propertyName,
Min = item.density
};
AddFilterToItem(item, filter);
}
}
/// <summary>
/// Sets the name filters.
/// </summary>
/// <param name="item">Item.</param>
private void SetNameFilters(PrefabItemOptions item)
{
if (string.IsNullOrEmpty(item.nameString))
{
return;
}
string propertyName = "";
item.namePropertyFromFindByTypeDictionary.TryGetValue(item.findByType, out propertyName);
if (item.findByType == LocationPrefabFindBy.POIName)
{
LayerFilter filter = new LayerFilter(LayerFilterOperationType.Contains)
{
Key = propertyName,
PropertyValue = item.nameString
};
AddFilterToItem(item, filter);
}
}
/// <summary>
/// Merges the filters with item filters.
/// </summary>
/// <param name="item">Item.</param>
private void AddFilterToItem(PrefabItemOptions item, LayerFilter filter)
{
if (item.filterOptions == null)
{
item.filterOptions = new VectorFilterOptions();
}
item.filterOptions.filters.Add(filter);
item.filterOptions.combinerType = item._combinerType;
}
/// <summary>
/// Gets the list of categories selected through the dropdown
/// </summary>
/// <returns>The selected categories list.</returns>
/// <param name="selectedCategories">Cat.</param>
private List<LocationPrefabCategories> GetSelectedCategoriesList(LocationPrefabCategories selectedCategories)
{
List<LocationPrefabCategories> containingCategories = new List<LocationPrefabCategories>();
Array eligibleValues = Enum.GetValues(typeof(LocationPrefabCategories));
if (selectedCategories == LocationPrefabCategories.None)
{
return containingCategories;
}
//For any other categories other than None and Any
foreach (object value in eligibleValues)
{
LocationPrefabCategories category = (LocationPrefabCategories)value;
if (category == LocationPrefabCategories.AnyCategory || category == LocationPrefabCategories.None)
{
continue;
}
if ((category & selectedCategories) != 0) //to check if category is contained in cat
{
containingCategories.Add(category);
}
}
return containingCategories;
}
public override void Create(VectorTileLayer layer, UnityTile tile, Action<UnityTile, LayerVisualizerBase> callback)
{
//for layers using specific locations, ignore VectorTileLayer and
//pass coordinates to the modifierstack using BuildFeatureFromLatLon.
if ((SubLayerProperties as PrefabItemOptions).findByType == LocationPrefabFindBy.AddressOrLatLon)
{
BuildFeatureFromLatLon(layer, tile);
if (callback != null)
{
callback(tile, this);
}
}
else
{
var item = (SubLayerProperties as PrefabItemOptions);
bool isCategoryNone = (item.findByType == LocationPrefabFindBy.MapboxCategory && item.categories == LocationPrefabCategories.None);
if (!isCategoryNone)
{
base.Create(layer, tile, callback);
}
}
}
/// <summary>
/// Creates a vector feature from lat lon and builds that feature using the modifier stack.
/// </summary>
/// <param name="layer">Layer.</param>
/// <param name="tile">Tile.</param>
private void BuildFeatureFromLatLon(VectorTileLayer layer, UnityTile tile)
{
if (tile.TileState != Enums.TilePropertyState.Unregistered)
{
string[] coordinates = (SubLayerProperties as PrefabItemOptions).coordinates;
for (int i = 0; i < coordinates.Length; i++)
{
if (string.IsNullOrEmpty(coordinates[i]))
{
return;
}
//check if the coordinate is in the tile
Utils.Vector2d coordinate = Conversions.StringToLatLon(coordinates[i]);
Mapbox.Map.UnwrappedTileId coordinateTileId = Conversions.LatitudeLongitudeToTileId(
coordinate.x, coordinate.y, tile.InitialZoom);
if (coordinateTileId.Canonical.Equals(tile.CanonicalTileId))
{
if (String.IsNullOrEmpty(coordinates[i]))
{
return;
}
//create new vector feature
VectorFeatureUnity feature = new VectorFeatureUnity();
feature.Properties = new Dictionary<string, object>();
feature.Points = new List<List<Vector3>>();
//create submesh for feature
List<Vector3> latLonPoint = new List<Vector3>();
//add point to submesh, and submesh to feature
latLonPoint.Add(Conversions.LatitudeLongitudeToUnityTilePosition(coordinate, tile.CurrentZoom, tile.TileScale, layer.Extent).ToVector3xz());
feature.Points.Add(latLonPoint);
//pass valid feature.Data to modifiers
//this data has no relation to the features being drawn
feature.Data = layer.GetFeature(0);
//pass the feature to the mod stack
base.Build(feature, tile, tile.gameObject);
}
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b250e20966143455d807eddf832c7362
timeCreated: 1524037447
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,766 @@
using Mapbox.VectorTile.Geometry;
namespace Mapbox.Unity.MeshGeneration.Interfaces
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.MeshGeneration.Modifiers;
using Mapbox.VectorTile;
using UnityEngine;
using Mapbox.Unity.Map;
using Mapbox.Unity.Utilities;
using Mapbox.Unity.MeshGeneration.Filters;
using Mapbox.Map;
public class VectorLayerVisualizerProperties
{
public FeatureProcessingStage featureProcessingStage;
public bool buildingsWithUniqueIds = false;
public VectorTileLayer vectorTileLayer;
public ILayerFeatureFilterComparer[] layerFeatureFilters;
public ILayerFeatureFilterComparer layerFeatureFilterCombiner;
}
public class VectorLayerVisualizer : LayerVisualizerBase
{
VectorSubLayerProperties _layerProperties;
public override VectorSubLayerProperties SubLayerProperties
{
get
{
return _layerProperties;
}
set
{
_layerProperties = value;
}
}
public ModifierStackBase DefaultModifierStack
{
get
{
return _defaultStack;
}
set
{
_defaultStack = value;
}
}
//public event System.EventHandler VectorHasChanged;
protected LayerPerformanceOptions _performanceOptions;
protected Dictionary<UnityTile, List<int>> _activeCoroutines;
int _entityInCurrentCoroutine = 0;
protected ModifierStackBase _defaultStack;
private HashSet<ulong> _activeIds;
private Dictionary<UnityTile, List<ulong>> _idPool; //necessary to keep _activeIds list up to date when unloading tiles
private string _key;
public override string Key
{
get { return _layerProperties.coreOptions.layerName; }
set { _layerProperties.coreOptions.layerName = value; }
}
public T FindMeshModifier<T>() where T : MeshModifier
{
MeshModifier mod = _defaultStack.MeshModifiers.FirstOrDefault(x => x.GetType() == typeof(T));
return (T)mod;
}
public T FindGameObjectModifier<T>() where T : GameObjectModifier
{
GameObjectModifier mod = _defaultStack.GoModifiers.FirstOrDefault(x => x.GetType() == typeof(T));
return (T)mod;
}
public T AddOrCreateMeshModifier<T>() where T : MeshModifier
{
MeshModifier mod = _defaultStack.MeshModifiers.FirstOrDefault(x => x.GetType() == typeof(T));
if (mod == null)
{
mod = (MeshModifier)CreateInstance(typeof(T));
_defaultStack.MeshModifiers.Add(mod);
}
return (T)mod;
}
public T AddOrCreateGameObjectModifier<T>() where T : GameObjectModifier
{
GameObjectModifier mod = _defaultStack.GoModifiers.FirstOrDefault(x => x.GetType() == typeof(T));
if (mod == null)
{
mod = (GameObjectModifier)CreateInstance(typeof(T));
_defaultStack.GoModifiers.Add(mod);
}
return (T)mod;
}
private void UpdateVector(object sender, System.EventArgs eventArgs)
{
VectorLayerUpdateArgs layerUpdateArgs = eventArgs as VectorLayerUpdateArgs;
layerUpdateArgs.visualizer = this;
layerUpdateArgs.effectsVectorLayer = true;
if (layerUpdateArgs.modifier != null)
{
layerUpdateArgs.property.PropertyHasChanged -= layerUpdateArgs.modifier.UpdateModifier;
layerUpdateArgs.modifier.ModifierHasChanged -= UpdateVector;
}
else if (layerUpdateArgs.property != null)
{
layerUpdateArgs.property.PropertyHasChanged -= UpdateVector;
}
UnbindSubLayerEvents();
OnUpdateLayerVisualizer(layerUpdateArgs);
}
public override void UnbindSubLayerEvents()
{
foreach (var modifier in _defaultStack.MeshModifiers)
{
modifier.UnbindProperties();
modifier.ModifierHasChanged -= UpdateVector;
}
foreach (var modifier in _defaultStack.GoModifiers)
{
modifier.UnbindProperties();
modifier.ModifierHasChanged -= UpdateVector;
}
_layerProperties.extrusionOptions.PropertyHasChanged -= UpdateVector;
_layerProperties.coreOptions.PropertyHasChanged -= UpdateVector;
_layerProperties.filterOptions.PropertyHasChanged -= UpdateVector;
_layerProperties.filterOptions.UnRegisterFilters();
_layerProperties.materialOptions.PropertyHasChanged -= UpdateVector;
_layerProperties.PropertyHasChanged -= UpdateVector;
}
public override void SetProperties(VectorSubLayerProperties properties)
{
if (_layerProperties == null && properties != null)
{
_layerProperties = properties;
if (_performanceOptions == null && properties.performanceOptions != null)
{
_performanceOptions = properties.performanceOptions;
}
}
if (_layerProperties.coreOptions.combineMeshes)
{
if (_defaultStack == null || !(_defaultStack is MergedModifierStack))
{
_defaultStack = ScriptableObject.CreateInstance<MergedModifierStack>();
}
else
{
// HACK - to clean out the Modifiers.
// Will this trigger GC that we could avoid ??
_defaultStack.MeshModifiers.Clear();
_defaultStack.GoModifiers.Clear();
}
}
else
{
if (_defaultStack == null || !(_defaultStack is ModifierStack))
{
_defaultStack = ScriptableObject.CreateInstance<ModifierStack>();
((ModifierStack)_defaultStack).moveFeaturePositionTo = _layerProperties.moveFeaturePositionTo;
}
else
{
// HACK - to clean out the Modifiers.
// Will this trigger GC that we could avoid ??
_defaultStack.MeshModifiers.Clear();
_defaultStack.GoModifiers.Clear();
}
}
//Add any additional modifiers that were added.
if (_defaultStack.MeshModifiers == null)
{
_defaultStack.MeshModifiers = new List<MeshModifier>();
}
if (_defaultStack.GoModifiers == null)
{
_defaultStack.GoModifiers = new List<GameObjectModifier>();
}
// Setup material options.
_layerProperties.materialOptions.SetDefaultMaterialOptions();
switch (_layerProperties.coreOptions.geometryType)
{
case VectorPrimitiveType.Point:
case VectorPrimitiveType.Custom:
{
// Let the user add anything that they want
if (_layerProperties.coreOptions.snapToTerrain == true)
{
//defaultMeshModifierStack.Add(CreateInstance<SnapTerrainModifier>());
AddOrCreateMeshModifier<SnapTerrainModifier>();
}
break;
}
case VectorPrimitiveType.Line:
{
if (_layerProperties.coreOptions.snapToTerrain == true)
{
AddOrCreateMeshModifier<SnapTerrainModifier>();
}
var lineMeshMod = AddOrCreateMeshModifier<LineMeshModifier>();
lineMeshMod.SetProperties(_layerProperties.lineGeometryOptions);
lineMeshMod.ModifierHasChanged += UpdateVector;
if (_layerProperties.extrusionOptions.extrusionType != Map.ExtrusionType.None)
{
var heightMod = AddOrCreateMeshModifier<HeightModifier>();
heightMod.SetProperties(_layerProperties.extrusionOptions);
heightMod.ModifierHasChanged += UpdateVector;
}
else
{
_layerProperties.extrusionOptions.PropertyHasChanged += UpdateVector;
}
//collider modifier options
var lineColliderMod = AddOrCreateGameObjectModifier<ColliderModifier>();
lineColliderMod.SetProperties(_layerProperties.colliderOptions);
lineColliderMod.ModifierHasChanged += UpdateVector;
var lineStyleMod = AddOrCreateGameObjectModifier<MaterialModifier>();
lineStyleMod.SetProperties(_layerProperties.materialOptions);
lineStyleMod.ModifierHasChanged += UpdateVector;
break;
}
case VectorPrimitiveType.Polygon:
{
if (_layerProperties.coreOptions.snapToTerrain == true)
{
AddOrCreateMeshModifier<SnapTerrainModifier>();
}
AddOrCreateMeshModifier<PolygonMeshModifier>();
UVModifierOptions uvModOptions = new UVModifierOptions();
uvModOptions.texturingType = (_layerProperties.materialOptions.style == StyleTypes.Custom) ? _layerProperties.materialOptions.customStyleOptions.texturingType : _layerProperties.materialOptions.texturingType;
uvModOptions.atlasInfo = (_layerProperties.materialOptions.style == StyleTypes.Custom) ? _layerProperties.materialOptions.customStyleOptions.atlasInfo : _layerProperties.materialOptions.atlasInfo;
uvModOptions.style = _layerProperties.materialOptions.style;
var uvMod = AddOrCreateMeshModifier<UvModifier>();
uvMod.SetProperties(uvModOptions);
if (_layerProperties.extrusionOptions.extrusionType != Map.ExtrusionType.None)
{
//replace materialOptions with styleOptions
bool useTextureSideWallModifier =
(_layerProperties.materialOptions.style == StyleTypes.Custom) ?
(_layerProperties.materialOptions.customStyleOptions.texturingType == UvMapType.Atlas || _layerProperties.materialOptions.customStyleOptions.texturingType == UvMapType.AtlasWithColorPalette)
: (_layerProperties.materialOptions.texturingType == UvMapType.Atlas || _layerProperties.materialOptions.texturingType == UvMapType.AtlasWithColorPalette);
if (useTextureSideWallModifier)
{
var atlasMod = AddOrCreateMeshModifier<TextureSideWallModifier>();
GeometryExtrusionWithAtlasOptions atlasOptions = new GeometryExtrusionWithAtlasOptions(_layerProperties.extrusionOptions, uvModOptions);
atlasMod.SetProperties(atlasOptions);
_layerProperties.extrusionOptions.PropertyHasChanged += UpdateVector;
}
else
{
var heightMod = AddOrCreateMeshModifier<HeightModifier>();
heightMod.SetProperties(_layerProperties.extrusionOptions);
heightMod.ModifierHasChanged += UpdateVector;
}
}
else
{
_layerProperties.extrusionOptions.PropertyHasChanged += UpdateVector;
}
//collider modifier options
var polyColliderMod = AddOrCreateGameObjectModifier<ColliderModifier>();
polyColliderMod.SetProperties(_layerProperties.colliderOptions);
polyColliderMod.ModifierHasChanged += UpdateVector;
var styleMod = AddOrCreateGameObjectModifier<MaterialModifier>();
styleMod.SetProperties(_layerProperties.materialOptions);
styleMod.ModifierHasChanged += UpdateVector;
bool isCustomStyle = (_layerProperties.materialOptions.style == StyleTypes.Custom);
if ((isCustomStyle) ? (_layerProperties.materialOptions.customStyleOptions.texturingType == UvMapType.AtlasWithColorPalette)
: (_layerProperties.materialOptions.texturingType == UvMapType.AtlasWithColorPalette))
{
var colorPaletteMod = AddOrCreateGameObjectModifier<MapboxStylesColorModifier>();
colorPaletteMod.m_scriptablePalette = (isCustomStyle) ? _layerProperties.materialOptions.customStyleOptions.colorPalette : _layerProperties.materialOptions.colorPalette;
_layerProperties.materialOptions.PropertyHasChanged += UpdateVector;
//TODO: Add SetProperties Method to MapboxStylesColorModifier
}
break;
}
default:
break;
}
_layerProperties.coreOptions.PropertyHasChanged += UpdateVector;
_layerProperties.filterOptions.PropertyHasChanged += UpdateVector;
_layerProperties.filterOptions.RegisterFilters();
if (_layerProperties.MeshModifiers != null)
{
_defaultStack.MeshModifiers.AddRange(_layerProperties.MeshModifiers);
}
if (_layerProperties.GoModifiers != null)
{
_defaultStack.GoModifiers.AddRange(_layerProperties.GoModifiers);
}
//Adding filters from the types dropdown
//if ((MapboxSpecialLayerParameters.LayerNameTypeProperty.ContainsKey(properties.coreOptions.layerName)) && !string.IsNullOrEmpty(properties.selectedTypes))
//{
// LayerFilter filter = new LayerFilter(LayerFilterOperationType.Contains);
// filter.Key = MapboxSpecialLayerParameters.LayerNameTypeProperty[properties.coreOptions.layerName];
// filter.PropertyValue = properties.selectedTypes;
// //if (properties.coreOptions.layerName == properties.roadLayer)
// //{
// // filter.Key = properties.roadLayer_TypeProperty;
// // filter.PropertyValue = properties.selectedTypes;
// //}
// //else if (properties.coreOptions.layerName == "landuse")
// //{
// // filter.Key = properties.landuseLayer_TypeProperty;
// // filter.PropertyValue = properties.selectedTypes;
// //}
// properties.filterOptions.filters.Add(filter);
//}
_layerProperties.PropertyHasChanged += UpdateVector;
}
/// <summary>
/// Add the replacement criteria to any mesh modifiers implementing IReplaceable
/// </summary>
/// <param name="criteria">Criteria.</param>
protected void SetReplacementCriteria(IReplacementCriteria criteria)
{
foreach (var meshMod in _defaultStack.MeshModifiers)
{
if (meshMod is IReplaceable)
{
((IReplaceable)meshMod).Criteria.Add(criteria);
}
}
}
#region Private Helper Methods
/// <summary>
/// Convenience function to add feature to Tile object pool.
/// </summary>
/// <param name="feature">Feature to be added to the pool.</param>
/// <param name="tile">Tile currently being processed.</param>
private void AddFeatureToTileObjectPool(VectorFeatureUnity feature, UnityTile tile)
{
_activeIds.Add(feature.Data.Id);
if (!_idPool.ContainsKey(tile))
{
_idPool.Add(tile, new List<ulong>());
}
else
{
_idPool[tile].Add(feature.Data.Id);
}
}
/// <summary>
/// Apply filters to the layer and check if the current feature is eleigible for rendering.
/// </summary>
/// <returns><c>true</c>, if feature eligible after filtering was applied, <c>false</c> otherwise.</returns>
/// <param name="feature">Feature.</param>
private bool IsFeatureEligibleAfterFiltering(VectorFeatureUnity feature, UnityTile tile, VectorLayerVisualizerProperties layerProperties)
{
if (layerProperties.layerFeatureFilters.Count() == 0)
{
return true;
}
else
{
// build features only if the filter returns true.
if (layerProperties.layerFeatureFilterCombiner.Try(feature))
{
return true;
}
}
return false;
}
/// <summary>
/// Function to fetch feature in vector tile at the index specified.
/// </summary>
/// <returns>The feature in tile at the index requested.</returns>
/// <param name="tile">Unity Tile containing the feature.</param>
/// <param name="index">Index of the vector feature being requested.</param>
private VectorFeatureUnity GetFeatureinTileAtIndex(int index, UnityTile tile, VectorLayerVisualizerProperties layerProperties)
{
return new VectorFeatureUnity(layerProperties.vectorTileLayer.GetFeature(index),
tile,
layerProperties.vectorTileLayer.Extent,
layerProperties.buildingsWithUniqueIds);
}
/// <summary>
/// Function to check if the feature is already in the active Id pool, features already in active Id pool should be skipped from processing.
/// </summary>
/// <returns><c>true</c>, if feature is already in activeId pool or if the layer has buildingsWithUniqueId flag set to <see langword="true"/>, <c>false</c> otherwise.</returns>
/// <param name="featureId">Feature identifier.</param>
private bool ShouldSkipProcessingFeatureWithId(ulong featureId, UnityTile tile, VectorLayerVisualizerProperties layerProperties)
{
return (layerProperties.buildingsWithUniqueIds && _activeIds.Contains(featureId));
}
/// <summary>
/// Gets a value indicating whether this entity per coroutine bucket is full.
/// </summary>
/// <value><c>true</c> if coroutine bucket is full; otherwise, <c>false</c>.</value>
private bool IsCoroutineBucketFull
{
get
{
return (_performanceOptions != null && _performanceOptions.isEnabled && _entityInCurrentCoroutine >= _performanceOptions.entityPerCoroutine);
}
}
public override bool Active
{
get
{
return _layerProperties.coreOptions.isActive;
}
}
#endregion
public override void Initialize()
{
base.Initialize();
_entityInCurrentCoroutine = 0;
_activeCoroutines = new Dictionary<UnityTile, List<int>>();
_activeIds = new HashSet<ulong>();
_idPool = new Dictionary<UnityTile, List<ulong>>();
if (_defaultStack != null)
{
_defaultStack.Initialize();
}
}
public override void InitializeStack()
{
if (_defaultStack != null)
{
_defaultStack.Initialize();
}
}
public override void Create(VectorTileLayer layer, UnityTile tile, Action<UnityTile, LayerVisualizerBase> callback)
{
if (!_activeCoroutines.ContainsKey(tile))
_activeCoroutines.Add(tile, new List<int>());
_activeCoroutines[tile].Add(Runnable.Run(ProcessLayer(layer, tile, tile.UnwrappedTileId, callback)));
}
protected IEnumerator ProcessLayer(VectorTileLayer layer, UnityTile tile, UnwrappedTileId tileId, Action<UnityTile, LayerVisualizerBase> callback = null)
{
//HACK to prevent request finishing on same frame which breaks modules started/finished events
yield return null;
if (tile == null)
{
yield break;
}
VectorLayerVisualizerProperties tempLayerProperties = new VectorLayerVisualizerProperties();
tempLayerProperties.vectorTileLayer = layer;
tempLayerProperties.featureProcessingStage = FeatureProcessingStage.PreProcess;
//Get all filters in the array.
tempLayerProperties.layerFeatureFilters = _layerProperties.filterOptions.filters.Select(m => m.GetFilterComparer()).ToArray();
// Pass them to the combiner
tempLayerProperties.layerFeatureFilterCombiner = new Filters.LayerFilterComparer();
switch (_layerProperties.filterOptions.combinerType)
{
case Filters.LayerFilterCombinerOperationType.Any:
tempLayerProperties.layerFeatureFilterCombiner = Filters.LayerFilterComparer.AnyOf(tempLayerProperties.layerFeatureFilters);
break;
case Filters.LayerFilterCombinerOperationType.All:
tempLayerProperties.layerFeatureFilterCombiner = Filters.LayerFilterComparer.AllOf(tempLayerProperties.layerFeatureFilters);
break;
case Filters.LayerFilterCombinerOperationType.None:
tempLayerProperties.layerFeatureFilterCombiner = Filters.LayerFilterComparer.NoneOf(tempLayerProperties.layerFeatureFilters);
break;
default:
break;
}
tempLayerProperties.buildingsWithUniqueIds = (_layerProperties.honorBuildingIdSetting) && _layerProperties.buildingsWithUniqueIds;
////find any replacement criteria and assign them
foreach (var goModifier in _defaultStack.GoModifiers)
{
if (goModifier is IReplacementCriteria && goModifier.Active)
{
SetReplacementCriteria((IReplacementCriteria)goModifier);
}
}
#region PreProcess & Process.
var featureCount = (tempLayerProperties.vectorTileLayer == null) ? 0 : tempLayerProperties.vectorTileLayer.FeatureCount();
do
{
for (int i = 0; i < featureCount; i++)
{
//checking if tile is recycled and changed
if (tile.UnwrappedTileId != tileId || !_activeCoroutines.ContainsKey(tile) || tile.TileState == Enums.TilePropertyState.Unregistered)
{
yield break;
}
ProcessFeature(i, tile, tempLayerProperties, layer.Extent);
if (IsCoroutineBucketFull)
{
//Reset bucket..
_entityInCurrentCoroutine = 0;
yield return null;
}
}
// move processing to next stage.
tempLayerProperties.featureProcessingStage++;
} while (tempLayerProperties.featureProcessingStage == FeatureProcessingStage.PreProcess
|| tempLayerProperties.featureProcessingStage == FeatureProcessingStage.Process);
#endregion
#region PostProcess
// TODO : Clean this up to follow the same pattern.
var mergedStack = _defaultStack as MergedModifierStack;
if (mergedStack != null && tile != null)
{
mergedStack.End(tile, tile.gameObject, layer.Name);
}
#endregion
if (callback != null)
callback(tile, this);
}
private bool ProcessFeature(int index, UnityTile tile, VectorLayerVisualizerProperties layerProperties, float layerExtent)
{
var fe = layerProperties.vectorTileLayer.GetFeature(index);
List<List<Point2d<float>>> geom;
if (layerProperties.buildingsWithUniqueIds == true) //ids from building dataset is big ulongs
{
geom = fe.Geometry<float>(); //and we're not clipping by passing no parameters
if (geom[0][0].X < 0 || geom[0][0].X > layerExtent || geom[0][0].Y < 0 || geom[0][0].Y > layerExtent)
{
return false;
}
}
else //streets ids, will require clipping
{
geom = fe.Geometry<float>(0); //passing zero means clip at tile edge
}
var feature = new VectorFeatureUnity(layerProperties.vectorTileLayer.GetFeature(index),
geom,
tile,
layerProperties.vectorTileLayer.Extent,
layerProperties.buildingsWithUniqueIds);
if (IsFeatureEligibleAfterFiltering(feature, tile, layerProperties))
{
if (tile != null && tile.gameObject != null && tile.VectorDataState != Enums.TilePropertyState.Cancelled)
{
switch (layerProperties.featureProcessingStage)
{
case FeatureProcessingStage.PreProcess:
//pre process features.
PreProcessFeatures(feature, tile, tile.gameObject);
break;
case FeatureProcessingStage.Process:
//skip existing features, only works on tilesets with unique ids
if (ShouldSkipProcessingFeatureWithId(feature.Data.Id, tile, layerProperties))
{
return false;
}
//feature not skipped. Add to pool only if features are in preprocess stage.
AddFeatureToTileObjectPool(feature, tile);
Build(feature, tile, tile.gameObject);
break;
case FeatureProcessingStage.PostProcess:
break;
default:
break;
}
_entityInCurrentCoroutine++;
}
}
return true;
}
/// <summary>
/// Preprocess features, finds the relevant modifier stack and passes the feature to that stack
/// </summary>
/// <param name="feature"></param>
/// <param name="tile"></param>
/// <param name="parent"></param>
private bool IsFeatureValid(VectorFeatureUnity feature)
{
if (feature.Properties.ContainsKey("extrude") && !bool.Parse(feature.Properties["extrude"].ToString()))
return false;
if (feature.Points.Count < 1)
return false;
return true;
}
protected void PreProcessFeatures(VectorFeatureUnity feature, UnityTile tile, GameObject parent)
{
////find any replacement criteria and assign them
foreach (var goModifier in _defaultStack.GoModifiers)
{
if (goModifier is IReplacementCriteria && goModifier.Active)
{
goModifier.FeaturePreProcess(feature);
}
}
}
protected void Build(VectorFeatureUnity feature, UnityTile tile, GameObject parent)
{
if (feature.Properties.ContainsKey("extrude") && !Convert.ToBoolean(feature.Properties["extrude"]))
return;
if (feature.Points.Count < 1)
return;
//this will be improved in next version and will probably be replaced by filters
var styleSelectorKey = _layerProperties.coreOptions.sublayerName;
var meshData = new MeshData();
meshData.TileRect = tile.Rect;
//and finally, running the modifier stack on the feature
var processed = false;
if (!processed)
{
if (_defaultStack != null)
{
_defaultStack.Execute(tile, feature, meshData, parent, styleSelectorKey);
}
}
}
protected void PostProcessFeatures(VectorFeatureUnity feature, UnityTile tile, GameObject parent)
{
//var mergedStack = _defaultStack as MergedModifierStack;
//if (mergedStack != null && tile != null)
//{
// mergedStack.End(tile, tile.gameObject, _vectorFeaturesPerTile[tile].vectorTileLayer.Name);
//}
}
private string FindSelectorKey(VectorFeatureUnity feature)
{
// TODO: FIX THIS!!
//if (string.IsNullOrEmpty(_classificationKey))
//{
// if (feature.Properties.ContainsKey("type"))
// {
// return feature.Properties["type"].ToString().ToLowerInvariant();
// }
// else if (feature.Properties.ContainsKey("class"))
// {
// return feature.Properties["class"].ToString().ToLowerInvariant();
// }
//}
//else
//TODO: Come back to this.
//var size = _layerProperties.coreOptions.propertyValuePairs.Count;
//for (int i = 0; i < size; i++)
//{
// var key = _layerProperties.coreOptions.propertyValuePairs[i].featureKey;
// if (feature.Properties.ContainsKey(key))
// {
// if (feature.Properties.ContainsKey(key))
// {
// return feature.Properties[key].ToString().ToLowerInvariant();
// }
// }
//}
return Key;
}
/// <summary>
/// Handle tile destruction event and propagate it to modifier stacks
/// </summary>
/// <param name="tile">Destroyed tile object</param>
public override void OnUnregisterTile(UnityTile tile)
{
base.OnUnregisterTile(tile);
if (_activeCoroutines.ContainsKey(tile))
{
foreach (var cor in _activeCoroutines[tile])
{
Runnable.Stop(cor);
}
}
_activeCoroutines.Remove(tile);
if (_defaultStack != null)
{
_defaultStack.UnregisterTile(tile);
}
//removing ids from activeIds list so they'll be recreated next time tile loads (necessary when you're unloading/loading tiles)
if (_idPool.ContainsKey(tile))
{
foreach (var item in _idPool[tile])
{
_activeIds.Remove(item);
}
_idPool[tile].Clear();
}
//UnbindSubLayerEvents();
}
public override void ClearCaches()
{
_idPool.Clear();
_defaultStack.ClearCaches();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 120e43a7012622e49aca0c9217acd1f9
timeCreated: 1520376260
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: