/* INFINITY CODE */
/* https://infinity-code.com */
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UPANO
using InfinityCode.uPano;
using InfinityCode.uPano.Controls;
using InfinityCode.uPano.Directions;
using InfinityCode.uPano.HotSpots;
using InfinityCode.uPano.InteractiveElements;
using InfinityCode.uPano.Plugins;
using InfinityCode.uPano.Renderers;
using InfinityCode.uPano.Requests;
using InfinityCode.uPano.Services;
using InfinityCode.uPano.Transitions;
#endif
///
/// Plugin for displaying Google Street View panoramas using uPano.
///
[AddComponentMenu("Infinity Code/Online Maps/Plugins/uPano Connector")]
[OnlineMapsPlugin("uPano Connector", typeof(OnlineMapsControlBase))]
public class OnlineMapsPanoConnector : MonoBehaviour
{
private const string overlayURL = "https://maps.google.com/maps/vt?pb=!1m5!1m4!1i{0}!2i{1}!3i{2}!4i256!2m8!1e2!2ssvv!4m2!1scb_client!2sapiv3!4m2!1scc!2s*211m3*211e3*212b1*213e2*211m3*211e2*212b1*213e2!3m5!3sUS!12m1!1e40!12m1!1e18";
///
/// Google API key
///
public string googleApiKey = "";
///
/// The minimum map zoom for which overlay will be displayed
///
public int minZoom = 10;
///
/// Maximum panorama zoom level (0 - 4)
///
public int panoramaMaxZoom = 3;
///
/// Use progressive loading panoramas (zoom - 0, 1, 2, 3, 4)
///
public bool usePreview = true;
///
/// Check the color of the overlay texture before opening the panorama.
///
public bool checkOverlayColor = true;
///
/// Use rotation from Online Maps Camera Orbit
///
public bool useRotation = true;
///
/// Overlay layer will be drawn
///
public OverlayLayer overlayLayer = OverlayLayer.front;
///
/// Prefab of the arrow to go to the next panorama
///
public GameObject nextDirectionPrefab;
///
/// Prefab of UI button to close the panorama
///
[Header("Panorama close settings")]
public GameObject closeButtonPrefab;
///
/// Hot key to close the panorama
///
public KeyCode closeByKeyCode = KeyCode.Escape;
///
/// Radius of the panorama sphere
///
[Header("Panorama mesh settings")]
public int radius = 10;
///
/// Number of segments of the panorama sphere
///
public int segments = 32;
///
/// The shader that will be used to display the panorama
///
[Header("Transitions")]
public Shader shader;
///
/// Prefab which contains the transition that is played before the panorama is closed
///
public GameObject beforeTransitionPrefab;
///
/// Prefab which contains the transition that is played after the panorama is closed
///
public GameObject afterTransitionPrefab;
///
/// Use global transitions if they are not in this component
///
public bool useGlobalTransitions = true;
///
/// Use transitions when a panorama is shown
///
public bool showPanoramaTransition = true;
///
/// Use transitions when a panorama is closing
///
public bool closePanoramaTransition = true;
private OnlineMaps map;
private Dictionary overlays;
private GameObject closeButtonInstance;
#if UPANO
private SphericalPanoRenderer panoRenderer;
private GoogleStreetViewRequest currentRequest;
private double lng, lat;
private int zoom;
public GoogleStreetViewMeta meta;
private bool CheckOverlayColor(double clng, double clat)
{
double tx, ty;
map.projection.CoordinatesToTile(clng, clat, map.zoom, out tx, out ty);
OnlineMapsTile tile = map.tileManager.GetTile(map.zoom, (int) tx, (int) ty);
if (tile == null) return false;
while (tile.status != OnlineMapsTileStatus.loaded)
{
tile = tile.parent;
if (tile == null) return false;
}
Texture2D overlay = null;
if (overlayLayer == OverlayLayer.front) overlay = tile.overlayFrontTexture;
else if (overlayLayer == OverlayLayer.back) overlay = tile.overlayBackTexture;
else if (overlayLayer == OverlayLayer.traffic) overlay = (tile as OnlineMapsRasterTile).trafficTexture;
if (overlay == null) return false;
int px = (int) Math.Round((tx - (int) tx) * 255);
int py = 255 - (int) Math.Round((ty - (int) ty) * 255);
for (int x = Mathf.Max(0, px - 2); x < Mathf.Min(255, px + 3); x++)
{
for (int y = Mathf.Max(0, py - 2); y < Mathf.Min(255, py + 3); y++)
{
if (overlay.GetPixel(x, y) != Color.clear) return true;
}
}
return false;
}
///
/// Closes the active instance of the panorama.
///
public void Close()
{
if (closePanoramaTransition) StartCloseTransition();
else CloseImmediately();
}
private void CloseImmediately()
{
if (panoRenderer != null)
{
if (panoRenderer.texture != null) Destroy(panoRenderer.texture);
Destroy(panoRenderer.gameObject);
panoRenderer = null;
}
if (closeButtonInstance != null)
{
Destroy(closeButtonInstance);
closeButtonInstance = null;
}
if (currentRequest != null)
{
currentRequest.Dispose();
currentRequest = null;
}
if (map != null) map.control.allowUserControl = true;
}
private void CreateDirections(DirectionManager directionManager)
{
directionManager.Clear();
try
{
foreach (GoogleStreetViewDirection item in meta.nearestDirections)
{
Direction direction = directionManager.Create(item.pan, nextDirectionPrefab);
if (!string.IsNullOrEmpty(item.title)) direction.title = item.title;
direction["id"] = item.id;
direction.OnClick.AddListener(LoadNextPanorama);
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void LoadNextPanorama(InteractiveElement element)
{
if (currentRequest != null) currentRequest.Dispose();
zoom = usePreview? 0: panoramaMaxZoom;
GoogleStreetViewRequest request = new GoogleStreetViewRequest(googleApiKey, element["id"] as string, zoom, true);
request.OnSuccess += OnGoogleStreetViewSuccess;
}
private void OnDisable()
{
if (map != null)
{
if (map.tileManager != null && map.tileManager.tiles != null)
{
foreach (OnlineMapsTile tile in map.tileManager.tiles) SetOverlay(tile as OnlineMapsRasterTile, null);
}
map.Redraw();
}
}
private void OnEnable()
{
if (string.IsNullOrEmpty(googleApiKey))
{
Debug.LogWarning("Please specify Online Maps Pano Connector/Google Api Key!!!");
Destroy(this);
return;
}
if (overlays == null) overlays = new Dictionary();
foreach (KeyValuePair pair in overlays)
{
if (!map.tileManager.dTiles.ContainsKey(pair.Key)) continue;
SetOverlay(map.tileManager.dTiles[pair.Key] as OnlineMapsRasterTile, pair.Value);
}
if (map != null) map.Redraw();
}
private void OnGoogleStreetViewSuccess(GoogleStreetViewRequest request)
{
currentRequest = null;
if (request.hasErrors)
{
Debug.Log(request.error);
return;
}
string panoID = request.panoID;
if (panoRenderer == null)
{
map.control.allowUserControl = false;
panoRenderer = SphericalPanoRenderer.CreateSphere(request.texture, radius, segments);
if (useRotation && OnlineMapsCameraOrbit.instance != null) panoRenderer.pano.pan = OnlineMapsCameraOrbit.instance.rotation.y;
else panoRenderer.pano.pan = 0;
panoRenderer.shader = shader != null ? shader : Shader.Find("Unlit/Texture");
panoRenderer.gameObject.AddComponent();
panoRenderer.gameObject.AddComponent();
panoRenderer.gameObject.AddComponent();
panoRenderer.gameObject.AddComponent();
panoRenderer.gameObject.AddComponent();
if (closeButtonPrefab != null && closeButtonInstance == null)
{
Canvas canvas = CanvasUtils.GetCanvas();
if (canvas != null)
{
closeButtonInstance = Instantiate(closeButtonPrefab);
closeButtonInstance.transform.SetParent(canvas.transform, false);
closeButtonInstance.GetComponentInChildren