Update SupportingScripts to 0.9.0.
This commit is contained in:
Родитель
41a59fff86
Коммит
c388c149b2
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "Microsoft.Maps.Unity.Editor",
|
||||
"references": [
|
||||
"Microsoft.Maps.Unity.SupportingScripts"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"Microsoft.Maps.Unity.dll"
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 71c89d9c39160f144b624374c46f00f4
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cbcc9be67fcbf9246b07a75484c20866
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7b2e1c711acbd2041bfbf3767abb70fb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -30,6 +30,8 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
var clusterMapPin = (ClusterMapPin)target;
|
||||
var latLon = clusterMapPin.MercatorCoordinate.ToLatLon();
|
||||
EditorGUILayout.TextField("Location", latLon.LatitudeInDegrees + ", " + latLon.LongitudeInDegrees);
|
||||
EditorGUILayout.IntField("Size", clusterMapPin.Size);
|
||||
EditorGUILayout.IntField("Level Of Detail", clusterMapPin.LevelOfDetail);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Microsoft.Maps.Unity
|
|||
/// <param name="targetType">The type to use the drawer for.</param>
|
||||
public CustomTileLayerDrawer(Type targetType)
|
||||
{
|
||||
this.TargetType = targetType;
|
||||
TargetType = targetType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(MapDataCache))]
|
||||
internal class MapDataCacheEditor : Editor
|
||||
{
|
||||
private SerializedProperty _percentUtilizationProperty;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_percentUtilizationProperty = serializedObject.FindProperty("_percentUtilization");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
var mapDataCache = (MapDataCache)target;
|
||||
mapDataCache.MaxCacheSizeInBytes =
|
||||
1024 *
|
||||
1024 *
|
||||
EditorGUILayout.LongField(
|
||||
new GUIContent("Max Cache Size (MB)"),
|
||||
mapDataCache.MaxCacheSizeInBytes / 1024 / 1024);
|
||||
|
||||
EditorGUILayout.PropertyField(_percentUtilizationProperty);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 225701b175b10a74b8abdf19673869db
|
||||
guid: 6c847bcdaad445644b3613d339b0d95a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -21,15 +21,15 @@ namespace Microsoft.Maps.Unity
|
|||
private SerializedProperty _isLayerSynchronizedProperty;
|
||||
|
||||
private Vector3 _mouseDownMapPinPlanePositionInMapLocalSpace;
|
||||
private Vector2D _mouseDownMapPinPositionInMercatorSpace;
|
||||
private MercatorCoordinate _mouseDownMapPinPositionInMercatorSpace;
|
||||
private bool _isHovered;
|
||||
private bool _isDragging;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_locationProperty = serializedObject.FindProperty("_location");
|
||||
_altitude = serializedObject.FindProperty("Altitude");
|
||||
_altitudeReferenceProperty = serializedObject.FindProperty("AltitudeReference");
|
||||
_altitude = serializedObject.FindProperty("_altitude");
|
||||
_altitudeReferenceProperty = serializedObject.FindProperty("_altitudeReference");
|
||||
_useRealworldScaleProperty = serializedObject.FindProperty("UseRealWorldScale");
|
||||
_scaleCurveProperty = serializedObject.FindProperty("ScaleCurve");
|
||||
_isLayerSynchronizedProperty = serializedObject.FindProperty("IsLayerSynchronized");
|
||||
|
@ -70,9 +70,8 @@ namespace Microsoft.Maps.Unity
|
|||
var transform = mapPin.transform;
|
||||
|
||||
Tools.hidden = true;
|
||||
|
||||
|
||||
var controlId = GUIUtility.GetControlID("MapPinEditorHandle".GetHashCode(), FocusType.Passive);
|
||||
var screenPosition = Handles.matrix.MultiplyPoint(transform.position);
|
||||
var size = 0.025f;
|
||||
|
||||
switch (Event.current.GetTypeForControl(controlId))
|
||||
|
@ -105,7 +104,7 @@ namespace Microsoft.Maps.Unity
|
|||
{
|
||||
// Respond to a press on this handle. Drag starts automatically.
|
||||
_mouseDownMapPinPlanePositionInMapLocalSpace = mapRenderer.transform.worldToLocalMatrix * ray.GetPoint(enter);
|
||||
_mouseDownMapPinPositionInMercatorSpace = mapPin.Location.ToMercatorPosition();
|
||||
_mouseDownMapPinPositionInMercatorSpace = mapPin.Location.ToMercatorCoordinate();
|
||||
_isDragging = true;
|
||||
GUIUtility.hotControl = controlId;
|
||||
Event.current.Use();
|
||||
|
@ -131,8 +130,8 @@ namespace Microsoft.Maps.Unity
|
|||
{
|
||||
Vector3 updatedHitPointInLocalSpace = mapRenderer.transform.worldToLocalMatrix * ray.GetPoint(enter);
|
||||
var newDeltaInLocalSpace = updatedHitPointInLocalSpace - _mouseDownMapPinPlanePositionInMapLocalSpace;
|
||||
var newDeltaInMercator = new Vector2D(newDeltaInLocalSpace.x, newDeltaInLocalSpace.z) / Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var newLocation = LatLon.FromMercatorPosition(_mouseDownMapPinPositionInMercatorSpace + newDeltaInMercator);
|
||||
var newDeltaInMercator = new MercatorCoordinate(newDeltaInLocalSpace.x, newDeltaInLocalSpace.z) / Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var newLocation = (_mouseDownMapPinPositionInMercatorSpace + newDeltaInMercator).ToLatLon();
|
||||
|
||||
Undo.RecordObject(target, "Changed Location");
|
||||
mapPin.Location = newLocation;
|
||||
|
|
|
@ -13,22 +13,21 @@ namespace Microsoft.Maps.Unity
|
|||
[CanEditMultipleObjects]
|
||||
internal class MapRendererEditor : Editor
|
||||
{
|
||||
private SerializedProperty _bingMapsKeyProperty;
|
||||
private SerializedProperty _showMapDataInEditorProperty;
|
||||
private static bool _showMapLocationOptions = true;
|
||||
private static bool _showLocationOptions = true;
|
||||
private SerializedProperty _centerProperty;
|
||||
private SerializedProperty _zoomLevelProperty;
|
||||
private SerializedProperty _minZoomLevelProperty;
|
||||
private SerializedProperty _maxZoomLevelProperty;
|
||||
private SerializedProperty _mapTerrainType;
|
||||
private SerializedProperty _mapShapeProperty;
|
||||
private static bool _showMapSizingOptions = true;
|
||||
private SerializedProperty _mapEdgeColorProperty;
|
||||
private SerializedProperty _mapEdgeColorFadeDistanceProperty;
|
||||
|
||||
private static bool _showLayoutOptions = true;
|
||||
private SerializedProperty _localMapDimensionProperty;
|
||||
private SerializedProperty _localMapRadiusProperty;
|
||||
private SerializedProperty _localMapHeightProperty;
|
||||
private static bool _terrainOptions = true;
|
||||
private SerializedProperty _localMapBaseHeightProperty;
|
||||
private SerializedProperty _mapColliderTypeProperty;
|
||||
|
||||
private static bool _showRenderingOptions = true;
|
||||
private SerializedProperty _elevationScaleProperty;
|
||||
private SerializedProperty _castShadowsProperty;
|
||||
private SerializedProperty _receiveShadowsProperty;
|
||||
|
@ -36,28 +35,29 @@ namespace Microsoft.Maps.Unity
|
|||
private SerializedProperty _useCustomTerrainMaterialProperty;
|
||||
private SerializedProperty _customTerrainMaterialProperty;
|
||||
private SerializedProperty _isClippingVolumeWallEnabledProperty;
|
||||
private SerializedProperty _mapEdgeColorProperty;
|
||||
private SerializedProperty _mapEdgeColorFadeDistanceProperty;
|
||||
private SerializedProperty _useCustomClippingVolumeMaterialProperty;
|
||||
private SerializedProperty _customClippingVolumeMaterialProperty;
|
||||
private SerializedProperty _clippingVolumeDistanceTextureResolution;
|
||||
private SerializedProperty _labelPrefabProperty;
|
||||
|
||||
private static bool _showQualityOptions = true;
|
||||
private SerializedProperty _detailOffsetProperty;
|
||||
private SerializedProperty _maxCacheSizeInBytesProperty;
|
||||
private SerializedProperty _mapColliderTypeProperty;
|
||||
private static bool _showTileLayers = true;
|
||||
|
||||
private static bool _showTileLayerOptions = true;
|
||||
private SerializedProperty _textureTileLayersProperty;
|
||||
private SerializedProperty _elevationTileLayersProperty;
|
||||
private SerializedProperty _hideTileLayerComponentsProperty;
|
||||
|
||||
private static bool _showLocalizationOptions = true;
|
||||
private SerializedProperty _languageOverrideProperty;
|
||||
private GUIStyle _baseStyle = null;
|
||||
private GUIStyle _hyperlinkStyle = null;
|
||||
private GUIStyle _errorIconStyle = null;
|
||||
private GUIContent _errorIcon = null;
|
||||
private SerializedProperty _languageChangedProperty;
|
||||
|
||||
private SerializedProperty _mapSessionProperty;
|
||||
|
||||
private GUIStyle _foldoutTitleStyle = null;
|
||||
private GUIStyle _boxStyle = null;
|
||||
private Texture2D _bannerWhite = null;
|
||||
private Texture2D _bannerBlack = null;
|
||||
|
||||
private readonly GUIContent[] _layerOptions =
|
||||
new GUIContent[]
|
||||
{
|
||||
|
@ -65,12 +65,14 @@ namespace Microsoft.Maps.Unity
|
|||
new GUIContent("Elevated", "The map terrain consists only of elevation data. No high resolution 3D models are used."),
|
||||
new GUIContent("Flat", "Both elevation and high resolution 3D models are disabled. The map will be flat.")
|
||||
};
|
||||
|
||||
private readonly GUIContent[] _shapeOptions =
|
||||
new GUIContent[]
|
||||
{
|
||||
new GUIContent("Block", "Default shape. The map is rendered on a rectangular block."),
|
||||
new GUIContent("Cylinder", "Map is rendered on a cylinder."),
|
||||
};
|
||||
|
||||
private readonly GUIContent[] _clippingVolumeDistanceTextureResolutionOptions =
|
||||
new GUIContent[]
|
||||
{
|
||||
|
@ -78,6 +80,7 @@ namespace Microsoft.Maps.Unity
|
|||
new GUIContent("Medium", "Medium quality texture size."),
|
||||
new GUIContent("High", "High quality texture size. Uses more memory.")
|
||||
};
|
||||
|
||||
private readonly GUIContent[] _colliderOptions =
|
||||
new GUIContent[]
|
||||
{
|
||||
|
@ -85,26 +88,22 @@ namespace Microsoft.Maps.Unity
|
|||
new GUIContent("Base Only", "Collider covering the base of the map."),
|
||||
new GUIContent("Full Extents", "Collider covering the full extents of the map."),
|
||||
};
|
||||
|
||||
private readonly GUILayoutOption[] _minMaxLabelsLayoutOptions =
|
||||
new GUILayoutOption[]
|
||||
{
|
||||
GUILayout.MaxWidth(52.0f)
|
||||
};
|
||||
|
||||
private readonly Tuple<UnityEngine.Object, UnityEngine.Object>[] _terrainMaterials =
|
||||
new Tuple<UnityEngine.Object, UnityEngine.Object>[3];
|
||||
|
||||
private static int ControlIdHint = "MapRendererEditor".GetHashCode();
|
||||
private readonly static int ControlIdHint = "MapRendererEditor".GetHashCode();
|
||||
|
||||
private bool _isDragging = false;
|
||||
private Vector3 _startingHitPointInWorldSpace;
|
||||
private Vector2D _startingCenterInMercatorSpace;
|
||||
private MercatorCoordinate _startingCenterInMercator;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_centerProperty = serializedObject.FindProperty("_center");
|
||||
_bingMapsKeyProperty = serializedObject.FindProperty("_bingMapsKey");
|
||||
_showMapDataInEditorProperty = serializedObject.FindProperty("_showMapDataInEditor");
|
||||
_zoomLevelProperty = serializedObject.FindProperty("_zoomLevel");
|
||||
_minZoomLevelProperty = serializedObject.FindProperty("_minimumZoomLevel");
|
||||
_maxZoomLevelProperty = serializedObject.FindProperty("_maximumZoomLevel");
|
||||
|
@ -112,7 +111,7 @@ namespace Microsoft.Maps.Unity
|
|||
_mapShapeProperty = serializedObject.FindProperty("_mapShape");
|
||||
_localMapDimensionProperty = serializedObject.FindProperty("LocalMapDimension");
|
||||
_localMapRadiusProperty = serializedObject.FindProperty("LocalMapRadius");
|
||||
_localMapHeightProperty = serializedObject.FindProperty("_localMapHeight");
|
||||
_localMapBaseHeightProperty = serializedObject.FindProperty("_localMapBaseHeight");
|
||||
_useCustomTerrainMaterialProperty = serializedObject.FindProperty("_useCustomTerrainMaterial");
|
||||
_elevationScaleProperty = serializedObject.FindProperty("_elevationScale");
|
||||
_castShadowsProperty = serializedObject.FindProperty("_castShadows");
|
||||
|
@ -123,18 +122,16 @@ namespace Microsoft.Maps.Unity
|
|||
_useCustomClippingVolumeMaterialProperty = serializedObject.FindProperty("_useCustomClippingVolumeMaterial");
|
||||
_customClippingVolumeMaterialProperty = serializedObject.FindProperty("_customClippingVolumeMaterial");
|
||||
_clippingVolumeDistanceTextureResolution = serializedObject.FindProperty("_clippingVolumeDistanceTextureResolution");
|
||||
_labelPrefabProperty = serializedObject.FindProperty("_labelPrefab");
|
||||
_mapEdgeColorProperty = serializedObject.FindProperty("_mapEdgeColor");
|
||||
_mapEdgeColorFadeDistanceProperty = serializedObject.FindProperty("_mapEdgeColorFadeDistance");
|
||||
_detailOffsetProperty = serializedObject.FindProperty("_detailOffset");
|
||||
_mapColliderTypeProperty = serializedObject.FindProperty("_mapColliderType");
|
||||
_maxCacheSizeInBytesProperty = serializedObject.FindProperty("_maxCacheSizeInBytes");
|
||||
_bannerWhite = (Texture2D)Resources.Load("MapsSDK-EditorBannerWhite");
|
||||
_bannerBlack = (Texture2D)Resources.Load("MapsSDK-EditorBannerBlack");
|
||||
_textureTileLayersProperty = serializedObject.FindProperty("_textureTileLayers");
|
||||
_elevationTileLayersProperty = serializedObject.FindProperty("_elevationTileLayers");
|
||||
_hideTileLayerComponentsProperty = serializedObject.FindProperty("_hideTileLayerComponents");
|
||||
_languageOverrideProperty = serializedObject.FindProperty("_languageOverride");
|
||||
_languageChangedProperty = serializedObject.FindProperty("_languageChanged");
|
||||
_mapSessionProperty = serializedObject.FindProperty("_mapSession");
|
||||
|
||||
EditorApplication.update += QueuePlayerLoopUpdate;
|
||||
}
|
||||
|
@ -188,7 +185,7 @@ namespace Microsoft.Maps.Unity
|
|||
if (mapRenderer.Raycast(ray, out var hitInfo))
|
||||
{
|
||||
_startingHitPointInWorldSpace = hitInfo.Point;
|
||||
_startingCenterInMercatorSpace = mapRenderer.Center.ToMercatorPosition();
|
||||
_startingCenterInMercator = mapRenderer.Center.ToMercatorCoordinate();
|
||||
_isDragging = true;
|
||||
currentEvent.Use();
|
||||
}
|
||||
|
@ -203,8 +200,8 @@ namespace Microsoft.Maps.Unity
|
|||
var updatedHitPointInWorldSpace = ray.GetPoint(enter);
|
||||
var newDeltaInWorldSpace = updatedHitPointInWorldSpace - _startingHitPointInWorldSpace;
|
||||
var newDeltaInLocalSpace = mapRenderer.transform.worldToLocalMatrix * newDeltaInWorldSpace;
|
||||
var newDeltaInMercator = new Vector2D(newDeltaInLocalSpace.x, newDeltaInLocalSpace.z) / Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var newCenter = LatLon.FromMercatorPosition(_startingCenterInMercatorSpace - newDeltaInMercator);
|
||||
var newDeltaInMercator = new MercatorCoordinate(newDeltaInLocalSpace.x, newDeltaInLocalSpace.z) / Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var newCenter = (_startingCenterInMercator - newDeltaInMercator).ToLatLon();
|
||||
|
||||
Undo.RecordObject(mapRenderer, "Change Center.");
|
||||
mapRenderer.Center = newCenter;
|
||||
|
@ -235,33 +232,11 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
RenderBanner();
|
||||
|
||||
// Setup and key.
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
EditorGUILayout.LabelField("API Settings", EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel++;
|
||||
_bingMapsKeyProperty.stringValue = EditorGUILayout.PasswordField("Bing Maps Key", _bingMapsKeyProperty.stringValue);
|
||||
if (string.IsNullOrWhiteSpace(_bingMapsKeyProperty.stringValue))
|
||||
{
|
||||
Help(
|
||||
"Provide a Bing Maps developer key to enable the map.",
|
||||
"Sign up for a key at the Bing Maps Dev Center.",
|
||||
"https://www.bingmapsportal.com/");
|
||||
}
|
||||
|
||||
_showMapDataInEditorProperty.boolValue =
|
||||
EditorGUILayout.Toggle(
|
||||
new GUIContent(
|
||||
"Show Map Data in Editor",
|
||||
"Map data usage in the editor will apply the specified Bing Maps key."),
|
||||
_showMapDataInEditorProperty.boolValue);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// Location Section
|
||||
EditorGUILayout.BeginVertical(_boxStyle);
|
||||
_showMapLocationOptions = EditorGUILayout.Foldout(_showMapLocationOptions, "Location", true, _foldoutTitleStyle);
|
||||
if (_showMapLocationOptions)
|
||||
_showLocationOptions = EditorGUILayout.Foldout(_showLocationOptions, "Location", true, _foldoutTitleStyle);
|
||||
if (_showLocationOptions)
|
||||
{
|
||||
var latitudeProperty = _centerProperty.FindPropertyRelative("Latitude");
|
||||
latitudeProperty.doubleValue = EditorGUILayout.DoubleField("Latitude", latitudeProperty.doubleValue);
|
||||
|
@ -272,7 +247,7 @@ namespace Microsoft.Maps.Unity
|
|||
// Get the zoomlevel values
|
||||
var minZoomLevel = _minZoomLevelProperty.floatValue;
|
||||
var maxZoomLevel = _maxZoomLevelProperty.floatValue;
|
||||
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel("Zoom Level Range");
|
||||
EditorGUI.indentLevel--;
|
||||
|
@ -281,19 +256,18 @@ namespace Microsoft.Maps.Unity
|
|||
maxZoomLevel = EditorGUILayout.FloatField((float)Math.Round(maxZoomLevel, 2), _minMaxLabelsLayoutOptions);
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
|
||||
// Update it back
|
||||
_minZoomLevelProperty.floatValue = minZoomLevel;
|
||||
_maxZoomLevelProperty.floatValue = maxZoomLevel;
|
||||
GUILayout.Space(4);
|
||||
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// Map Layout Section
|
||||
EditorGUILayout.BeginVertical(_boxStyle);
|
||||
_showMapSizingOptions = EditorGUILayout.Foldout(_showMapSizingOptions, "Map Layout", true, _foldoutTitleStyle);
|
||||
if (_showMapSizingOptions)
|
||||
_showLayoutOptions = EditorGUILayout.Foldout(_showLayoutOptions, "Map Layout", true, _foldoutTitleStyle);
|
||||
if (_showLayoutOptions)
|
||||
{
|
||||
// Map Shape Controls
|
||||
GUILayout.BeginHorizontal();
|
||||
|
@ -306,20 +280,17 @@ namespace Microsoft.Maps.Unity
|
|||
if (_mapShapeProperty.enumValueIndex == (int)MapShape.Block)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_localMapDimensionProperty);
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Dimension: " + ((MapRenderer)target).MapDimension.ToString());
|
||||
GUILayout.Space(6f);
|
||||
EditorGUILayout.PropertyField(_localMapHeightProperty);
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Height: " + ((MapRenderer)target).MapHeight.ToString());
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Dimension: " + mapRenderer.MapDimension.ToString());
|
||||
}
|
||||
else if (_mapShapeProperty.enumValueIndex == (int)MapShape.Cylinder)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_localMapRadiusProperty);
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Radius: " + (((MapRenderer)target).MapDimension.x / 2.0f).ToString());
|
||||
GUILayout.Space(6f);
|
||||
EditorGUILayout.PropertyField(_localMapHeightProperty);
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Height: " + ((MapRenderer)target).MapHeight.ToString());
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Radius: " + (mapRenderer.MapDimension.x / 2.0f).ToString());
|
||||
}
|
||||
GUILayout.Space(6f);
|
||||
EditorGUILayout.PropertyField(_localMapBaseHeightProperty);
|
||||
EditorGUILayout.LabelField(" ", "Scaled Map Base Height: " + mapRenderer.MapBaseHeight.ToString());
|
||||
GUILayout.Space(6f);
|
||||
|
||||
// Map Collider Type Controls
|
||||
GUILayout.BeginHorizontal();
|
||||
|
@ -333,8 +304,8 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
// Render Settings Section
|
||||
EditorGUILayout.BeginVertical(_boxStyle);
|
||||
_terrainOptions = EditorGUILayout.Foldout(_terrainOptions, "Render Settings", true, _foldoutTitleStyle);
|
||||
if (_terrainOptions)
|
||||
_showRenderingOptions = EditorGUILayout.Foldout(_showRenderingOptions, "Render Settings", true, _foldoutTitleStyle);
|
||||
if (_showRenderingOptions)
|
||||
{
|
||||
// Map Terrain Type Controls
|
||||
GUILayout.BeginHorizontal();
|
||||
|
@ -382,8 +353,9 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
GUILayout.Space(6f);
|
||||
}
|
||||
GUILayout.Space(6f);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// Quality options.
|
||||
|
@ -391,15 +363,6 @@ namespace Microsoft.Maps.Unity
|
|||
_showQualityOptions = EditorGUILayout.Foldout(_showQualityOptions, "Quality", true, _foldoutTitleStyle);
|
||||
if (_showQualityOptions)
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(Application.isPlaying);
|
||||
_maxCacheSizeInBytesProperty.longValue =
|
||||
1024 *
|
||||
1024 *
|
||||
EditorGUILayout.LongField(
|
||||
new GUIContent("Max Cache Size (MB)"),
|
||||
_maxCacheSizeInBytesProperty.longValue / 1024 / 1024);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
var position = EditorGUILayout.GetControlRect(false, 2 * EditorGUIUtility.singleLineHeight);
|
||||
position.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
|
@ -440,8 +403,8 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
// Texture Tile Providers
|
||||
EditorGUILayout.BeginVertical(_boxStyle);
|
||||
_showTileLayers = EditorGUILayout.Foldout(_showTileLayers, "Tile Layers", true, _foldoutTitleStyle);
|
||||
if (_showTileLayers)
|
||||
_showTileLayerOptions = EditorGUILayout.Foldout(_showTileLayerOptions, "Tile Layers", true, _foldoutTitleStyle);
|
||||
if (_showTileLayerOptions)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_textureTileLayersProperty, true);
|
||||
EditorGUILayout.PropertyField(_elevationTileLayersProperty, true);
|
||||
|
@ -452,7 +415,7 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
// Localization
|
||||
EditorGUILayout.BeginVertical(_boxStyle);
|
||||
_showLocalizationOptions = EditorGUILayout.Foldout(_showTileLayers, "Localization", true, _foldoutTitleStyle);
|
||||
_showLocalizationOptions = EditorGUILayout.Foldout(_showLocalizationOptions, "Localization", true, _foldoutTitleStyle);
|
||||
if (_showLocalizationOptions)
|
||||
{
|
||||
var previousIsLanguageAutoDetected = _languageOverrideProperty.intValue == (int)SystemLanguage.Unknown;
|
||||
|
@ -481,62 +444,26 @@ namespace Microsoft.Maps.Unity
|
|||
EditorGUILayout.PropertyField(_languageOverrideProperty, new GUIContent("Language"));
|
||||
}
|
||||
|
||||
GUILayout.Space(4);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(12);
|
||||
EditorGUILayout.PropertyField(_languageChangedProperty);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
GUILayout.Space(4);
|
||||
|
||||
EditorGUILayout.PropertyField(_mapSessionProperty);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (_baseStyle == null)
|
||||
{
|
||||
_baseStyle = new GUIStyle
|
||||
{
|
||||
wordWrap = true,
|
||||
font = EditorStyles.helpBox.font,
|
||||
fontSize = EditorStyles.helpBox.fontSize,
|
||||
normal = EditorStyles.helpBox.normal
|
||||
};
|
||||
_baseStyle.normal.background = null;
|
||||
_baseStyle.stretchWidth = false;
|
||||
_baseStyle.stretchHeight = false;
|
||||
_baseStyle.margin = new RectOffset();
|
||||
}
|
||||
|
||||
if (_errorIcon == null)
|
||||
{
|
||||
_errorIcon = EditorGUIUtility.TrIconContent("console.erroricon");
|
||||
}
|
||||
|
||||
if (_errorIconStyle == null)
|
||||
{
|
||||
_errorIconStyle =
|
||||
new GUIStyle(_baseStyle)
|
||||
{
|
||||
stretchHeight = false,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
fixedWidth = _errorIcon.image.width,
|
||||
fixedHeight = 1.0f * _errorIcon.image.height,
|
||||
stretchWidth = false,
|
||||
wordWrap = false
|
||||
};
|
||||
}
|
||||
|
||||
if (_hyperlinkStyle == null)
|
||||
{
|
||||
_hyperlinkStyle = new GUIStyle(_baseStyle);
|
||||
_hyperlinkStyle.alignment = TextAnchor.UpperLeft;
|
||||
_hyperlinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f);
|
||||
_hyperlinkStyle.stretchWidth = false;
|
||||
_hyperlinkStyle.padding = new RectOffset();
|
||||
_hyperlinkStyle.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
|
||||
if (_foldoutTitleStyle == null)
|
||||
{
|
||||
{
|
||||
_foldoutTitleStyle = new GUIStyle(EditorStyles.foldout)
|
||||
{
|
||||
fontStyle = UnityEngine.FontStyle.Bold
|
||||
|
@ -549,56 +476,6 @@ namespace Microsoft.Maps.Unity
|
|||
}
|
||||
}
|
||||
|
||||
private void RenderBanner()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.Label(EditorGUIUtility.isProSkin ? _bannerWhite : _bannerBlack, GUILayout.MaxHeight(96f));
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void Help(string message, string urlMessage, string url)
|
||||
{
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel(" ");
|
||||
var rect = EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
var iconWidth = _errorIcon.image.width;
|
||||
EditorGUILayout.LabelField(_errorIcon, _errorIconStyle, GUILayout.Width(iconWidth));
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
{
|
||||
GUILayout.Space(8);
|
||||
EditorGUILayout.LabelField(message, _baseStyle);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUILayout.LabelField(urlMessage, _hyperlinkStyle);
|
||||
|
||||
var linkRect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
EditorGUIUtility.AddCursorRect(linkRect, MouseCursor.Link);
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.MouseUp && linkRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
Application.OpenURL(url);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUILayout.Space(4);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUI.indentLevel++;
|
||||
}
|
||||
|
||||
private void QueuePlayerLoopUpdate()
|
||||
{
|
||||
EditorApplication.QueuePlayerLoopUpdate();
|
||||
|
|
|
@ -20,8 +20,8 @@ namespace Microsoft.Maps.Unity
|
|||
Gizmos.matrix = mapRenderer.gameObject.transform.localToWorldMatrix;
|
||||
Gizmos.color = color;
|
||||
Gizmos.DrawCube(
|
||||
new Vector3(0, mapRenderer.LocalMapHeight / 2, 0),
|
||||
new Vector3(mapRenderer.LocalMapDimension.x, mapRenderer.LocalMapHeight, mapRenderer.LocalMapDimension.y));
|
||||
new Vector3(0, mapRenderer.LocalMapBaseHeight / 2, 0),
|
||||
new Vector3(mapRenderer.LocalMapDimension.x, mapRenderer.LocalMapBaseHeight, mapRenderer.LocalMapDimension.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(MapSession))]
|
||||
[CanEditMultipleObjects]
|
||||
internal class MapSessionEditor : Editor
|
||||
{
|
||||
private SerializedProperty _developerKeyProperty;
|
||||
private SerializedProperty _showMapDataInEditorProperty;
|
||||
|
||||
private GUIStyle _baseStyle = null;
|
||||
private GUIStyle _hyperlinkStyle = null;
|
||||
private GUIStyle _iconStyle = null;
|
||||
private GUIContent _warnIcon = null;
|
||||
private GUIStyle _foldoutTitleStyle = null;
|
||||
private GUIStyle _boxStyle = null;
|
||||
private Texture2D _bannerWhite = null;
|
||||
private Texture2D _bannerBlack = null;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_developerKeyProperty = serializedObject.FindProperty("_developerKey");
|
||||
_showMapDataInEditorProperty = serializedObject.FindProperty("_showMapDataInEditor");
|
||||
_bannerWhite = (Texture2D)Resources.Load("MapsSDK-EditorBannerWhite");
|
||||
_bannerBlack = (Texture2D)Resources.Load("MapsSDK-EditorBannerBlack");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
// This should just be done one time.
|
||||
{
|
||||
var mapSession = target as MapSession;
|
||||
var components = mapSession.gameObject.GetComponents<Component>();
|
||||
|
||||
var mapRendererIndex = -1;
|
||||
for (var i = 0; i < components.Length; i++)
|
||||
{
|
||||
if (components[i] is MapRenderer)
|
||||
{
|
||||
mapRendererIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var mapSessionIndex = -1;
|
||||
for (var i = 0; i < components.Length; i++)
|
||||
{
|
||||
if (components[i] is MapSession)
|
||||
{
|
||||
mapSessionIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapSessionIndex > mapRendererIndex)
|
||||
{
|
||||
var delta = mapSessionIndex - mapRendererIndex;
|
||||
while (delta > 0)
|
||||
{
|
||||
UnityEditorInternal.ComponentUtility.MoveComponentUp(mapSession);
|
||||
delta--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderBanner();
|
||||
|
||||
// Setup and key.
|
||||
_developerKeyProperty.stringValue = EditorGUILayout.PasswordField("Developer Key", _developerKeyProperty.stringValue);
|
||||
if (string.IsNullOrWhiteSpace(_developerKeyProperty.stringValue))
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
Help(
|
||||
"Provide a developer key to enable Bing Maps services.",
|
||||
"Sign up for a key at the Bing Maps Dev Center.",
|
||||
"https://www.bingmapsportal.com/");
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
_showMapDataInEditorProperty.boolValue =
|
||||
EditorGUILayout.Toggle(
|
||||
new GUIContent(
|
||||
"Show Map Data in Editor",
|
||||
"Map data usage in the editor will apply to the specified developer key."),
|
||||
_showMapDataInEditorProperty.boolValue);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void Help(string message, string urlMessage, string url)
|
||||
{
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel(" ");
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
GUILayout.Space(8);
|
||||
var iconWidth = _warnIcon.image.width;
|
||||
EditorGUILayout.LabelField(_warnIcon, _iconStyle, GUILayout.Width(iconWidth));
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
{
|
||||
GUILayout.Space(8);
|
||||
EditorGUILayout.LabelField(message, _baseStyle);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUILayout.LabelField(urlMessage, _hyperlinkStyle);
|
||||
|
||||
var linkRect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
EditorGUIUtility.AddCursorRect(linkRect, MouseCursor.Link);
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.MouseUp && linkRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
Application.OpenURL(url);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUILayout.Space(4);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUI.indentLevel++;
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (_baseStyle == null)
|
||||
{
|
||||
_baseStyle = new GUIStyle
|
||||
{
|
||||
wordWrap = true,
|
||||
font = EditorStyles.helpBox.font,
|
||||
fontSize = EditorStyles.helpBox.fontSize,
|
||||
normal = EditorStyles.helpBox.normal
|
||||
};
|
||||
_baseStyle.normal.background = null;
|
||||
_baseStyle.stretchWidth = false;
|
||||
_baseStyle.stretchHeight = false;
|
||||
_baseStyle.margin = new RectOffset();
|
||||
}
|
||||
|
||||
if (_warnIcon == null)
|
||||
{
|
||||
_warnIcon = EditorGUIUtility.TrIconContent("console.warnicon");
|
||||
}
|
||||
|
||||
if (_iconStyle == null)
|
||||
{
|
||||
_iconStyle =
|
||||
new GUIStyle(_baseStyle)
|
||||
{
|
||||
stretchHeight = false,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
fixedWidth = _warnIcon.image.width,
|
||||
fixedHeight = _warnIcon.image.height,
|
||||
stretchWidth = false,
|
||||
wordWrap = false
|
||||
};
|
||||
}
|
||||
|
||||
if (_hyperlinkStyle == null)
|
||||
{
|
||||
_hyperlinkStyle =
|
||||
new GUIStyle(_baseStyle)
|
||||
{
|
||||
alignment = TextAnchor.UpperLeft
|
||||
};
|
||||
_hyperlinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f);
|
||||
_hyperlinkStyle.stretchWidth = false;
|
||||
_hyperlinkStyle.padding = new RectOffset();
|
||||
_hyperlinkStyle.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
|
||||
if (_foldoutTitleStyle == null)
|
||||
{
|
||||
_foldoutTitleStyle = new GUIStyle(EditorStyles.foldout)
|
||||
{
|
||||
fontStyle = UnityEngine.FontStyle.Bold
|
||||
};
|
||||
}
|
||||
|
||||
if (_boxStyle == null)
|
||||
{
|
||||
_boxStyle = new GUIStyle(GUI.skin.box);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderBanner()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.Label(EditorGUIUtility.isProSkin ? _bannerWhite : _bannerBlack, GUILayout.MaxHeight(96f));
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b303ffbed90191b4dbbf76b03bf83d80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: cab8e8f62b00b544f803696d2e169bf3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// This script provides a menu item under "Assets -> Maps SDK for Unity -> Upgrade Component GUIDs". This will find all old component GUIDs
|
||||
/// which have had their GUIDs modified to a new value. This is typically a result of migrating a component from a DLL to a script.
|
||||
/// Finds and replaces matching GUID usages in any scene or prefab.
|
||||
/// </summary>
|
||||
public static class SdkUpgradeUtility
|
||||
{
|
||||
// List of Tuples containing old guid (Item1) and the new guid (Item2).
|
||||
private static readonly List<Tuple<string, string>> GuidsToUpdate =
|
||||
new List<Tuple<string, string>>
|
||||
{
|
||||
// MapRenderer
|
||||
new Tuple<string, string>(
|
||||
"fileID: -194183520, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3",
|
||||
"fileID: 11500000, guid: 1cf6985fc3c122a4193d16fdcfb59784, type: 3"),
|
||||
// CopyrightLayer
|
||||
new Tuple<string, string>(
|
||||
"fileID: 1914003294, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3",
|
||||
"fileID: 11500000, guid: 02c7d1b323594a144ac9b98fd93e0f7f, type: 3"),
|
||||
// MapDataCache
|
||||
new Tuple<string, string>(
|
||||
"fileID: -1554650353, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3",
|
||||
"fileID: 11500000, guid: 1ef50f6f9318ded40b230c1eefb7f968, type: 3"),
|
||||
// MapPinLayer
|
||||
new Tuple<string, string>(
|
||||
"fileID: 1083584769, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3}",
|
||||
"fileID: 11500000, guid: 5d8a6459eb3010b4f9751de03dca135a, type: 3}"),
|
||||
// MapPin
|
||||
new Tuple<string, string>(
|
||||
"fileID: -404975296, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3",
|
||||
"fileID: 11500000, guid: 0bb87916f59f52349b237e7ce66a84a1, type: 3"),
|
||||
// ClusterMapPin
|
||||
new Tuple<string, string>(
|
||||
"fileID: -2137691127, guid: f58183a31672bf641bbeeaef3d4759c0, type: 3",
|
||||
"fileID: 11500000, guid: 10142379db1f9994e9e1ea54ee0ceb78, type: 3")
|
||||
};
|
||||
|
||||
[MenuItem("Assets/Maps SDK for Unity/Upgrade Component GUIDs")]
|
||||
public static void UpgradeScenes()
|
||||
{
|
||||
// Find all scene files in the assets directory.
|
||||
|
||||
// Replace old GUIDs with new GUIDs.
|
||||
var output = "";
|
||||
var needsAssetReimport = false;
|
||||
|
||||
// Scenes
|
||||
var sceneFiles = Directory.GetFiles(Application.dataPath, "*.unity", SearchOption.AllDirectories);
|
||||
foreach (var sceneFile in sceneFiles)
|
||||
{
|
||||
output += ScrubAssets(sceneFile);
|
||||
needsAssetReimport = needsAssetReimport || !string.IsNullOrEmpty(output);
|
||||
}
|
||||
|
||||
// Prefabs
|
||||
var prefabFiles = Directory.GetFiles(Application.dataPath, "*.prefab", SearchOption.AllDirectories);
|
||||
foreach (var prefabFile in prefabFiles)
|
||||
{
|
||||
output += ScrubAssets(prefabFile);
|
||||
needsAssetReimport = needsAssetReimport || !string.IsNullOrEmpty(output);
|
||||
}
|
||||
|
||||
// Reimport assets if there were changes to the scene files.
|
||||
if (needsAssetReimport)
|
||||
{
|
||||
Debug.Log("Upgraded assets:\r\n" + output);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("No assets were modified.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string ScrubAssets(string assetFile)
|
||||
{
|
||||
var assetText = File.ReadAllText(assetFile);
|
||||
|
||||
var newAssetText = assetText;
|
||||
foreach (var guidToUpdate in GuidsToUpdate)
|
||||
{
|
||||
newAssetText = newAssetText.Replace(guidToUpdate.Item1, guidToUpdate.Item2);
|
||||
}
|
||||
|
||||
var output = "";
|
||||
if (newAssetText != assetText)
|
||||
{
|
||||
output += " " + Path.GetFileName(assetFile) + "\r\n";
|
||||
File.WriteAllText(assetFile, newAssetText);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 007c5a4f1ad183f4d82f32e5342af7df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"name": "Microsoft.Maps.Unity.SupportingScripts"
|
||||
}
|
||||
{
|
||||
"name": "Microsoft.Maps.Unity.SupportingScripts"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 733ffde8ec04390438678aec62001c8d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 609eb4e277e00424daf7838ab0ca87cd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,81 +1,81 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: StandardClippingVolumeMaterial-MapsSDK
|
||||
m_Shader: {fileID: 4800000, guid: 4f3662d02ce27e74ba4365f3c0264722, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _TerrainDistanceTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: StandardClippingVolumeMaterial-MapsSDK
|
||||
m_Shader: {fileID: 4800000, guid: 4f3662d02ce27e74ba4365f3c0264722, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _TerrainDistanceTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
|
@ -1,8 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d35f8f2bbaf569a418c0ddbcaa384840
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: d35f8f2bbaf569a418c0ddbcaa384840
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,76 +1,76 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: StandardTerrainMaterial-MapsSDK
|
||||
m_Shader: {fileID: 4800000, guid: 8e4dab924fbdfc04a81deb2ea246a3ff, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 44bb6c7e1a380214fac3e1cca2195376, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: StandardTerrainMaterial-MapsSDK
|
||||
m_Shader: {fileID: 4800000, guid: 8e4dab924fbdfc04a81deb2ea246a3ff, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 44bb6c7e1a380214fac3e1cca2195376, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
|
@ -1,8 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d68ae504d313a4489795ec46e1c8f48
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 1d68ae504d313a4489795ec46e1c8f48
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 324e19c307bf7374b9a245a49fec9622
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
До Ширина: | Высота: | Размер: 2.9 KiB После Ширина: | Высота: | Размер: 2.9 KiB |
|
@ -1,119 +1,119 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 44bb6c7e1a380214fac3e1cca2195376
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 6
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 2
|
||||
aniso: 4
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 44bb6c7e1a380214fac3e1cca2195376
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 6
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 2
|
||||
aniso: 4
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d374608a22f6ddc40b7d42af63a0ca11
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a697e415a1022a54e87af4db75ea04c8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// This component provides an interface to configure the cache size that is used to store <see cref="MapRenderer"/> data.
|
||||
/// Because the cache is global, multiple instances of this component are not needed.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[ExecuteInEditMode]
|
||||
public class MapDataCache : MapDataCacheBase
|
||||
{
|
||||
private const long DefaultMaxCacheSizeInBytes = 2147483648L; // 2 GB
|
||||
private const long MaxMaxCacheSizeInBytes = 4294967296L; // 4 GB
|
||||
private const long MinCacheSizeInBytes = 209715200L; // 200 MB
|
||||
|
||||
/// <summary>
|
||||
/// Determines how large the cache is relative to the estimated application memory limit, e.g. if the maximum app memory for the
|
||||
/// application is determined to be 1GB, then a utilization value of 0.5 (50%), will result in a cache size of 512MB.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Range(0, 1)]
|
||||
private float _percentUtilization = 0.3f;
|
||||
|
||||
/// <summary>
|
||||
/// Determines how large the cache is relative to the estimated application memory limit, e.g. if the maximum app memory for the
|
||||
/// application is determined to be 1GB, then a utilization value of 0.5 (50%), will result in a cache size of 512MB.
|
||||
/// </summary>
|
||||
public float PercentUtilization
|
||||
{
|
||||
get => _percentUtilization;
|
||||
set
|
||||
{
|
||||
var newPercentUtilization = Mathf.Clamp01(_percentUtilization);
|
||||
if (newPercentUtilization != _percentUtilization)
|
||||
{
|
||||
_percentUtilization = newPercentUtilization;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The maximum possible cache size. Even if the device could support a larger cache, the cache size will not exceed this value.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private long _maxCacheSizeInBytes = DefaultMaxCacheSizeInBytes;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum possible cache size. Even if the device could support a larger cache, the cache size will not exceed this value.
|
||||
/// </summary>
|
||||
public long MaxCacheSizeInBytes
|
||||
{
|
||||
get => _maxCacheSizeInBytes;
|
||||
set
|
||||
{
|
||||
var newMaxCacheSizeInBytes = Math.Min(MaxMaxCacheSizeInBytes, _maxCacheSizeInBytes);
|
||||
if (_maxCacheSizeInBytes != newMaxCacheSizeInBytes)
|
||||
{
|
||||
_maxCacheSizeInBytes = newMaxCacheSizeInBytes;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
_maxCacheSizeInBytes = Math.Min(MaxMaxCacheSizeInBytes, _maxCacheSizeInBytes);
|
||||
_percentUtilization = Mathf.Clamp01(_percentUtilization);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override long ComputeCacheSizeInBytes()
|
||||
{
|
||||
var maximumAvailableBytes = 0L;
|
||||
|
||||
#if UNITY_ANDROID
|
||||
// On Android, we can query the application's memory limit to get an accurate max size.
|
||||
if (!Application.isEditor)
|
||||
{
|
||||
try
|
||||
{
|
||||
maximumAvailableBytes = GetAvailableMemory();
|
||||
maximumAvailableBytes = (long)(maximumAvailableBytes * 0.9f); // Leave some room.
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e, gameObject);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// The fall back option is to just compute a maximum size based on the total available memory.
|
||||
if (maximumAvailableBytes <= 0)
|
||||
{
|
||||
var totalSystemMemoryInBytes = SystemInfo.systemMemorySize /* <-- MB */ * 1000L * 1000L;
|
||||
var managedBytes = GC.GetTotalMemory(true);
|
||||
maximumAvailableBytes = totalSystemMemoryInBytes - managedBytes;
|
||||
}
|
||||
|
||||
var percentUtilization = Mathf.Clamp01(_percentUtilization);
|
||||
var cacheSizeInBytes = (long)(percentUtilization * maximumAvailableBytes);
|
||||
return Math.Max(MinCacheSizeInBytes, Math.Min(cacheSizeInBytes, _maxCacheSizeInBytes));
|
||||
}
|
||||
|
||||
#if UNITY_ANDROID
|
||||
|
||||
private static AndroidJavaObject GetMemoryInfo()
|
||||
{
|
||||
var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||||
var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
|
||||
var systemService = currentActivity.Call<AndroidJavaObject>("getSystemService", "activity");
|
||||
var memoryInfo = new AndroidJavaObject("android.app.ActivityManager$MemoryInfo");
|
||||
systemService.Call("getMemoryInfo", memoryInfo);
|
||||
return memoryInfo;
|
||||
}
|
||||
|
||||
private static long GetAvailableMemory()
|
||||
{
|
||||
using (var memoryInfo = GetMemoryInfo())
|
||||
{
|
||||
return memoryInfo.Get<long>("availMem");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1ef50f6f9318ded40b230c1eefb7f968
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1dc6775b63b0414fbe5f55b0f9a613a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b203a2e1986b2424cb9eb1e0df040324
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a47178748d759746adc3412b40b1fde
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
/// <summary>
|
||||
/// Alignment options for <see cref="MapCopyrightLayer"/>.
|
||||
/// </summary>
|
||||
public enum MapCopyrightAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// Default alignment. Copyright text is rendered at the bottom of the map.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
|
||||
/// <summary>
|
||||
/// Copyright text is rendered at the top of the map.
|
||||
/// </summary>
|
||||
Top
|
||||
};
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 147b435955cf84a4fbad9fd9187c7b40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,273 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Handles rendering and positioning of copyright text associated with the <see cref="MapRendererBase"/>.
|
||||
/// This layer is automatically added when the <see cref="MapRendererBase"/> component is added to a <see cref="GameObject"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the default placement of the copyright text displayed by the <see cref="MapRendererBase"/> is unacceptable, it can be disabled
|
||||
/// and the text can be displayed manually by retrieving the copyright text string from <see cref="MapRendererBase.Copyright"/> and
|
||||
/// rendering it with a TextMesh or TextMeshPro component. The copyright text must be displayed in a conspicuous manner near the map.
|
||||
/// </remarks>
|
||||
[DisallowMultipleComponent]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(MapRenderer))]
|
||||
public class MapCopyrightLayer : MapLayer
|
||||
{
|
||||
private const float Margin = 0.015f;
|
||||
|
||||
/// <summary>
|
||||
/// The font used for the copyright text.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Font _font = null;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the copyright text.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Color _textColor = new Color(0, 0, 0, 0.42f);
|
||||
|
||||
/// <summary>
|
||||
/// The alignment of the copyright text.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private MapCopyrightAlignment _mapCopyrightAlignment = MapCopyrightAlignment.Bottom;
|
||||
|
||||
// Reload these fields lazily...
|
||||
// The corresponding text GameObjects will be marked HideAndDontSave, i.e. purely temporary.
|
||||
|
||||
private TextMesh _copyrightText1 = null;
|
||||
private TextMesh _copyrightText2 = null;
|
||||
private Shader _occludable3DTextShader = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
LayerName = "MapCopyrightLayer";
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
MapRenderer.AfterUpdate -= UpdateDefaultCopyrights;
|
||||
MapRenderer.AfterUpdate += UpdateDefaultCopyrights;
|
||||
MapRenderer.AfterOnDisable -= MapRendererDisabled;
|
||||
MapRenderer.AfterOnDisable += MapRendererDisabled;
|
||||
|
||||
if (_copyrightText1 != null)
|
||||
{
|
||||
_copyrightText1.gameObject.SetActive(true);
|
||||
}
|
||||
if (_copyrightText2 != null)
|
||||
{
|
||||
_copyrightText2.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
MapRenderer.AfterUpdate -= UpdateDefaultCopyrights;
|
||||
MapRenderer.AfterOnDisable -= MapRendererDisabled;
|
||||
|
||||
_copyrightText1?.gameObject.SetActive(false);
|
||||
_copyrightText2?.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_copyrightText1 != null)
|
||||
{
|
||||
DestroyImmediate(_copyrightText1.gameObject);
|
||||
_copyrightText1 = null;
|
||||
}
|
||||
|
||||
if (_copyrightText2 != null)
|
||||
{
|
||||
DestroyImmediate(_copyrightText2.gameObject);
|
||||
_copyrightText2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDefaultCopyrights(object sender, EventArgs args)
|
||||
{
|
||||
const int fontSize = 46;
|
||||
const float targetLocalSize = 0.175f;
|
||||
const float targetLocalScale = targetLocalSize / fontSize;
|
||||
var localYOffset = new Vector3(0, MapRenderer.LocalMapBaseHeight - 2 * targetLocalScale, 0);
|
||||
|
||||
// Load the default font, if it hasn't already been loaded.
|
||||
if (_font == null)
|
||||
{
|
||||
_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
Debug.Assert(_font != null);
|
||||
}
|
||||
|
||||
// Create the copyright game objects if they haven't already been created.
|
||||
EnsureCopyrightGameObjectSetup(ref _copyrightText1, "DefaultCopyright1", fontSize);
|
||||
EnsureCopyrightGameObjectSetup(ref _copyrightText2, "DefaultCopyright2", fontSize);
|
||||
|
||||
// Sync the configurable properties.
|
||||
{
|
||||
var mapRendererGameObject = MapRenderer.gameObject;
|
||||
_copyrightText1.gameObject.layer = mapRendererGameObject.layer;
|
||||
_copyrightText1.text = MapRenderer.Copyright;
|
||||
_copyrightText1.color = _textColor;
|
||||
_copyrightText2.gameObject.layer = mapRendererGameObject.layer;
|
||||
_copyrightText2.text = MapRenderer.Copyright;
|
||||
_copyrightText2.color = _textColor;
|
||||
}
|
||||
|
||||
// Update positions.
|
||||
{
|
||||
// First, determine which two sides of the map that we can see.
|
||||
var mainCamera = Camera.main;
|
||||
var cameraPosition = mainCamera == null ? Vector3.zero : mainCamera.transform.position;
|
||||
var thisTransform = transform;
|
||||
var cameraToPosition = thisTransform.position - cameraPosition;
|
||||
var transformForward = thisTransform.forward;
|
||||
var normal1Sign = Vector3.Dot(cameraToPosition, transformForward) > 0 ? -1.0f : 1.0f;
|
||||
var normal2Sign = Vector3.Dot(cameraToPosition, transform.right) > 0 ? -1.0f : 1.0f;
|
||||
var forward = transformForward * normal1Sign;
|
||||
var localForward = Vector3.forward * normal1Sign;
|
||||
var right = thisTransform.right * normal2Sign;
|
||||
var localRight = Vector3.right * normal2Sign;
|
||||
|
||||
// Position the text meshes.
|
||||
UpdateTextPositionAndAlignment(
|
||||
_copyrightText1,
|
||||
MapRenderer.LocalMapDimension.y,
|
||||
MapRenderer.LocalMapDimension.x,
|
||||
new Vector3(Margin, 0, 0),
|
||||
localForward,
|
||||
localYOffset,
|
||||
targetLocalScale);
|
||||
|
||||
UpdateTextPositionAndAlignment(
|
||||
_copyrightText2,
|
||||
MapRenderer.LocalMapDimension.x,
|
||||
MapRenderer.LocalMapDimension.y,
|
||||
new Vector3(0, 0, Margin),
|
||||
localRight,
|
||||
localYOffset,
|
||||
targetLocalScale);
|
||||
|
||||
// Align the text meshes correctly.
|
||||
_copyrightText1.transform.rotation = Quaternion.LookRotation(-forward, transform.up);
|
||||
_copyrightText2.transform.rotation = Quaternion.LookRotation(-right, transform.up);
|
||||
|
||||
// Enable / Disable the text depending on if the camera can see them.
|
||||
var cameraToText1Position = _copyrightText1.transform.position - cameraPosition;
|
||||
var cameraToText2Position = _copyrightText2.transform.position - cameraPosition;
|
||||
|
||||
var isText1VisibleToCamera = Vector3.Dot(cameraToText1Position, -_copyrightText1.transform.forward) <= 0;
|
||||
var isText2VisibleToCamera = Vector3.Dot(cameraToText2Position, -_copyrightText2.transform.forward) <= 0;
|
||||
|
||||
_copyrightText1.gameObject.SetActive(isText1VisibleToCamera);
|
||||
_copyrightText2.gameObject.SetActive(isText2VisibleToCamera);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTextPositionAndAlignment(
|
||||
TextMesh textMesh,
|
||||
float localNormalMagnitude,
|
||||
float localCrossMagnitude,
|
||||
Vector3 marginLeft,
|
||||
Vector3 localNormal,
|
||||
Vector3 localYOffset,
|
||||
float localScale)
|
||||
{
|
||||
if (MapRenderer.MapShape == MapShape.Block)
|
||||
{
|
||||
var localCross = Vector3.Cross(localNormal, Vector3.up);
|
||||
textMesh.transform.localPosition =
|
||||
0.504f * localNormalMagnitude * localNormal +
|
||||
0.5f * localCrossMagnitude * -localCross +
|
||||
(IsVectorNegative(localCross) ? -marginLeft : marginLeft);
|
||||
|
||||
if (_mapCopyrightAlignment == MapCopyrightAlignment.Top)
|
||||
{
|
||||
textMesh.anchor = TextAnchor.UpperLeft;
|
||||
textMesh.transform.localPosition += localYOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
textMesh.transform.localPosition += new Vector3(0, Margin, 0);
|
||||
textMesh.anchor = TextAnchor.LowerLeft;
|
||||
}
|
||||
textMesh.alignment = TextAlignment.Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
textMesh.transform.localPosition = MapRenderer.LocalMapRadius * localNormal;
|
||||
if (_mapCopyrightAlignment == MapCopyrightAlignment.Top)
|
||||
{
|
||||
textMesh.anchor = TextAnchor.UpperCenter;
|
||||
textMesh.transform.localPosition += localYOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
textMesh.transform.localPosition += new Vector3(0, Margin, 0);
|
||||
textMesh.anchor = TextAnchor.LowerCenter;
|
||||
}
|
||||
textMesh.alignment = TextAlignment.Center;
|
||||
}
|
||||
textMesh.transform.localScale = new Vector3(localScale, localScale, localScale);
|
||||
}
|
||||
|
||||
private bool IsVectorNegative(Vector3 v)
|
||||
{
|
||||
return v.x < 0 || v.z < 0;
|
||||
}
|
||||
|
||||
private void EnsureCopyrightGameObjectSetup(ref TextMesh textMesh, string copyrightGameObjectName, int fontSize)
|
||||
{
|
||||
if (textMesh == null)
|
||||
{
|
||||
var defaultCopyrightText =
|
||||
new GameObject(copyrightGameObjectName)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
defaultCopyrightText.transform.parent = transform;
|
||||
|
||||
textMesh = defaultCopyrightText.AddComponent<TextMesh>();
|
||||
textMesh.font = _font;
|
||||
textMesh.fontSize = fontSize;
|
||||
textMesh.fontStyle = UnityEngine.FontStyle.Bold;
|
||||
|
||||
if (_occludable3DTextShader == null)
|
||||
{
|
||||
_occludable3DTextShader = Shader.Find("MapsSDK/Occludable3DTextShader");
|
||||
}
|
||||
|
||||
if (_occludable3DTextShader != null)
|
||||
{
|
||||
var meshRenderer = textMesh.GetComponent<MeshRenderer>();
|
||||
meshRenderer.sharedMaterial = new Material(_occludable3DTextShader);
|
||||
meshRenderer.receiveShadows = true;
|
||||
meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
|
||||
if (textMesh.font != null)
|
||||
{
|
||||
meshRenderer.sharedMaterial.SetTexture("_MainTex", textMesh.font.material.mainTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textMesh.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void MapRendererDisabled(object sender, EventArgs args)
|
||||
{
|
||||
_copyrightText1?.gameObject.SetActive(false);
|
||||
_copyrightText2?.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 02c7d1b323594a144ac9b98fd93e0f7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for any type of layer associated with a <see cref="Unity.MapRenderer"/>.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(MapRenderer))]
|
||||
public abstract class MapLayer : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the <see cref="MapLayer"/>.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string _layerName;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the <see cref="MapLayer"/>.
|
||||
/// </summary>
|
||||
public string LayerName { get => _layerName; set => _layerName = value; }
|
||||
|
||||
private MapRenderer _mapRenderer;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MapRenderer"/> that this layer has been attached to.
|
||||
/// </summary>
|
||||
public MapRenderer MapRenderer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mapRenderer == null)
|
||||
{
|
||||
_mapRenderer = GetComponent<MapRenderer>();
|
||||
|
||||
if (_mapRenderer == null)
|
||||
{
|
||||
Debug.LogError($"Unable to find MapRenderer component on '{gameObject.name}'.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return _mapRenderer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 924125f3911e8214282ec255b5f3324a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2486b69a850b2749b2b81de84c6fd61
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a cluster of <see cref="MapPin"/>s at the specified level of detail.
|
||||
/// </summary>
|
||||
[HelpURL("https://github.com/Microsoft/MapsSDK-Unity/wiki/Attaching-GameObjects-to-the-map")]
|
||||
public class ClusterMapPin : MapPin
|
||||
{
|
||||
/// <summary>
|
||||
/// The level of detail represented by this cluster.
|
||||
/// </summary>
|
||||
public short LevelOfDetail
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of pins in this cluster.
|
||||
/// </summary>
|
||||
public int Size
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 10142379db1f9994e9e1ea54ee0ceb78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,182 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial;
|
||||
using Microsoft.Geospatial.VectorMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A MapPin can be used to pin a <see cref="GameObject"/> to a <see cref="MapRendererBase"/> at a specified
|
||||
/// <see cref="Geospatial.LatLon"/> and altitude.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[ExecuteInEditMode]
|
||||
[HelpURL("https://github.com/Microsoft/MapsSDK-Unity/wiki/Attaching-GameObjects-to-the-map")]
|
||||
public class MapPin : MonoBehaviour, IPinnable
|
||||
{
|
||||
[SerializeField]
|
||||
private LatLonWrapper _location;
|
||||
|
||||
/// <summary>
|
||||
/// The location of the <see cref="MapPin"/>.
|
||||
/// </summary>
|
||||
public LatLon Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return _location.ToLatLon();
|
||||
}
|
||||
set
|
||||
{
|
||||
var oldLocation = _location.ToLatLon();
|
||||
if (value != oldLocation)
|
||||
{
|
||||
_location = new LatLonWrapper(value);
|
||||
LocationChanged?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action that is invoked when the <see cref="Location"/> is changed.
|
||||
/// </summary>
|
||||
public Action<MapPin, LatLon> LocationChanged;
|
||||
|
||||
private MercatorCoordinate _mercatorCoordinate;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MercatorCoordinate MercatorCoordinate => _mercatorCoordinate;
|
||||
|
||||
[SerializeField]
|
||||
private double _altitude;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public double Altitude { get => _altitude; set => _altitude = value; }
|
||||
|
||||
[SerializeField]
|
||||
private AltitudeReference _altitudeReference = AltitudeReference.Surface;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public AltitudeReference AltitudeReference
|
||||
{
|
||||
get => _altitudeReference;
|
||||
set => _altitudeReference = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Vector3 PositionInMapLocalSpace
|
||||
{
|
||||
get => transform.localPosition;
|
||||
set => transform.localPosition = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool HasBeenFullyPositioned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, synchronizes this <see cref="GameObject"/>'s and it's childrens' layers to the same value as the
|
||||
/// associated <see cref="MapRendererBase"/>'s layer.
|
||||
/// </summary>
|
||||
public bool IsLayerSynchronized = true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the <see cref="ScaleCurve"/> is relative to the real-world scale at a given zoom level. As the map zooms out,
|
||||
/// size falls off exponentially. If false, the ScaleCurve represents the direct scale of the MapPin at a given zoom level.
|
||||
/// </summary>
|
||||
public bool UseRealWorldScale;
|
||||
|
||||
/// <summary>
|
||||
/// The scale of the pin relative to the map's zoom level.
|
||||
/// </summary>
|
||||
public AnimationCurve ScaleCurve = AnimationCurve.Linear(MapConstants.MinimumZoomLevel, 1, MapConstants.MaximumZoomLevel, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Reset the component to default values.
|
||||
/// </summary>
|
||||
protected virtual void Reset()
|
||||
{
|
||||
_mercatorCoordinate = Location.ToMercatorCoordinate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Awake is called when the component instance is being loaded.
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_mercatorCoordinate = Location.ToMercatorCoordinate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnEnable is called when the component is enabled and when scripts are reloaded.
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_mercatorCoordinate = Location.ToMercatorCoordinate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is called when the script is loaded or a value is changed in the inspector. Called in the editor only.
|
||||
/// </summary>
|
||||
protected virtual void Validate()
|
||||
{
|
||||
_mercatorCoordinate = Location.ToMercatorCoordinate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronizes the <see cref="MapPin"/>'s layers (and any of it's children layers) with the <see cref="MapRenderer"/>'s layer.
|
||||
/// Whether or not a <see cref="MapPin"/>'s layer is synchronized depends on the value of <see cref="MapPin.IsLayerSynchronized"/>.
|
||||
/// </summary>
|
||||
public static void SynchronizeLayers(IReadOnlyList<MapPin> mapPins, MapRenderer mapRenderer)
|
||||
{
|
||||
var targetLayer = mapRenderer.gameObject.layer;
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
if (mapPin.IsLayerSynchronized && mapPin.gameObject.layer != targetLayer)
|
||||
{
|
||||
mapPin.gameObject.layer = targetLayer;
|
||||
foreach (var child in mapPin.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
child.gameObject.layer = targetLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the <see cref="MapPin"/>s' scale based on <see cref="MapPin.ScaleCurve"/> and <see cref="MapPin.UseRealWorldScale"/>.
|
||||
/// </summary>
|
||||
public static void UpdateScales<T>(List<T> mapPins, MapRenderer mapRenderer) where T : MapPin
|
||||
{
|
||||
const double EquatorialCircumferenceInWgs84Meters = 40075016.685578488;
|
||||
var mapZoomLevel = mapRenderer.ZoomLevel;
|
||||
var mapTotalWidthInLocalSpace = Math.Pow(2, Math.Max(mapZoomLevel - 1.0, 0.0));
|
||||
var mapElevationScale = mapRenderer.ElevationScale;
|
||||
var mapRealisticScale = mapTotalWidthInLocalSpace / EquatorialCircumferenceInWgs84Meters;
|
||||
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
if (mapPin.enabled && mapPin.gameObject.activeInHierarchy)
|
||||
{
|
||||
// Scale the pin depending on the scale curve and current ZoomLevel.
|
||||
var mercatorScaleAtCoordinate = MercatorScale.AtMercatorLatitude(mapPin.MercatorCoordinate.Y);
|
||||
{
|
||||
var scale = mapPin.ScaleCurve.Evaluate(mapZoomLevel);
|
||||
|
||||
var additionalYScale = 1.0f;
|
||||
if (mapPin.UseRealWorldScale)
|
||||
{
|
||||
scale *= (float)(mercatorScaleAtCoordinate * mapRealisticScale);
|
||||
additionalYScale = mapElevationScale;
|
||||
}
|
||||
|
||||
mapPin.transform.localScale = new Vector3(scale, scale * additionalYScale, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0bb87916f59f52349b237e7ce66a84a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,386 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial.VectorMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
/// <summary>
|
||||
/// Maintains a collection of <see cref="MapPin"/>s. Supports clustering. This layer is queried by the associated MapRenderer to get the
|
||||
/// MapPins or clusters in the map's current view. All associated MapPins are parented to a child GameObject with
|
||||
/// the same name as this MapPinLayer.
|
||||
/// </summary>
|
||||
[HelpURL("https://github.com/Microsoft/MapsSDK-Unity/wiki/Attaching-GameObjects-to-the-map")]
|
||||
public class MapPinLayer : MapLayer
|
||||
{
|
||||
private MapPinSpatialIndex _mapPinSpatialIndex;
|
||||
|
||||
[SerializeField]
|
||||
private ObservableMapPinList _mapPins = new ObservableMapPinList();
|
||||
|
||||
/// <summary>
|
||||
/// All MapPins associated with this MapPinLayer.
|
||||
/// </summary>
|
||||
public ObservableList<MapPin> MapPins { get { return _mapPins; } }
|
||||
|
||||
/// <summary>
|
||||
/// The MapPins which are active.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<MapPin> ActiveMapPins => _activeMapPins;
|
||||
|
||||
/// <summary>
|
||||
/// The ClusterMapPins which are active.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<ClusterMapPin> ActiveClusterMapPins => _activeClusterMapPins;
|
||||
|
||||
/// <summary>
|
||||
/// True if the MapPins in this data source should be clustered. Note, if this is set to true, it is expected that a prefab
|
||||
/// has been provided to ClusterMapPinPrefab.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private bool _isClusteringEnabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// True if the MapPins in this data source should be clustered. Note, if this is set to true, it is expected that a prefab
|
||||
/// has been provided to ClusterMapPinPrefab.
|
||||
/// </summary>
|
||||
public bool IsClusteringEnabled
|
||||
{
|
||||
get => _isClusteringEnabled;
|
||||
set
|
||||
{
|
||||
if (_isClusteringEnabled != value)
|
||||
{
|
||||
_isClusteringEnabled = value;
|
||||
RebuildSpatialIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the number of pins in a spatial region exceed the ClusterThreshold, a single cluster MapPin will be rendered instead.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private int _clusterThreshold = 5;
|
||||
|
||||
/// <summary>
|
||||
/// If the number of pins in a spatial region exceed the ClusterThreshold, a single cluster MapPin will be rendered instead.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Modifying during ruintime will cause the MapPinLayer to rebuild, which may be expensive.
|
||||
/// </remarks>
|
||||
public int ClusterThreshold
|
||||
{
|
||||
get => _clusterThreshold;
|
||||
set
|
||||
{
|
||||
value = Math.Max(2, value);
|
||||
if (_clusterThreshold != value)
|
||||
{
|
||||
_clusterThreshold = value;
|
||||
RebuildSpatialIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The prefab to use for clusters.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private ClusterMapPin _clusterMapPinPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// The prefab to use for clusters.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Modifying during ruintime will cause the MapPinLayer to rebuild, which may be expensive.
|
||||
/// </remarks>
|
||||
public ClusterMapPin ClusterMapPinPrefab
|
||||
{
|
||||
get => _clusterMapPinPrefab;
|
||||
set
|
||||
{
|
||||
if (value != _clusterMapPinPrefab)
|
||||
{
|
||||
_clusterMapPinPrefab = value;
|
||||
RebuildSpatialIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject _containerGo;
|
||||
private readonly HashSet<MapPin> _mapPinsInViewThisFrame = new HashSet<MapPin>();
|
||||
private readonly HashSet<MapPin> _activeMapPins = new HashSet<MapPin>();
|
||||
private readonly HashSet<ClusterMapPin> _clusterMapPinsInViewThisFrame = new HashSet<ClusterMapPin>();
|
||||
private readonly HashSet<ClusterMapPin> _activeClusterMapPins = new HashSet<ClusterMapPin>();
|
||||
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
_clusterThreshold = Math.Max(_clusterThreshold, 2);
|
||||
}
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (string.IsNullOrEmpty(LayerName))
|
||||
{
|
||||
LayerName = "MapPinLayer";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Hook up ObservableList events.
|
||||
MapPins.ItemAdded += OnItemAdded;
|
||||
MapPins.RangeAdded += OnRangeAdded;
|
||||
MapPins.ItemRemoved += OnItemRemoved;
|
||||
MapPins.RangeRemoved += OnRangeRemoved;
|
||||
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
_containerGo.gameObject.SetActive(true);
|
||||
|
||||
EnsureSpatialIndexInitialized();
|
||||
|
||||
MapRenderer.AfterUpdate -= UpdateMapPinsInView;
|
||||
MapRenderer.AfterUpdate += UpdateMapPinsInView;
|
||||
MapRenderer.AfterOnDisable -= MapRendererDisabled;
|
||||
MapRenderer.AfterOnDisable += MapRendererDisabled;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_mapPinSpatialIndex.DestroyClusterMapPins();
|
||||
_activeClusterMapPins.Clear();
|
||||
|
||||
foreach (var mapPin in _activeMapPins)
|
||||
{
|
||||
mapPin.gameObject.SetActive(false);
|
||||
}
|
||||
_activeMapPins.Clear();
|
||||
|
||||
// Unregister events.
|
||||
MapRenderer.AfterUpdate -= UpdateMapPinsInView;
|
||||
MapRenderer.AfterOnDisable -= MapRendererDisabled;
|
||||
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
_containerGo.gameObject.SetActive(false);
|
||||
|
||||
// Unhook ObservableList events.
|
||||
MapPins.ItemAdded -= OnItemAdded;
|
||||
MapPins.RangeAdded -= OnRangeAdded;
|
||||
MapPins.ItemRemoved -= OnItemRemoved;
|
||||
MapPins.RangeRemoved -= OnRangeRemoved;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
MapPins.Clear();
|
||||
|
||||
Destroy(_containerGo);
|
||||
_containerGo = null;
|
||||
}
|
||||
|
||||
private void UpdateMapPinsInView(object sender, EventArgs args)
|
||||
{
|
||||
Profiler.BeginSample("UpdateMapPinsInView");
|
||||
|
||||
if (_mapPinSpatialIndex != null)
|
||||
{
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
_containerGo.gameObject.SetActive(true);
|
||||
|
||||
List<MapPin> mapPinsInView;
|
||||
List<ClusterMapPin> clusterMapPinsInView;
|
||||
if (MapRenderer.MapShape == MapShape.Block)
|
||||
{
|
||||
_mapPinSpatialIndex.GetPinsInView(
|
||||
MapRenderer.MercatorBoundingBox,
|
||||
MapRenderer.ZoomLevel,
|
||||
_clusterMapPinPrefab,
|
||||
_containerGo.transform,
|
||||
out mapPinsInView,
|
||||
out clusterMapPinsInView);
|
||||
}
|
||||
else // Cylinder.
|
||||
{
|
||||
_mapPinSpatialIndex.GetPinsInView(
|
||||
MapRenderer.MercatorBoundingBox,
|
||||
MapRenderer.MercatorBoundingCircle,
|
||||
MapRenderer.ZoomLevel,
|
||||
_clusterMapPinPrefab,
|
||||
_containerGo.transform,
|
||||
out mapPinsInView,
|
||||
out clusterMapPinsInView);
|
||||
}
|
||||
|
||||
// Update visible MapPins' position and other properties.
|
||||
{
|
||||
MapPin.SynchronizeLayers(mapPinsInView, MapRenderer);
|
||||
MapPin.SynchronizeLayers(clusterMapPinsInView, MapRenderer);
|
||||
MapRenderer.TrackAndPositionPinnables(mapPinsInView);
|
||||
MapRenderer.TrackAndPositionPinnables(clusterMapPinsInView);
|
||||
MapPin.UpdateScales(mapPinsInView, MapRenderer);
|
||||
MapPin.UpdateScales(clusterMapPinsInView, MapRenderer);
|
||||
}
|
||||
|
||||
// Disable MapPins that are no longer visible.
|
||||
{
|
||||
_mapPinsInViewThisFrame.Clear();
|
||||
_mapPinsInViewThisFrame.UnionWith(mapPinsInView);
|
||||
|
||||
foreach (var previousActiveMapPin in _activeMapPins)
|
||||
{
|
||||
if (previousActiveMapPin != null && !_mapPinsInViewThisFrame.Contains(previousActiveMapPin))
|
||||
{
|
||||
MapRenderer.UntrackPinnable(previousActiveMapPin);
|
||||
previousActiveMapPin.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
_clusterMapPinsInViewThisFrame.Clear();
|
||||
_clusterMapPinsInViewThisFrame.UnionWith(clusterMapPinsInView);
|
||||
|
||||
foreach (var previousActiveClusterMapPin in _activeClusterMapPins)
|
||||
{
|
||||
if (previousActiveClusterMapPin != null && !_clusterMapPinsInViewThisFrame.Contains(previousActiveClusterMapPin))
|
||||
{
|
||||
MapRenderer.UntrackPinnable(previousActiveClusterMapPin);
|
||||
previousActiveClusterMapPin.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out pins that have not been fully positioned, i.e. are still awaiting an elevation sample.
|
||||
// As a side effect, this will also enable any pins once any initial async op used to position them has completed.
|
||||
|
||||
_mapPinsInViewThisFrame.RemoveWhere(
|
||||
(MapPin mapPin) =>
|
||||
{
|
||||
mapPin.gameObject.SetActive(mapPin.HasBeenFullyPositioned);
|
||||
return !mapPin.HasBeenFullyPositioned;
|
||||
});
|
||||
|
||||
_clusterMapPinsInViewThisFrame.RemoveWhere(
|
||||
(ClusterMapPin clusterMapPin) =>
|
||||
{
|
||||
clusterMapPin.gameObject.SetActive(clusterMapPin.HasBeenFullyPositioned);
|
||||
return !clusterMapPin.HasBeenFullyPositioned;
|
||||
});
|
||||
|
||||
// Assign to the active properties.
|
||||
|
||||
_activeMapPins.Clear();
|
||||
_activeMapPins.UnionWith(_mapPinsInViewThisFrame);
|
||||
_mapPinsInViewThisFrame.Clear();
|
||||
|
||||
_activeClusterMapPins.Clear();
|
||||
_activeClusterMapPins.UnionWith(_clusterMapPinsInViewThisFrame);
|
||||
_clusterMapPinsInViewThisFrame.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private void MapRendererDisabled(object sender, EventArgs args)
|
||||
{
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
_containerGo.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnItemAdded(object sender, MapPin mapPin, int index)
|
||||
{
|
||||
_mapPinSpatialIndex.AddMapPin(mapPin);
|
||||
mapPin.gameObject.SetActive(false);
|
||||
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
mapPin.transform.SetParent(_containerGo.transform, false);
|
||||
}
|
||||
|
||||
private void OnRangeAdded(object sender, IEnumerable<MapPin> mapPins, int index)
|
||||
{
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
_mapPinSpatialIndex.AddMapPin(mapPin);
|
||||
}
|
||||
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
mapPin.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
EnsureContainerGameObjectIsCreated();
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
mapPin.transform.SetParent(_containerGo.transform, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemRemoved(object sender, MapPin mapPin, int index)
|
||||
{
|
||||
_mapPinSpatialIndex.RemoveMapPin(mapPin);
|
||||
}
|
||||
|
||||
private void OnRangeRemoved(object sender, IEnumerable<MapPin> mapPins, int index)
|
||||
{
|
||||
foreach (var mapPin in mapPins)
|
||||
{
|
||||
_mapPinSpatialIndex.RemoveMapPin(mapPin);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureContainerGameObjectIsCreated()
|
||||
{
|
||||
if (_containerGo == null)
|
||||
{
|
||||
// Create a GO to hold the pins if one doesn't already exist.
|
||||
var mapPinContainerName = string.IsNullOrEmpty(LayerName) ? "Unnamed MapPinLayer Container" : LayerName + " Container";
|
||||
_containerGo = new GameObject(mapPinContainerName);
|
||||
_containerGo.transform.SetParent(transform, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSpatialIndexInitialized()
|
||||
{
|
||||
if (_mapPinSpatialIndex != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_mapPinSpatialIndex = new MapPinSpatialIndex(_isClusteringEnabled, _clusterThreshold);
|
||||
|
||||
// If there was already been MapPins added to the data source, add them to the spatial index as well.
|
||||
{
|
||||
foreach (var mapPin in MapPins)
|
||||
{
|
||||
_mapPinSpatialIndex.AddMapPin(mapPin);
|
||||
}
|
||||
|
||||
foreach (var mapPin in MapPins)
|
||||
{
|
||||
mapPin.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
foreach (var mapPin in MapPins)
|
||||
{
|
||||
mapPin.transform.SetParent(_containerGo.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RebuildSpatialIndex()
|
||||
{
|
||||
if (_mapPinSpatialIndex != null)
|
||||
{
|
||||
_mapPinSpatialIndex.DestroyClusterMapPins();
|
||||
_mapPinSpatialIndex = null;
|
||||
}
|
||||
|
||||
EnsureSpatialIndexInitialized();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d8a6459eb3010b4f9751de03dca135a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,448 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Geospatial;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if DEBUG
|
||||
using UnityEngine.Assertions;
|
||||
#endif
|
||||
|
||||
internal class MapPinSpatialIndex
|
||||
{
|
||||
private class TileData
|
||||
{
|
||||
internal int MapPinCount;
|
||||
internal double TotalLat;
|
||||
internal double TotalLon;
|
||||
internal ClusterMapPin ClusterMapPin;
|
||||
|
||||
// If non-null, the (unclustered) MapPins for this tile. If null, a cluster exists in this tile and MapPinCount should be
|
||||
// greater than the ClusterThreshold.
|
||||
internal List<MapPin> MapPins;
|
||||
|
||||
internal bool IsClustered()
|
||||
{
|
||||
// If the MapPins are null, then we are in clustering mode.
|
||||
return MapPins == null;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int ClusterThreshold;
|
||||
|
||||
private readonly Dictionary<long, TileData>[] _tiledSpatialIndex;
|
||||
|
||||
private readonly TileLevelOfDetail _maxLod = new TileLevelOfDetail(18);
|
||||
|
||||
private readonly bool _isClusteringEnabled = false;
|
||||
|
||||
private readonly List<ClusterMapPin> _clusterMapPins = new List<ClusterMapPin>();
|
||||
|
||||
internal MapPinSpatialIndex(bool isClusteringEnabled, int clusterThreshold = 5)
|
||||
{
|
||||
_isClusteringEnabled = isClusteringEnabled;
|
||||
|
||||
if (clusterThreshold < 2)
|
||||
{
|
||||
throw new ArgumentException(nameof(clusterThreshold), "clusterThreshold should be greater than 1.");
|
||||
}
|
||||
|
||||
ClusterThreshold = clusterThreshold;
|
||||
|
||||
// Initialize the spatial index. For each LOD, create a dictionary that maps TileIds to TileData.
|
||||
_tiledSpatialIndex = new Dictionary<long, TileData>[_maxLod.Value];
|
||||
for (var i = 0; i < _tiledSpatialIndex.Length; i++)
|
||||
{
|
||||
_tiledSpatialIndex[i] = new Dictionary<long, TileData>();
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddMapPin(MapPin mapPinToAdd)
|
||||
{
|
||||
mapPinToAdd.LocationChanged += MapPinLocationChanged;
|
||||
var latLon = mapPinToAdd.Location;
|
||||
|
||||
// Insert into max LOD.
|
||||
TileId maxLodTileId;
|
||||
{
|
||||
var lodIndex = _maxLod.Value - 1;
|
||||
maxLodTileId = new TileId(latLon, _maxLod);
|
||||
if (!_tiledSpatialIndex[lodIndex].TryGetValue(maxLodTileId.Value, out TileData maxLodTileData))
|
||||
{
|
||||
maxLodTileData =
|
||||
new TileData
|
||||
{
|
||||
MapPins = new List<MapPin> { mapPinToAdd }
|
||||
};
|
||||
_tiledSpatialIndex[lodIndex].Add(maxLodTileId.Value, maxLodTileData);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxLodTileData.MapPins.Add(mapPinToAdd);
|
||||
}
|
||||
|
||||
maxLodTileData.MapPinCount++;
|
||||
maxLodTileData.TotalLat += latLon.LatitudeInDegrees;
|
||||
maxLodTileData.TotalLon += latLon.LongitudeInDegrees;
|
||||
}
|
||||
|
||||
// Bubble up tile into parent LODs.
|
||||
maxLodTileId.TryGetParent(out var parentTileId);
|
||||
var parentLodIndex = parentTileId.CalculateLevelOfDetail().Value - 1;
|
||||
while (parentLodIndex >= 0)
|
||||
{
|
||||
if (!_tiledSpatialIndex[parentLodIndex].TryGetValue(parentTileId.Value, out var parentTileData))
|
||||
{
|
||||
// This is a new tile. Create and add a new TileData for this LOD.
|
||||
parentTileData =
|
||||
new TileData
|
||||
{
|
||||
MapPins = new List<MapPin> { mapPinToAdd },
|
||||
MapPinCount = 1,
|
||||
TotalLat = latLon.LatitudeInDegrees,
|
||||
TotalLon = latLon.LongitudeInDegrees
|
||||
};
|
||||
_tiledSpatialIndex[parentLodIndex].Add(parentTileId.Value, parentTileData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have a tile with points or clusters.
|
||||
|
||||
// In either case, track the LatLong.
|
||||
parentTileData.MapPinCount++;
|
||||
parentTileData.TotalLat += latLon.LatitudeInDegrees;
|
||||
parentTileData.TotalLon += latLon.LongitudeInDegrees;
|
||||
|
||||
var isCluster = _isClusteringEnabled && parentTileData.MapPinCount > ClusterThreshold;
|
||||
if (isCluster)
|
||||
{
|
||||
parentTileData.MapPins = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentTileData.MapPins.Add(mapPinToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
parentLodIndex--;
|
||||
parentTileId.TryGetParent(out parentTileId);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveMapPin(MapPin mapPinToRemove)
|
||||
{
|
||||
RemoveMapPin(mapPinToRemove, mapPinToRemove.Location);
|
||||
}
|
||||
|
||||
private void RemoveMapPin(MapPin mapPinToRemove, LatLon locationOverride)
|
||||
{
|
||||
// Find the MapPin in the spatial index at the max LOD.
|
||||
var lodIndex = _maxLod.Value - 1;
|
||||
var maxLodTileId = new TileId(locationOverride, _maxLod);
|
||||
var indexChanged = false;
|
||||
if (_tiledSpatialIndex[lodIndex].TryGetValue(maxLodTileId.Value, out TileData maxLodTileData))
|
||||
{
|
||||
if (maxLodTileData.MapPins.Remove(mapPinToRemove))
|
||||
{
|
||||
indexChanged = true;
|
||||
|
||||
mapPinToRemove.LocationChanged -= MapPinLocationChanged;
|
||||
|
||||
maxLodTileData.MapPinCount--;
|
||||
if (maxLodTileData.MapPinCount == 0)
|
||||
{
|
||||
// Remove tile if now empty.
|
||||
_tiledSpatialIndex[lodIndex].Remove(maxLodTileId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxLodTileData.TotalLat -= locationOverride.LatitudeInDegrees;
|
||||
maxLodTileData.TotalLon -= locationOverride.LongitudeInDegrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bubble up change to parent tiles.
|
||||
if (indexChanged)
|
||||
{
|
||||
maxLodTileId.TryGetParent(out var parentTileId);
|
||||
var parentLodIndex = parentTileId.CalculateLevelOfDetail().Value - 1;
|
||||
while (parentLodIndex >= 0)
|
||||
{
|
||||
_tiledSpatialIndex[parentLodIndex].TryGetValue(parentTileId.Value, out var parentTileData);
|
||||
parentTileData.MapPinCount--;
|
||||
|
||||
if (parentTileData.MapPinCount == 0)
|
||||
{
|
||||
// No more pins left in this tile. Remove it from the spatial index.
|
||||
_tiledSpatialIndex[parentLodIndex].Remove(parentTileId.Value);
|
||||
|
||||
#if DEBUG
|
||||
// It shouldn't be clustered.
|
||||
Assert.IsTrue(parentTileData.ClusterMapPin == null);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
parentTileData.TotalLat -= locationOverride.LatitudeInDegrees;
|
||||
parentTileData.TotalLon -= locationOverride.LongitudeInDegrees;
|
||||
|
||||
var isCluster = _isClusteringEnabled && parentTileData.MapPinCount > ClusterThreshold;
|
||||
if (!isCluster)
|
||||
{
|
||||
if (parentTileData.MapPins != null)
|
||||
{
|
||||
parentTileData.MapPins.Remove(mapPinToRemove);
|
||||
}
|
||||
else
|
||||
{
|
||||
// When we remove the MapPin, this tile will fall under the cluster threshold so we will need to repopulate
|
||||
// the children list.
|
||||
parentTileData.MapPins = GatherChildren(parentTileId);
|
||||
|
||||
// Destroy the ClusterMapPin game object if it exists.
|
||||
if (parentTileData.ClusterMapPin != null)
|
||||
{
|
||||
_clusterMapPins.Remove(parentTileData.ClusterMapPin);
|
||||
UnityEngine.Object.Destroy(parentTileData.ClusterMapPin.gameObject);
|
||||
parentTileData.ClusterMapPin = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parentLodIndex--;
|
||||
parentTileId.TryGetParent(out parentTileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pins in the specified bounding box.
|
||||
/// </summary>
|
||||
internal void GetPinsInView(
|
||||
MercatorBoundingBox mercatorBox,
|
||||
float levelOfDetail,
|
||||
ClusterMapPin clusterMapPinPrefab,
|
||||
Transform parentTransform,
|
||||
out List<MapPin> mapPins,
|
||||
out List<ClusterMapPin> clusterMapPins)
|
||||
{
|
||||
var box = mercatorBox.ToGeoBoundingBox();
|
||||
var lod = (short)Mathf.Min(Mathf.Round(levelOfDetail), _maxLod.Value);
|
||||
var tileLod = new TileLevelOfDetail(lod);
|
||||
var tileLodData = _tiledSpatialIndex[lod - 1];
|
||||
var tiles = TileOperations.GetCoveredTileIds(box, tileLod);
|
||||
mapPins = new List<MapPin>();
|
||||
clusterMapPins = new List<ClusterMapPin>();
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var tileBounds = tile.ToMercatorBoundingBox();
|
||||
var isTileCompletelyInsideMap = mercatorBox.Contains(tileBounds);
|
||||
|
||||
if (tileLodData.TryGetValue(tile.Value, out var tileData))
|
||||
{
|
||||
if (tileData.IsClustered())
|
||||
{
|
||||
var latLon = new LatLon(tileData.TotalLat / tileData.MapPinCount, tileData.TotalLon / tileData.MapPinCount);
|
||||
if (isTileCompletelyInsideMap || box.Intersects(latLon))
|
||||
{
|
||||
// Use the ClusterMapPin.
|
||||
if (tileData.ClusterMapPin == null)
|
||||
{
|
||||
// Deactivate the GO to start with. It will get activated once elevation has been sampled and it's in view.
|
||||
clusterMapPinPrefab.gameObject.SetActive(false);
|
||||
var newClusterMapPin = UnityEngine.Object.Instantiate(clusterMapPinPrefab);
|
||||
|
||||
if (parentTransform != null)
|
||||
{
|
||||
newClusterMapPin.transform.SetParent(parentTransform, false);
|
||||
}
|
||||
newClusterMapPin.LevelOfDetail = tileLod.Value;
|
||||
tileData.ClusterMapPin = newClusterMapPin;
|
||||
|
||||
_clusterMapPins.Add(newClusterMapPin);
|
||||
}
|
||||
|
||||
tileData.ClusterMapPin.Size = tileData.MapPinCount;
|
||||
tileData.ClusterMapPin.Location = new LatLon(latLon.LatitudeInDegrees, latLon.LongitudeInDegrees);
|
||||
clusterMapPins.Add(tileData.ClusterMapPin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add all of the MapPins in this tile to the list.
|
||||
if (isTileCompletelyInsideMap)
|
||||
{
|
||||
foreach (var mapPin in tileData.MapPins)
|
||||
{
|
||||
mapPins.Add(mapPin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var mapPin in tileData.MapPins)
|
||||
{
|
||||
if (box.Intersects(mapPin.Location))
|
||||
{
|
||||
mapPins.Add(mapPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pins in the specified circular area.
|
||||
/// </summary>
|
||||
internal void GetPinsInView(
|
||||
MercatorBoundingBox mercatorBox,
|
||||
MercatorBoundingCircle mercatorBoundingCircle,
|
||||
float levelOfDetail,
|
||||
ClusterMapPin clusterMapPinPrefab,
|
||||
Transform parentTransform,
|
||||
out List<MapPin> mapPins,
|
||||
out List<ClusterMapPin> clusterMapPins)
|
||||
{
|
||||
var lod = (short)Mathf.Min(Mathf.Round(levelOfDetail), _maxLod.Value);
|
||||
var tileLod = new TileLevelOfDetail(lod);
|
||||
var tileLodData = _tiledSpatialIndex[lod - 1];
|
||||
var tiles = TileOperations.GetCoveredTileIds(mercatorBox, tileLod);
|
||||
mapPins = new List<MapPin>();
|
||||
clusterMapPins = new List<ClusterMapPin>();
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var tileBounds = tile.ToMercatorBoundingBox();
|
||||
var isTileCompletelyInsideMap = mercatorBoundingCircle.Contains(tileBounds);
|
||||
|
||||
if (tileLodData.TryGetValue(tile.Value, out var tileData))
|
||||
{
|
||||
if (tileData.IsClustered())
|
||||
{
|
||||
var latLon = new LatLon(tileData.TotalLat / tileData.MapPinCount, tileData.TotalLon / tileData.MapPinCount);
|
||||
var mercatorCoordinate = latLon.ToMercatorCoordinate();
|
||||
if (isTileCompletelyInsideMap || mercatorBoundingCircle.Intersects(mercatorCoordinate))
|
||||
{
|
||||
// Use the ClusterMapPin.
|
||||
if (tileData.ClusterMapPin == null)
|
||||
{
|
||||
// Deactivate the GO to start with. It will get activated once elevation has been sampled and it's in view.
|
||||
clusterMapPinPrefab.gameObject.SetActive(false);
|
||||
var newClusterMapPin = UnityEngine.Object.Instantiate(clusterMapPinPrefab);
|
||||
|
||||
if (parentTransform != null)
|
||||
{
|
||||
newClusterMapPin.transform.SetParent(parentTransform, false);
|
||||
}
|
||||
newClusterMapPin.LevelOfDetail = tileLod.Value;
|
||||
tileData.ClusterMapPin = newClusterMapPin;
|
||||
|
||||
_clusterMapPins.Add(newClusterMapPin);
|
||||
}
|
||||
|
||||
tileData.ClusterMapPin.Size = tileData.MapPinCount;
|
||||
tileData.ClusterMapPin.Location = new LatLon(latLon.LatitudeInDegrees, latLon.LongitudeInDegrees);
|
||||
clusterMapPins.Add(tileData.ClusterMapPin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add all of the MapPins in this tile to the list.
|
||||
if (isTileCompletelyInsideMap)
|
||||
{
|
||||
foreach (var mapPin in tileData.MapPins)
|
||||
{
|
||||
mapPins.Add(mapPin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var mapPin in tileData.MapPins)
|
||||
{
|
||||
if (mercatorBoundingCircle.Intersects(mapPin.MercatorCoordinate))
|
||||
{
|
||||
mapPins.Add(mapPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all ClusterMapPins associated with this index. When pins in view are requested in the future,
|
||||
/// the ClusterMapPin will be recreated as needed.
|
||||
/// </summary>
|
||||
internal void DestroyClusterMapPins()
|
||||
{
|
||||
foreach (var clusterMapPin in _clusterMapPins)
|
||||
{
|
||||
if (clusterMapPin != null)
|
||||
{
|
||||
UnityEngine.Object.Destroy(clusterMapPin.gameObject);
|
||||
}
|
||||
}
|
||||
_clusterMapPins.Clear();
|
||||
}
|
||||
|
||||
private void MapPinLocationChanged(MapPin mapPinToUpdate, LatLon oldLocation)
|
||||
{
|
||||
RemoveMapPin(mapPinToUpdate, oldLocation);
|
||||
AddMapPin(mapPinToUpdate);
|
||||
}
|
||||
|
||||
private List<MapPin> GatherChildren(TileId tileId)
|
||||
{
|
||||
var result = new List<MapPin>();
|
||||
var tempChildrenTileIds = new TileId[4];
|
||||
var tilesToCheck = new Queue<TileId>();
|
||||
tilesToCheck.Enqueue(tileId);
|
||||
|
||||
while (tilesToCheck.Count > 0)
|
||||
{
|
||||
var tileToCheck = tilesToCheck.Dequeue();
|
||||
var lod = tileToCheck.CalculateLevelOfDetail();
|
||||
var lodIndex = lod.Value - 1;
|
||||
if (_tiledSpatialIndex[lodIndex].TryGetValue(tileToCheck.Value, out var tileData))
|
||||
{
|
||||
if (tileData.MapPins != null)
|
||||
{
|
||||
#if DEBUG
|
||||
if (_isClusteringEnabled && lod != _maxLod)
|
||||
{
|
||||
Assert.IsTrue(tileData.MapPinCount <= ClusterThreshold);
|
||||
}
|
||||
#endif
|
||||
|
||||
result.AddRange(tileData.MapPins);
|
||||
}
|
||||
else if (lodIndex < (_maxLod.Value - 1))
|
||||
{
|
||||
#if DEBUG
|
||||
if (_isClusteringEnabled)
|
||||
{
|
||||
Assert.IsTrue(tileData.MapPinCount <= ClusterThreshold);
|
||||
}
|
||||
Assert.IsTrue(lodIndex < _maxLod.Value);
|
||||
#endif
|
||||
|
||||
tileToCheck.GetChildren(tempChildrenTileIds);
|
||||
foreach (var childTile in tempChildrenTileIds)
|
||||
{
|
||||
tilesToCheck.Enqueue(childTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 413fb67fbe5b52b4c86606f4fd7496bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// List of MapPins with callbacks for item addition and removal. Also, this list can be serialized.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ObservableMapPinList : ObservableList<MapPin>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a8e9f77ae9789a44ea91a49bc04a1ffc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,449 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
/// <summary>
|
||||
/// Manages streaming and rendering of map data.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
[DisallowMultipleComponent]
|
||||
[HelpURL("https://github.com/Microsoft/MapsSDK-Unity/wiki/Configuring-the-MapRenderer")]
|
||||
public sealed class MapRenderer : MapRendererBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of collider that the map is using.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private MapColliderType _mapColliderType = MapColliderType.BaseOnly;
|
||||
|
||||
/// <summary>
|
||||
/// The type of collider that the map is using.
|
||||
/// </summary>
|
||||
public MapColliderType MapColliderType { get => _mapColliderType; set => _mapColliderType = value; }
|
||||
private MapColliderType _previousMapColliderType = MapColliderType.BaseOnly;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Collider"/> used for the map. The dimensions are synchronized to match the map's layout.
|
||||
/// Null value if no <see cref="Collider"/> is active.
|
||||
/// </summary>
|
||||
public Collider MapCollider => _mapCollider;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Collider"/> used for the map. The dimensions are synchronized to match the map's layout.
|
||||
/// Null value if no <see cref="Collider"/> is active.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Collider _mapCollider = null;
|
||||
|
||||
/// <summary>
|
||||
/// The collider used for all map shape types although in the future may just apply to box mode.
|
||||
/// </summary>
|
||||
private BoxCollider _mapBoxCollider = null;
|
||||
|
||||
private IMapSceneAnimationController _activeMapSceneAnimationController;
|
||||
|
||||
// Manages MapPins attached directly as children to the MapRenderer. Behaves like a MapPinLayer, but no clustering or indexing.
|
||||
private bool _checkChildMapPins = true;
|
||||
private readonly HashSet<MapPin> _mapPinChildrenSet = new HashSet<MapPin>();
|
||||
private readonly List<MapPin> _lastMapPinsInView = new List<MapPin>();
|
||||
private readonly List<MapPin> _mapPinsInView = new List<MapPin>();
|
||||
private readonly HashSet<MapPin> _currentChildrenMapPins = new HashSet<MapPin>();
|
||||
private readonly List<MapPin> _mapPinChildrenToRemove = new List<MapPin>();
|
||||
|
||||
/// <summary>
|
||||
/// Called after the <see cref="MapRenderer"/> has exected Update().
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use this callback when performing operations to a <see cref="MapLayer"/> that depend on various map properties.
|
||||
/// At this point in the lifecycle, <see cref="MapRendererBase.Center"/>, <see cref="MapRendererBase.ZoomLevel"/>,
|
||||
/// and other properties related to the position of the map will reflect the values used for this frame,
|
||||
/// i.e. it is after any animations have ran and the properties used to position and render the map content in this frame
|
||||
/// have already been determined.
|
||||
/// </remarks>
|
||||
public event EventHandler AfterUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="MapRenderer"/>'s view to reflect the new <see cref="MapScene"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A yieldable object is returned that can be used to wait for the end of the animation in a coroutine.
|
||||
/// </returns>
|
||||
public WaitForMapSceneAnimation SetMapScene(
|
||||
MapScene mapScene,
|
||||
MapSceneAnimationKind mapSceneAnimationKind = MapSceneAnimationKind.Bow,
|
||||
float animationTimeScale = 1.0f)
|
||||
{
|
||||
return
|
||||
SetMapScene(
|
||||
mapScene,
|
||||
new MapSceneAnimationController(),
|
||||
mapSceneAnimationKind,
|
||||
animationTimeScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="MapRenderer"/>'s view to reflect the new <see cref="MapScene"/>
|
||||
/// using the specified <see cref="IMapSceneAnimationController"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A yieldable object is returned that can be used to wait for the end of the animation in a coroutine.
|
||||
/// </returns>
|
||||
public WaitForMapSceneAnimation SetMapScene(
|
||||
MapScene mapScene,
|
||||
IMapSceneAnimationController mapSceneAnimationController,
|
||||
MapSceneAnimationKind mapSceneAnimationKind = MapSceneAnimationKind.Bow,
|
||||
float animationTimeScale = 1.0f)
|
||||
{
|
||||
// If we were in the middle of a previous animation, make sure it has yielded and then reset it.
|
||||
CancelAnimation();
|
||||
|
||||
mapScene.GetLocationAndZoomLevel(out var finalCenter, out var finalZoomLevel);
|
||||
|
||||
animationTimeScale = Mathf.Max(0, animationTimeScale);
|
||||
|
||||
if (mapSceneAnimationKind == MapSceneAnimationKind.None || animationTimeScale == 0.0)
|
||||
{
|
||||
// Snap the view.
|
||||
ZoomLevel = (float)finalZoomLevel;
|
||||
Center = finalCenter;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// Otherwise, setup an animation.
|
||||
mapSceneAnimationController.Initialize(this, mapScene, animationTimeScale, mapSceneAnimationKind);
|
||||
_activeMapSceneAnimationController = mapSceneAnimationController;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Failed to initialize the IMapSceneAnimationController.\r\n" + e, gameObject);
|
||||
_activeMapSceneAnimationController = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a yield instruction from the animation controller itself (if we have one). Otherwise, we were setting a scene
|
||||
// without animation, so just return a completed yield instruction.
|
||||
return
|
||||
_activeMapSceneAnimationController == null ?
|
||||
new WaitForMapSceneAnimation(true /* isComplete */) :
|
||||
_activeMapSceneAnimationController.YieldInstruction;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool RunAnimation(out LatLon newCenter, out float newZoomLevel)
|
||||
{
|
||||
if (_activeMapSceneAnimationController != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_activeMapSceneAnimationController.UpdateAnimation(ZoomLevel, Center, out newZoomLevel, out newCenter))
|
||||
{
|
||||
// Animation is complete.
|
||||
_activeMapSceneAnimationController = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Failed to update animation.\r\n" + e, gameObject);
|
||||
_activeMapSceneAnimationController = null;
|
||||
}
|
||||
}
|
||||
|
||||
newCenter = new LatLon();
|
||||
newZoomLevel = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void CancelAnimation()
|
||||
{
|
||||
if (_activeMapSceneAnimationController == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_activeMapSceneAnimationController.YieldInstruction.SetComplete();
|
||||
_activeMapSceneAnimationController = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OneTimeSetup(int lastVersion)
|
||||
{
|
||||
// Runs one-time setup to add sibling components which are present by default but can be removed later.
|
||||
// The logic here also takes into account the "version" of the Maps SDK as some setup should only
|
||||
// be ran when upgrading from one version to a newer version. See MapRenderer.Version docs for mapping of
|
||||
// each version integer to Maps SDK version.
|
||||
|
||||
if (lastVersion < 1)
|
||||
{
|
||||
// Add a MapCopyrightLayer by default.
|
||||
var existingMapCopyrightLayer = GetComponent<MapCopyrightLayer>();
|
||||
if (existingMapCopyrightLayer == null)
|
||||
{
|
||||
gameObject.AddComponent<MapCopyrightLayer>();
|
||||
}
|
||||
|
||||
// Initialize default layers.
|
||||
if (TextureTileLayers.Count == 0)
|
||||
{
|
||||
gameObject.AddComponent<DefaultTextureTileLayer>();
|
||||
}
|
||||
}
|
||||
|
||||
if (lastVersion < 2)
|
||||
{
|
||||
if (ElevationTileLayers.Count == 0)
|
||||
{
|
||||
// Adds the DefaultElevationLayer to the now Serialized list of elevation layers.
|
||||
gameObject.AddComponent<DefaultElevationTileLayer>();
|
||||
}
|
||||
}
|
||||
|
||||
if (lastVersion < 3)
|
||||
{
|
||||
// Grab a reference to the first box collider that is found (if any).
|
||||
var existingColliders = GetComponents<BoxCollider>();
|
||||
if (existingColliders != null)
|
||||
{
|
||||
foreach (var collider in existingColliders)
|
||||
{
|
||||
_mapCollider = collider;
|
||||
_mapBoxCollider = collider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_checkChildMapPins = true;
|
||||
|
||||
// Create a MapDataCache if it doesn't exist.
|
||||
if (FindObjectOfType<MapDataCacheBase>() == null)
|
||||
{
|
||||
gameObject.AddComponent<MapDataCache>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_checkChildMapPins = true;
|
||||
|
||||
// Create a MapDataCache if it doesn't exist.
|
||||
if (FindObjectOfType<MapDataCacheBase>() == null)
|
||||
{
|
||||
gameObject.AddComponent<MapDataCache>();
|
||||
}
|
||||
|
||||
if (_mapCollider != null)
|
||||
{
|
||||
_mapCollider.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTransformChildrenChanged()
|
||||
{
|
||||
_checkChildMapPins = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
UpdateChildrenMapPins();
|
||||
|
||||
UpdateMapCollider();
|
||||
|
||||
{
|
||||
Profiler.BeginSample("AfterUpdate");
|
||||
AfterUpdate?.Invoke(this, EventArgs.Empty);
|
||||
Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
foreach (var childMapPin in _lastMapPinsInView)
|
||||
{
|
||||
childMapPin.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (_mapCollider != null)
|
||||
{
|
||||
_mapCollider.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMapCollider()
|
||||
{
|
||||
if (_mapColliderType != MapColliderType.None)
|
||||
{
|
||||
if (_mapCollider == null)
|
||||
{
|
||||
_mapBoxCollider = gameObject.AddComponent<BoxCollider>();
|
||||
_mapCollider = _mapBoxCollider;
|
||||
}
|
||||
else if (_mapBoxCollider == null)
|
||||
{
|
||||
// The box collider field is just used to prevent recasting _mapCollider every frame.
|
||||
// Since it's not serialized it may be null even if _mapCollider isn't.
|
||||
_mapBoxCollider = _mapCollider as BoxCollider;
|
||||
}
|
||||
|
||||
_mapCollider.enabled = true;
|
||||
|
||||
var colliderHeight = (_mapColliderType == MapColliderType.BaseOnly) ? LocalMapBaseHeight : LocalMapHeight;
|
||||
_mapBoxCollider.center = new Vector3(0, colliderHeight / 2, 0);
|
||||
if (MapShape == MapShape.Block)
|
||||
{
|
||||
_mapBoxCollider.size = new Vector3(LocalMapDimension.x, colliderHeight, LocalMapDimension.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mapBoxCollider.size = new Vector3(LocalMapRadius * 2.0f, colliderHeight, LocalMapRadius * 2.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_previousMapColliderType != MapColliderType.None && _mapCollider != null)
|
||||
{
|
||||
DestroyImmediate(_mapCollider);
|
||||
_mapCollider = null;
|
||||
_mapBoxCollider = null;
|
||||
}
|
||||
}
|
||||
|
||||
_previousMapColliderType = _mapColliderType;
|
||||
}
|
||||
|
||||
private void UpdateChildrenMapPins()
|
||||
{
|
||||
Profiler.BeginSample("UpdateChildrenMapPins");
|
||||
|
||||
_mapPinsInView.Clear();
|
||||
|
||||
// Get all the direct descendant MapPins of this GameObject that are in view.
|
||||
{
|
||||
if (_checkChildMapPins)
|
||||
{
|
||||
_currentChildrenMapPins.Clear();
|
||||
|
||||
var currentChildrenMapPins = GetComponentsInChildren<MapPin>(true);
|
||||
foreach (var currentChildMapPin in currentChildrenMapPins)
|
||||
{
|
||||
if (currentChildMapPin.transform.parent == transform)
|
||||
{
|
||||
_currentChildrenMapPins.Add(currentChildMapPin);
|
||||
}
|
||||
}
|
||||
|
||||
// Add any new MapPin children.
|
||||
foreach (var mapPin in _currentChildrenMapPins)
|
||||
{
|
||||
if (_mapPinChildrenSet.Add(mapPin))
|
||||
{
|
||||
// This is a new MapPin. Deactivate until it's position has been calculated.
|
||||
mapPin.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any MapPins that are no longer children or have been disabled.
|
||||
{
|
||||
_mapPinChildrenToRemove.Clear();
|
||||
foreach (var existingChildMapPin in _mapPinChildrenSet)
|
||||
{
|
||||
if (!_currentChildrenMapPins.Contains(existingChildMapPin))
|
||||
{
|
||||
_mapPinChildrenToRemove.Add(existingChildMapPin);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mapPinChildToRemove in _mapPinChildrenToRemove)
|
||||
{
|
||||
_mapPinChildrenSet.Remove(mapPinChildToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
_currentChildrenMapPins.Clear();
|
||||
_mapPinChildrenToRemove.Clear();
|
||||
_checkChildMapPins = false;
|
||||
}
|
||||
|
||||
// Get the MapPins in view.
|
||||
if (_mapPinChildrenSet.Count > 0)
|
||||
{
|
||||
if (MapShape == MapShape.Block)
|
||||
{
|
||||
var mercatorBoundingBox = MercatorBoundingBox;
|
||||
foreach (var mapPin in _mapPinChildrenSet)
|
||||
{
|
||||
if (mercatorBoundingBox.Intersects(mapPin.Location))
|
||||
{
|
||||
_mapPinsInView.Add(mapPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Cylinder
|
||||
{
|
||||
var mercatorBoundingCircle = MercatorBoundingCircle;
|
||||
foreach (var mapPin in _mapPinChildrenSet)
|
||||
{
|
||||
if (mercatorBoundingCircle.Intersects(mapPin.MercatorCoordinate))
|
||||
{
|
||||
_mapPinsInView.Add(mapPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrackAndPositionPinnables(_mapPinsInView);
|
||||
|
||||
// Disable any MapPins that were in the last view but is not the current view.
|
||||
{
|
||||
foreach (var lastMapPinInView in _lastMapPinsInView)
|
||||
{
|
||||
if (lastMapPinInView != null && !_mapPinsInView.Contains(lastMapPinInView))
|
||||
{
|
||||
UntrackPinnable(lastMapPinInView);
|
||||
lastMapPinInView.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
_lastMapPinsInView.Clear();
|
||||
_lastMapPinsInView.AddRange(_mapPinsInView);
|
||||
}
|
||||
|
||||
MapPin.SynchronizeLayers(_mapPinsInView, this);
|
||||
MapPin.UpdateScales(_mapPinsInView, this);
|
||||
|
||||
// Ensure the MapPins that have had their positions computed have been enabled.
|
||||
foreach (var mapPinInView in _mapPinsInView)
|
||||
{
|
||||
mapPinInView.gameObject.SetActive(mapPinInView.HasBeenFullyPositioned && mapPinInView.enabled);
|
||||
}
|
||||
|
||||
Profiler.EndSample();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1cf6985fc3c122a4193d16fdcfb59784
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,166 +1,165 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial;
|
||||
using Microsoft.Geospatial.VectorMath;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Helpers to transform between Unity's world and local spaces to the geographic coordinate system of the <see cref="MapRenderer"/>.
|
||||
/// </summary>
|
||||
public static class MapRendererTransformExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The WGS84 ellipsoid circumference measured in meters.
|
||||
/// </summary>
|
||||
public const double EquatorialCircumferenceInWgs84Meters = 40075016.685578488;
|
||||
|
||||
/// <summary>
|
||||
/// Constat for 2 * Math.PI.
|
||||
/// </summary>
|
||||
public const double TwoPi = 2 * Math.PI;
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in the <see cref="MapRenderer"/>'s local space to a Mercator position.
|
||||
/// </summary>
|
||||
public static Vector2D TransformLocalPointToMercator(this MapRenderer mapRenderer, Vector3 pointInLocalSpace)
|
||||
{
|
||||
var deltaFromMapCenterToPointInMercatorSpace = TransformLocalDirectionToMercator(mapRenderer, pointInLocalSpace);
|
||||
return mapRenderer.Center.ToMercatorPosition() + deltaFromMapCenterToPointInMercatorSpace;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in the <see cref="MapRenderer"/>'s local space to a Mercator position. Includes the altitude
|
||||
/// measured as meters from the WGS84 ellipsoid.
|
||||
/// </summary>
|
||||
public static Vector2D TransformLocalPointToMercatorWithAltitude(
|
||||
this MapRenderer mapRenderer,
|
||||
Vector3 pointInLocalSpace,
|
||||
out double altitudeInMeters,
|
||||
out double mercatorScale)
|
||||
{
|
||||
var mercatorPosition = TransformLocalPointToMercator(mapRenderer, pointInLocalSpace);
|
||||
|
||||
mercatorScale = Math.Cosh(TwoPi * mercatorPosition.Y);
|
||||
var equatorialCircumferenceInLocalSpace = Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var elevationScale = (EquatorialCircumferenceInWgs84Meters / equatorialCircumferenceInLocalSpace) / mercatorScale;
|
||||
altitudeInMeters = (pointInLocalSpace.y - mapRenderer.LocalMapHeight) * elevationScale + mapRenderer.ElevationBaseline;
|
||||
|
||||
return mercatorPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// </summary>
|
||||
public static Vector2D TransformLocalDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInLocalSpace)
|
||||
{
|
||||
return TransformLocalDirectionToMercator(directionInLocalSpace, mapRenderer.ZoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// Uses the specified zoom level rather than the <see cref="MapRenderer"/>'s zoom level for the transformation.
|
||||
/// </summary>
|
||||
public static Vector2D TransformLocalDirectionToMercator(Vector3 directionInLocalSpace, double zoomLevel)
|
||||
{
|
||||
var mercatorMapSizeInLocalSpace = Math.Pow(2, zoomLevel - 1);
|
||||
var directionInMercator = new Vector2D(directionInLocalSpace.x, directionInLocalSpace.z) / mercatorMapSizeInLocalSpace;
|
||||
return directionInMercator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// </summary>
|
||||
public static Vector2D TransformWorldDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInWorldSpace)
|
||||
{
|
||||
return TransformWorldDirectionToMercator(mapRenderer, directionInWorldSpace, mapRenderer.ZoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// Uses the specified zoom level rather than the <see cref="MapRenderer"/>'s zoom level for the transformation.
|
||||
/// </summary>
|
||||
public static Vector2D TransformWorldDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInWorldSpace, double zoomLevel)
|
||||
{
|
||||
var directionInLocalSpace = mapRenderer.transform.InverseTransformDirection(directionInWorldSpace);
|
||||
directionInLocalSpace.x /= mapRenderer.transform.localScale.x;
|
||||
directionInLocalSpace.y /= mapRenderer.transform.localScale.y;
|
||||
directionInLocalSpace.z /= mapRenderer.transform.localScale.z;
|
||||
return TransformLocalDirectionToMercator(directionInLocalSpace, zoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a Mercator position.
|
||||
/// </summary>
|
||||
public static Vector2D TransformWorldPointToMercator(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
var localSpacePoint = mapRenderer.transform.InverseTransformPoint(pointInWorldSpace);
|
||||
return TransformLocalPointToMercator(mapRenderer, localSpacePoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a Mercator position.
|
||||
/// </summary>
|
||||
public static Vector2D TransformWorldPointToMercatorWithAltitude(
|
||||
this MapRenderer mapRenderer,
|
||||
Vector3 pointInWorldSpace,
|
||||
out double altitudeInMeters,
|
||||
out double mercatorScale)
|
||||
{
|
||||
var localSpacePoint = mapRenderer.transform.InverseTransformPoint(pointInWorldSpace);
|
||||
return TransformLocalPointToMercatorWithAltitude(mapRenderer, localSpacePoint, out altitudeInMeters, out mercatorScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="LatLon"/>.
|
||||
/// </summary>
|
||||
public static LatLon TransformWorldPointToLatLon(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
return LatLon.FromMercatorPosition(mapRenderer.TransformWorldPointToMercator(pointInWorldSpace));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="LatLonAlt"/>.
|
||||
/// </summary>
|
||||
public static LatLonAlt TransformWorldPointToLatLonAlt(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
var mercatorPosition =
|
||||
TransformLocalPointToMercatorWithAltitude(
|
||||
mapRenderer,
|
||||
pointInWorldSpace,
|
||||
out var altitudeInMeters,
|
||||
out var mercatorScale);
|
||||
|
||||
var latLon = LatLon.FromMercatorPosition(mercatorPosition);
|
||||
return new LatLonAlt(ref latLon, altitudeInMeters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="LatLonAlt"/>.
|
||||
/// </summary>
|
||||
public static Vector3 TransformLatLonAltToWorldPoint(this MapRenderer mapRenderer, LatLonAlt location)
|
||||
{
|
||||
// Can compute XZ coords in local space from the Mercator position and map center.
|
||||
var mercatorPosition = location.LatLon.ToMercatorPosition();
|
||||
var mercatorPositionRelativeToCenter = mercatorPosition - mapRenderer.Center.ToMercatorPosition();
|
||||
var equatorialCircumferenceInLocalSpace = Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var localSpaceXZ = equatorialCircumferenceInLocalSpace * mercatorPositionRelativeToCenter;
|
||||
|
||||
// Altitude to local y value.
|
||||
var offsetMapAltitudeInMeters = location.AltitudeInMeters - mapRenderer.ElevationBaseline;
|
||||
var mercatorScale = 1.0 / Math.Cos(location.LatLon.LatitudeInRadians);
|
||||
var altitudeInLocalSpace = offsetMapAltitudeInMeters * mercatorScale * (equatorialCircumferenceInLocalSpace / EquatorialCircumferenceInWgs84Meters);
|
||||
|
||||
var pointInLocalSpace =
|
||||
new Vector3(
|
||||
(float)localSpaceXZ.X,
|
||||
(float)(altitudeInLocalSpace + mapRenderer.LocalMapHeight),
|
||||
(float)localSpaceXZ.Y);
|
||||
|
||||
return mapRenderer.transform.TransformPoint(pointInLocalSpace);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Helpers to transform between Unity's world and local spaces to the geographic coordinate system of the <see cref="MapRenderer"/>.
|
||||
/// </summary>
|
||||
public static class MapRendererTransformExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The WGS84 ellipsoid circumference measured in meters.
|
||||
/// </summary>
|
||||
public const double EquatorialCircumferenceInWgs84Meters = 40075016.685578488;
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in the <see cref="MapRenderer"/>'s local space to a <see cref="MercatorCoordinate"/>.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformLocalPointToMercator(this MapRenderer mapRenderer, Vector3 pointInLocalSpace)
|
||||
{
|
||||
var deltaFromMapCenterToPointInMercator = TransformLocalDirectionToMercator(mapRenderer, pointInLocalSpace);
|
||||
return mapRenderer.Center.ToMercatorCoordinate() + deltaFromMapCenterToPointInMercator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in the <see cref="MapRenderer"/>'s local space to a <see cref="MercatorCoordinate"/>.
|
||||
/// Includes the altitude measured as meters from the WGS84 ellipsoid.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformLocalPointToMercatorWithAltitude(
|
||||
this MapRenderer mapRenderer,
|
||||
Vector3 pointInLocalSpace,
|
||||
out double altitudeInMeters,
|
||||
out double mercatorScale)
|
||||
{
|
||||
var mercatorCoordinate = TransformLocalPointToMercator(mapRenderer, pointInLocalSpace);
|
||||
|
||||
mercatorScale = MercatorScale.AtMercatorLatitude(mercatorCoordinate.Y);
|
||||
var equatorialCircumferenceInLocalSpace = Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var elevationScale = (EquatorialCircumferenceInWgs84Meters / equatorialCircumferenceInLocalSpace) / mercatorScale / mapRenderer.ElevationScale;
|
||||
altitudeInMeters = (pointInLocalSpace.y - mapRenderer.LocalMapBaseHeight) * elevationScale + mapRenderer.ElevationBaseline;
|
||||
|
||||
return mercatorCoordinate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformLocalDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInLocalSpace)
|
||||
{
|
||||
return TransformLocalDirectionToMercator(directionInLocalSpace, mapRenderer.ZoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRenderer"/>'s local space to a direction in Mercator space.
|
||||
/// Uses the specified zoom level rather than the <see cref="MapRenderer"/>'s zoom level for the transformation.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformLocalDirectionToMercator(Vector3 directionInLocalSpace, double zoomLevel)
|
||||
{
|
||||
var mercatorMapSizeInLocalSpace = Math.Pow(2, zoomLevel - 1);
|
||||
var directionInMercator = new MercatorCoordinate(directionInLocalSpace.x, directionInLocalSpace.z) / mercatorMapSizeInLocalSpace;
|
||||
return directionInMercator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRendererBase"/>'s local space to a direction in Mercator space.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformWorldDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInWorldSpace)
|
||||
{
|
||||
return TransformWorldDirectionToMercator(mapRenderer, directionInWorldSpace, mapRenderer.ZoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ direction in the <see cref="MapRendererBase"/>'s local space to a direction in Mercator space.
|
||||
/// Uses the specified zoom level rather than the <see cref="MapRendererBase"/>'s zoom level for the transformation.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformWorldDirectionToMercator(this MapRenderer mapRenderer, Vector3 directionInWorldSpace, double zoomLevel)
|
||||
{
|
||||
var directionInLocalSpace = mapRenderer.transform.InverseTransformDirection(directionInWorldSpace);
|
||||
directionInLocalSpace.x /= mapRenderer.transform.localScale.x;
|
||||
directionInLocalSpace.y /= mapRenderer.transform.localScale.y;
|
||||
directionInLocalSpace.z /= mapRenderer.transform.localScale.z;
|
||||
return TransformLocalDirectionToMercator(directionInLocalSpace, zoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="MercatorCoordinate"/>.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformWorldPointToMercator(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
var pointInLocalSpace = mapRenderer.transform.InverseTransformPoint(pointInWorldSpace);
|
||||
return TransformLocalPointToMercator(mapRenderer, pointInLocalSpace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="MercatorCoordinate"/>.
|
||||
/// </summary>
|
||||
public static MercatorCoordinate TransformWorldPointToMercatorWithAltitude(
|
||||
this MapRenderer mapRenderer,
|
||||
Vector3 pointInWorldSpace,
|
||||
out double altitudeInMeters,
|
||||
out double mercatorScale)
|
||||
{
|
||||
var pointInLocalSpace = mapRenderer.transform.InverseTransformPoint(pointInWorldSpace);
|
||||
return TransformLocalPointToMercatorWithAltitude(mapRenderer, pointInLocalSpace, out altitudeInMeters, out mercatorScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="LatLon"/>.
|
||||
/// </summary>
|
||||
public static LatLon TransformWorldPointToLatLon(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
return mapRenderer.TransformWorldPointToMercator(pointInWorldSpace).ToLatLon();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms an XYZ point in world space to a <see cref="LatLonAlt"/>.
|
||||
/// </summary>
|
||||
public static LatLonAlt TransformWorldPointToLatLonAlt(this MapRenderer mapRenderer, Vector3 pointInWorldSpace)
|
||||
{
|
||||
var pointInLocalSpace = mapRenderer.transform.InverseTransformPoint(pointInWorldSpace);
|
||||
var mercatorCoordinate =
|
||||
TransformLocalPointToMercatorWithAltitude(
|
||||
mapRenderer,
|
||||
pointInLocalSpace,
|
||||
out var altitudeInMeters,
|
||||
out var mercatorScale);
|
||||
|
||||
var latLon = mercatorCoordinate.ToLatLon();
|
||||
return new LatLonAlt(ref latLon, altitudeInMeters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a <see cref="LatLonAlt"/> to an XYZ point in world space.
|
||||
/// </summary>
|
||||
public static Vector3 TransformLatLonAltToWorldPoint(this MapRenderer mapRenderer, LatLonAlt location)
|
||||
{
|
||||
// Can compute XZ coords in local space from the Mercator coordinate of thie location and the map center.
|
||||
var mercatorCoordinate = location.LatLon.ToMercatorCoordinate();
|
||||
var mercatorCoordinateRelativeToCenter = mercatorCoordinate - mapRenderer.Center.ToMercatorCoordinate();
|
||||
var equatorialCircumferenceInLocalSpace = Math.Pow(2, mapRenderer.ZoomLevel - 1);
|
||||
var localSpaceXZ = equatorialCircumferenceInLocalSpace * mercatorCoordinateRelativeToCenter;
|
||||
|
||||
// Altitude to local y value.
|
||||
var offsetMapAltitudeInMeters = location.AltitudeInMeters - mapRenderer.ElevationBaseline;
|
||||
var mercatorScale = MercatorScale.AtMercatorLatitude(mercatorCoordinate.Y);
|
||||
var altitudeInLocalSpace =
|
||||
mapRenderer.ElevationScale *
|
||||
offsetMapAltitudeInMeters *
|
||||
mercatorScale *
|
||||
(equatorialCircumferenceInLocalSpace / EquatorialCircumferenceInWgs84Meters);
|
||||
|
||||
var pointInLocalSpace =
|
||||
new Vector3(
|
||||
(float)localSpaceXZ.X,
|
||||
(float)(altitudeInLocalSpace + mapRenderer.LocalMapBaseHeight),
|
||||
(float)localSpaceXZ.Y);
|
||||
|
||||
return mapRenderer.transform.TransformPoint(pointInLocalSpace);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f8f52b76722377449d9c99ec5de9961
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 4f8f52b76722377449d9c99ec5de9961
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4a6978be5245b5244a3040509b70baf7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using Microsoft.Geospatial;
|
||||
|
||||
/// <summary>
|
||||
/// Animates a MapRenderer to the specified <see cref="MapScene"/>.
|
||||
/// </summary>
|
||||
public interface IMapSceneAnimationController
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a yieldable object that can be used to wait for animation to complete.
|
||||
/// </summary>
|
||||
WaitForMapSceneAnimation YieldInstruction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the controller to animate the specified <see cref="MapScene"/>.
|
||||
/// </summary>
|
||||
void Initialize(MapRendererBase mapRenderer, MapScene mapScene, float animationTimeScale, MapSceneAnimationKind mapSceneAnimationKind);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the zoom level and location for this frame of the animation.
|
||||
/// </summary>
|
||||
bool UpdateAnimation(float currentZoomLevel, LatLon currentLocation, out float zoomLevel, out LatLon location);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a77f095839516184bb1bd32efb79760f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -9,15 +9,16 @@ namespace Microsoft.Maps.Unity
|
|||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Animates a MapRenderer to the specified MapScene. Derives the animation duration and preforms a preceptually smooth animation,
|
||||
/// based on the work of van Wijk and Nuij, "Smooth and Efficient Zooming and Panning". https://www.win.tue.nl/~vanwijk/zoompan.pdf
|
||||
/// Animates a <see cref="MapRenderer"/> to the specified <see cref="MapScene"/>. Derives the animation duration and preforms a
|
||||
/// preceptually smooth animation, based on the work of van Wijk and Nuij, "Smooth and Efficient Zooming and Panning".
|
||||
/// https://www.win.tue.nl/~vanwijk/zoompan.pdf
|
||||
/// </summary>
|
||||
public class MapSceneAnimationController : IMapSceneAnimationController
|
||||
{
|
||||
private double _startZoomLevel;
|
||||
private double _endZoomLevel;
|
||||
private Vector2D _startMercatorCenter;
|
||||
private Vector2D _endMercatorCenter;
|
||||
private MercatorCoordinate _startMercatorCenter;
|
||||
private MercatorCoordinate _endMercatorCenter;
|
||||
private double _animationTime;
|
||||
private double _startHeightInMercator;
|
||||
private double _endHeightInMercator;
|
||||
|
@ -41,17 +42,17 @@ namespace Microsoft.Maps.Unity
|
|||
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(
|
||||
MapRenderer mapRenderer,
|
||||
MapRendererBase mapRenderer,
|
||||
MapScene mapScene,
|
||||
float animationTimeScale,
|
||||
MapSceneAnimationKind mapSceneAnimationKind)
|
||||
{
|
||||
_runningTime = 0;
|
||||
|
||||
_startMercatorCenter = mapRenderer.Center.ToMercatorPosition();
|
||||
_startMercatorCenter = mapRenderer.Center.ToMercatorCoordinate();
|
||||
_startZoomLevel = mapRenderer.ZoomLevel;
|
||||
mapScene.GetLocationAndZoomLevel(out var endLocation, out _endZoomLevel);
|
||||
_endMercatorCenter = endLocation.ToMercatorPosition();
|
||||
_endMercatorCenter = endLocation.ToMercatorCoordinate();
|
||||
_startHeightInMercator = ZoomLevelToMercatorAltitude(_startZoomLevel);
|
||||
_endHeightInMercator = ZoomLevelToMercatorAltitude(_endZoomLevel);
|
||||
|
||||
|
@ -76,7 +77,7 @@ namespace Microsoft.Maps.Unity
|
|||
out _animationTime);
|
||||
|
||||
// Tweaking the resulting animation time to speed up slower animations and slow down the shorter animation.
|
||||
_animationTime = _animationTime / 6.0; // Normalize.
|
||||
_animationTime /= 6.0; // Normalize.
|
||||
_animationTime = Math.Pow(_animationTime, 1.0 / 3.0); // Rescale.
|
||||
_animationTime *= 6.0; // Convert back to original range.
|
||||
}
|
||||
|
@ -112,7 +113,7 @@ namespace Microsoft.Maps.Unity
|
|||
// First, update the zoom.
|
||||
zoomLevel = (float)(_startZoomLevel + (_endZoomLevel - _startZoomLevel) * t);
|
||||
|
||||
// Update the location.
|
||||
// Update the location.
|
||||
if (_startMercatorCenter != _endMercatorCenter)
|
||||
{
|
||||
if (_startZoomLevel != _endZoomLevel)
|
||||
|
@ -120,18 +121,18 @@ namespace Microsoft.Maps.Unity
|
|||
// Adjust t so that it depends on the zoom level. This keeps the position animating correctly at a logarthmic scale to
|
||||
// match how zoom level is being calculated.
|
||||
var adjustedT = (_startHeightInMercator - ZoomLevelToMercatorAltitude(zoomLevel)) / (_startHeightInMercator - _endHeightInMercator);
|
||||
var mercatorPosition = Interpolate(_startMercatorCenter, _endMercatorCenter, Math.Pow(adjustedT, 0.8));
|
||||
location = LatLon.FromMercatorPosition(mercatorPosition);
|
||||
var mercatorCoordinate = Interpolate(_startMercatorCenter, _endMercatorCenter, Math.Pow(adjustedT, 0.8));
|
||||
location = mercatorCoordinate.ToLatLon();
|
||||
}
|
||||
else
|
||||
{
|
||||
var mercatorPosition = Interpolate(_startMercatorCenter, _endMercatorCenter, t);
|
||||
location = LatLon.FromMercatorPosition(mercatorPosition);
|
||||
var mercatorCoordinate = Interpolate(_startMercatorCenter, _endMercatorCenter, t);
|
||||
location = mercatorCoordinate.ToLatLon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
location = LatLon.FromMercatorPosition(_endMercatorCenter);
|
||||
location = _endMercatorCenter.ToLatLon();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +152,7 @@ namespace Microsoft.Maps.Unity
|
|||
out double animationTime)
|
||||
{
|
||||
u0 = 0;
|
||||
u1 = (_endMercatorCenter - _startMercatorCenter).Length();
|
||||
u1 = MercatorCoordinate.Distance(_endMercatorCenter, _startMercatorCenter);
|
||||
|
||||
w0 = 1.0 / Math.Pow(2, _startZoomLevel - 1);
|
||||
w1 = 1.0 / Math.Pow(2, _endZoomLevel - 1);
|
||||
|
@ -192,7 +193,7 @@ namespace Microsoft.Maps.Unity
|
|||
u = Math.Max(0, Math.Min(u / _u1, 1.0));
|
||||
|
||||
zoomLevel = (float)MercatorAltitudeToZoomLevel(w);
|
||||
location = LatLon.FromMercatorPosition(Vector2D.Lerp(_startMercatorCenter, _endMercatorCenter, u));
|
||||
location = Interpolate(_startMercatorCenter, _endMercatorCenter, u).ToLatLon();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -225,11 +226,12 @@ namespace Microsoft.Maps.Unity
|
|||
return Math.Log(1.0 / mercatorAltitude, 2.0) + 1;
|
||||
}
|
||||
|
||||
private static Vector2D Interpolate(Vector2D from, Vector2D to, double t)
|
||||
private static MercatorCoordinate Interpolate(in MercatorCoordinate from, in MercatorCoordinate to, double t)
|
||||
{
|
||||
return new Vector2D(
|
||||
from.X + (to.X - from.X) * t,
|
||||
from.Y + (to.Y - from.Y) * t);
|
||||
return
|
||||
new MercatorCoordinate(
|
||||
from.X + (to.X - from.X) * t,
|
||||
from.Y + (to.Y - from.Y) * t);
|
||||
}
|
||||
|
||||
private static double SmoothStep(double from, double to, double t)
|
|
@ -0,0 +1,23 @@
|
|||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the animation to use when setting a MapScene.
|
||||
/// </summary>
|
||||
public enum MapSceneAnimationKind
|
||||
{
|
||||
/// <summary>
|
||||
/// No animation.
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// A linear animation.
|
||||
/// </summary>
|
||||
Linear,
|
||||
|
||||
/// <summary>
|
||||
/// A parabolic animation.
|
||||
/// </summary>
|
||||
Bow
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d31f867dfde6b54c9cd895b72ba1538
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -6,7 +6,7 @@ namespace Microsoft.Maps.Unity
|
|||
using Microsoft.Geospatial;
|
||||
|
||||
/// <summary>
|
||||
/// The most basic MapScene that can be used to change the map's location and zoom level.
|
||||
/// A basic <see cref="MapScene"/> that can be used to change the map's location and zoom level.
|
||||
/// </summary>
|
||||
public class MapSceneOfLocationAndZoomLevel : MapScene
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ namespace Microsoft.Maps.Unity
|
|||
public float ZoomLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a MapSceneOfLocationAndZoomLevel from the specified location and zoom level.
|
||||
/// Constructs a <see cref="MapSceneOfLocationAndZoomLevel"/> from the specified location and zoom level.
|
||||
/// </summary>
|
||||
public MapSceneOfLocationAndZoomLevel(LatLon location, float zoomLevel)
|
||||
{
|
|
@ -0,0 +1,34 @@
|
|||
namespace Microsoft.Maps.Unity
|
||||
{
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Used to suspend coroutine execution once the associated MapScene animation has been completed or cancelled.
|
||||
/// </summary>
|
||||
public class WaitForMapSceneAnimation : CustomYieldInstruction
|
||||
{
|
||||
private bool _keepWaiting = true;
|
||||
|
||||
/// <summary>
|
||||
/// Returns false once the animation has been completed or cancelled.
|
||||
/// </summary>
|
||||
public override bool keepWaiting => _keepWaiting;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the yieldable instance.
|
||||
/// </summary>
|
||||
public WaitForMapSceneAnimation(bool isCompleted = false)
|
||||
{
|
||||
_keepWaiting = !isCompleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completes the yield instruction.
|
||||
/// </summary>
|
||||
public void SetComplete()
|
||||
{
|
||||
_keepWaiting = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb7373b1ea3896d438d2e23843712aa9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 424715533f7464745a37e0bacd374d56, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a29a412c84fbd74ea026071161116bd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0079aaf4dc00c3448978c59fca500583
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -15,8 +15,8 @@ namespace Microsoft.Maps.Unity.Services
|
|||
RestServiceDomain +
|
||||
$"{restApi}?" +
|
||||
(string.IsNullOrWhiteSpace(Uri.EscapeDataString(queryParameters)) ?
|
||||
$"key={MapServices.BingMapsKey ?? ""}" :
|
||||
$"{queryParameters}&key={MapServices.BingMapsKey ?? ""}");
|
||||
$"key={MapSession.Current.DeveloperKey ?? ""}" :
|
||||
$"{queryParameters}&key={MapSession.Current.DeveloperKey ?? ""}");
|
||||
|
||||
// Useful for debugging.
|
||||
//UnityEngine.Debug.Log(url);
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aa85fa9a0f235804bb1a8f841dc16f42
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -9,14 +9,14 @@ namespace Microsoft.Maps.Unity.Search
|
|||
public class MapLocationAddress
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the address in a local format. This address may not include the country or region, e.g.
|
||||
/// Specifies the address in a local format. This address may not include the country/region, e.g.
|
||||
/// "1 Microsoft Way, Redmond, WA 98052-8300"
|
||||
/// </summary>
|
||||
public string FormattedAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A string specifying the populated place for the address.
|
||||
/// This typically refers to a city, but may refer to a suburb or a neighborhood in certain countries.
|
||||
/// This typically refers to a city, but may refer to a suburb or a neighborhood depending on the country/region.
|
||||
/// </summary>
|
||||
public string AddressLine { get; }
|
||||
|
||||
|
@ -27,19 +27,19 @@ namespace Microsoft.Maps.Unity.Search
|
|||
|
||||
/// <summary>
|
||||
/// A string specifying the populated place for the address.
|
||||
/// This typically refers to a city, but may refer to a suburb or a neighborhood in certain countries.
|
||||
/// This typically refers to a city, but may refer to a suburb or a neighborhood depending on the country/region.
|
||||
/// </summary>
|
||||
public string Locality { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A string specifying the subdivision name in the country or region for an address.
|
||||
/// A string specifying the subdivision name in the country/region for an address.
|
||||
/// This element is typically treated as the first order administrative subdivision,
|
||||
/// but in some cases it is the second, third, or fourth order subdivision in a country, dependency, or region.
|
||||
/// but in some cases it is the second, third, or fourth order subdivision in a country/region.
|
||||
/// </summary>
|
||||
public string AdminDistrict { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A string specifying the subdivision name in the country or region for an address.
|
||||
/// A string specifying the subdivision name in the country/region for an address.
|
||||
/// This element is used when there is another level of subdivision information for a location, such as the county.
|
||||
/// </summary>
|
||||
public string AdminDistrict2 { get; }
|
||||
|
@ -50,12 +50,12 @@ namespace Microsoft.Maps.Unity.Search
|
|||
public string PostalCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A string specifying the country or region name of an address.
|
||||
/// A string specifying the country/region name of an address.
|
||||
/// </summary>
|
||||
public string CountryRegion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A string specifying the two-letter ISO country code.
|
||||
/// A string specifying the two-letter ISO country/region code.
|
||||
/// </summary>
|
||||
public string CountryCode { get; }
|
||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.Maps.Unity.Search
|
|||
public LatLon Point { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A structured address including common adress components like city, state, neighborhood, country, etc.
|
||||
/// A structured address including common adress components like city, state, neighborhood, country/region, etc.
|
||||
/// </summary>
|
||||
public MapLocationAddress Address { get; }
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.Maps.Unity.Search
|
|||
string resource = "Locations",
|
||||
bool startWithAmpersand = true)
|
||||
{
|
||||
string url = null;
|
||||
string url;
|
||||
if (mapLocationOptions != null)
|
||||
{
|
||||
var parameters =
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 86fa9bec97cbd464dafca8bfd11a2308
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -21,13 +21,13 @@ namespace Microsoft.Maps.Unity.Search
|
|||
public string Culture { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// A string that an ISO 3166-1 Alpha-2 region/country code. This will alter geopolitically disputed results to align with the specified region.
|
||||
/// A string that an ISO 3166-1 Alpha-2 country/region code. This will alter geopolitically disputed results to align with the specified region.
|
||||
/// https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
||||
/// </summary>
|
||||
public string Region { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies to include the two-letter ISO country code with the address information in the response.
|
||||
/// Specifies to include the two-letter ISO country/region code with the address information in the response.
|
||||
/// By default, MapLocationAddress will not include this.
|
||||
/// </summary>
|
||||
public bool IncludeCountryCode { get; set; }
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче