You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
mapbox-sdk/Unity/MeshGeneration/LayerVisualizers/LocationPrefabsLayerVisuali...

387 lines
11 KiB

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;
_performanceOptions = item.performanceOptions;
item.filterOptions.filters.Clear();
//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;
}
if (item.spawnPrefabOptions.prefab == null)
{
item.spawnPrefabOptions.prefab = Resources.Load<GameObject>("MapboxPin");
Debug.LogWarning("No prefab assigned for POI Layer - " + layerName + " , using default prefab! You may want to assign a custom prefab.");
}
//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.Clear();
}
_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.CurrentZoom);
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);
}
}
}
}
}
}