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.
387 lines
11 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|