You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
8.3 KiB
229 lines
8.3 KiB
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using Logger = ARLocation.Utils.Logger;
|
|
|
|
namespace ARLocation {
|
|
|
|
[AddComponentMenu("AR+GPS/Hotspot")]
|
|
[HelpURL("https://http://docs.unity-ar-gps-location.com/guide/#hotspot")]
|
|
[DisallowMultipleComponent]
|
|
public class Hotspot : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public class OnHotspotActivatedUnityEvent : UnityEvent<GameObject> {}
|
|
|
|
[Serializable]
|
|
public class OnHotspotLeaveUnityEvent : UnityEvent<GameObject> {}
|
|
|
|
[Serializable]
|
|
public enum PositionModes {
|
|
HotspotCenter,
|
|
CameraPosition
|
|
};
|
|
|
|
[Serializable]
|
|
public class HotspotSettingsData
|
|
{
|
|
[Tooltip("The prefab/GameObject that will be instantiated by the Hotspot.")]
|
|
public GameObject Prefab;
|
|
|
|
[Tooltip("The positioning mode. 'HotspotCenter' means the object will be instantiated at the Hotpot's center geo-location. 'CameraPosition' means it will be positioned at the front of the camera.")]
|
|
public PositionModes PositionMode;
|
|
|
|
[Tooltip("The distance from the center that the user must be located to activate the Hotspot.")]
|
|
public float ActivationRadius = 4.0f;
|
|
|
|
[Tooltip("If true, align the instantiated object to face the camera (horizontally).")]
|
|
public bool AlignToCamera = true;
|
|
|
|
[Tooltip("If 'PositionMode' is set to 'CameraPosition', how far from the camera the instantiated object should be placed.")]
|
|
public float DistanceFromCamera = 3.0f;
|
|
}
|
|
|
|
[Serializable]
|
|
public class StateData
|
|
{
|
|
public bool Activated;
|
|
public GameObject Instance;
|
|
public Location Location;
|
|
public bool EmittedLeaveHotspotEvent;
|
|
}
|
|
|
|
public PlaceAtLocation.LocationSettingsData LocationSettings = new PlaceAtLocation.LocationSettingsData();
|
|
public HotspotSettingsData HotspotSettings = new HotspotSettingsData();
|
|
|
|
[Space(4.0f)]
|
|
|
|
[Header("Debug")]
|
|
[Tooltip("When debug mode is enabled, this component will print relevant messages to the console. Filter by 'Hotspot' in the log output to see the messages.")]
|
|
public bool DebugMode;
|
|
|
|
[Space(4.0f)]
|
|
|
|
|
|
[Header("Events")]
|
|
[Tooltip("If true, monitor distance to emit the 'OnLeaveHotspot' event. If you don't need it, keep this disabled for better performance.")]
|
|
public bool UseOnLeaveHotspotEvent;
|
|
|
|
[Tooltip("Event for the Hotspot is activated.")]
|
|
public OnHotspotActivatedUnityEvent OnHotspotActivated = new OnHotspotActivatedUnityEvent();
|
|
|
|
[Tooltip("This event will be emited only once, when the user leaves the hotspot area after it is activated.")]
|
|
public OnHotspotLeaveUnityEvent OnHotspotLeave = new OnHotspotLeaveUnityEvent();
|
|
|
|
private readonly StateData state = new StateData();
|
|
|
|
private Transform root;
|
|
private Camera arCamera;
|
|
private double currentDistance;
|
|
|
|
// ReSharper disable once UnusedMember.Global
|
|
public GameObject Instance => state.Instance;
|
|
|
|
// ReSharper disable once MemberCanBePrivate.Global
|
|
public Location Location {
|
|
// ReSharper disable once UnusedMember.Global
|
|
get => state.Location;
|
|
set => state.Location = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the current user distance to the Hotspot center.
|
|
/// </summary>
|
|
public float CurrentDistance => (float) currentDistance;
|
|
|
|
void Start()
|
|
{
|
|
var arLocationProvider = ARLocationProvider.Instance;
|
|
arLocationProvider.Provider.LocationUpdatedRaw += Provider_LocationUpdatedRaw;
|
|
|
|
root = ARLocationManager.Instance.gameObject.transform;
|
|
|
|
if (state.Location == null)
|
|
{
|
|
state.Location = LocationSettings.GetLocation();
|
|
}
|
|
|
|
arCamera = ARLocationManager.Instance.MainCamera;
|
|
|
|
if (arLocationProvider.IsEnabled)
|
|
{
|
|
Provider_LocationUpdatedRaw(arLocationProvider.CurrentLocation, arLocationProvider.LastLocation);
|
|
}
|
|
}
|
|
|
|
public void Restart()
|
|
{
|
|
state.Activated = false;
|
|
state.EmittedLeaveHotspotEvent = false;
|
|
state.Instance = null;
|
|
|
|
Destroy(state.Instance);
|
|
}
|
|
|
|
|
|
private void Provider_LocationUpdatedRaw(LocationReading currentLocation, LocationReading lastLocation)
|
|
{
|
|
if (state.Activated) return;
|
|
|
|
Logger.LogFromMethod("Hotspot", "LocationUpdatedRaw", $"({gameObject.name}): New device location {currentLocation}", DebugMode);
|
|
|
|
currentDistance = Location.HorizontalDistance(currentLocation.ToLocation(), state.Location);
|
|
|
|
var delta = Location.HorizontalVectorFromTo(currentLocation.ToLocation(), state.Location);
|
|
|
|
if (currentDistance <= HotspotSettings.ActivationRadius)
|
|
{
|
|
ActivateHotspot(new Vector3((float) delta.x, 0, (float) delta.y));
|
|
}
|
|
else
|
|
{
|
|
Logger.LogFromMethod("Hotspot", "LocationUpdatedRaw", $"({gameObject.name}): No activation - distance = {currentDistance}", DebugMode);
|
|
}
|
|
}
|
|
|
|
private void ActivateHotspot(Vector3 delta)
|
|
{
|
|
Logger.LogFromMethod("Hotspot", "ActivateHotspot", $"({gameObject.name}): Activating hotspot...", DebugMode);
|
|
|
|
if (HotspotSettings.Prefab == null) return;
|
|
|
|
state.Instance = Instantiate(HotspotSettings.Prefab, HotspotSettings.AlignToCamera ? gameObject.transform : root);
|
|
|
|
switch (HotspotSettings.PositionMode)
|
|
{
|
|
case PositionModes.HotspotCenter:
|
|
state.Instance.transform.position = arCamera.transform.position + delta;
|
|
break;
|
|
case PositionModes.CameraPosition:
|
|
var transform1 = arCamera.transform;
|
|
var forward = transform1.forward;
|
|
forward.y = 0;
|
|
state.Instance.transform.position = transform1.position + forward * HotspotSettings.DistanceFromCamera;
|
|
break;
|
|
}
|
|
|
|
if (HotspotSettings.AlignToCamera)
|
|
{
|
|
state.Instance.transform.LookAt(arCamera.transform);
|
|
}
|
|
|
|
state.Instance.AddComponent<GroundHeight>();
|
|
state.Instance.name = name + " (Hotspot)";
|
|
|
|
state.Activated = true;
|
|
|
|
Logger.LogFromMethod("Hotspot", "ActivateHotspot", $"({name}): Hotspot activated", DebugMode);
|
|
|
|
OnHotspotActivated?.Invoke(state.Instance);
|
|
}
|
|
|
|
// ReSharper disable once UnusedMethodReturnValue.Global
|
|
// ReSharper disable once MemberCanBePrivate.Global
|
|
public static Hotspot AddHotspotComponent(GameObject go, Location location, HotspotSettingsData settings)
|
|
{
|
|
var hotspot = go.AddComponent<Hotspot>();
|
|
hotspot.Location = location.Clone();
|
|
hotspot.HotspotSettings = settings;
|
|
|
|
return hotspot;
|
|
}
|
|
|
|
// ReSharper disable once UnusedMember.Global
|
|
public static GameObject CreateHotspotGameObject(Location location, HotspotSettingsData settings,
|
|
string name = "GPS Hotspot")
|
|
{
|
|
var go = new GameObject(name);
|
|
|
|
AddHotspotComponent(go, location, settings);
|
|
|
|
return go;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (UseOnLeaveHotspotEvent && state.Activated && !state.EmittedLeaveHotspotEvent)
|
|
{
|
|
var distance = Vector3.Distance(arCamera.transform.position, state.Instance.transform.position);
|
|
if (distance >= HotspotSettings.ActivationRadius)
|
|
{
|
|
OnHotspotLeave?.Invoke(state.Instance);
|
|
state.EmittedLeaveHotspotEvent = true;
|
|
}
|
|
}
|
|
}
|
|
public void AtoB_Button()
|
|
{
|
|
LocationSettings.LocationInput.Location.Latitude = 35.967491;
|
|
LocationSettings.LocationInput.Location.Longitude = 126.711558;
|
|
gameObject.GetComponent<Hotspot>().enabled = true;
|
|
|
|
}
|
|
public void AtoC_Button()
|
|
{
|
|
gameObject.GetComponent<Hotspot>().enabled = true;
|
|
|
|
}
|
|
}
|
|
}
|