123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- using System;
- using System.Collections;
- using UnityEngine;
- using UnityEngine.Events;
- using UnityEngine.Serialization;
- // ReSharper disable UnusedMember.Global
- namespace ARLocation
- {
- using Utils;
- [AddComponentMenu("AR+GPS/AR Location Provider")]
- [HelpURL("https://http://docs.unity-ar-gps-location.com/guide/#arlocationprovider")]
- [DisallowMultipleComponent]
- public class ARLocationProvider : Singleton<ARLocationProvider>
- {
- [Serializable]
- public class LocationEnabledUnityEvent : UnityEvent<Location> {}
- [Serializable]
- public class LocationUpdatedUnityEvent : UnityEvent<Location> {}
- [Serializable]
- public class CompassUpdatedUnityEvent: UnityEvent<HeadingReading> {}
- [FormerlySerializedAs("LocationUpdateSettings")]
- [Tooltip("The options for the Location Provider.")]
- [Header("Update Settings")]
- public LocationProviderOptions LocationProviderSettings = new LocationProviderOptions();
- [Tooltip("The data of mock location. If present, overrides the Mock Location above.")]
- [Header("Mock Data")]
- public LocationData MockLocationData;
- [Tooltip("The maximum wait time to wait for location initialization.")]
- [Header("Initialization")]
- public uint MaxWaitTime = 200;
- [Tooltip("Wait this many seconds before starting location services. Useful when using Unity Remote.")]
- public uint StartUpDelay;
- [Header("Debug")]
- [Tooltip("When debug mode is enabled, this component will print relevant messages to the console. Filter by 'ARLocationProvider' in the log output to see the messages.")]
- public bool DebugMode;
- [Header("Events")]
- [Tooltip("Called after the first location is read.")]
- public LocationEnabledUnityEvent OnEnabled = new LocationEnabledUnityEvent();
- [Tooltip("Called after each new location update.")]
- public LocationUpdatedUnityEvent OnLocationUpdated = new LocationUpdatedUnityEvent();
- [Tooltip("Called after each new raw device GPS data is obtained.")]
- public LocationUpdatedUnityEvent OnRawLocationUpdated = new LocationUpdatedUnityEvent();
- [Tooltip("Called after each new compass update.")]
- public CompassUpdatedUnityEvent OnCompassUpdated = new CompassUpdatedUnityEvent();
- /// <summary>
- /// Returns the current location provider.
- /// </summary>
- public ILocationProvider Provider { get; private set; }
- /// <summary>
- /// If true, the location provider has received the first location data.
- /// </summary>
- public bool IsEnabled => Provider.IsEnabled;
- /// <summary>
- /// If true, the location provider has started, but no location data has been read.
- /// </summary>
- public bool HasStarted => Provider.HasStarted;
- /// <summary>
- /// The number of location updates so far.
- /// </summary>
- public int LocationUpdateCount => Provider.LocationUpdateCount;
- /// <summary>
- /// If true, updates are paused.
- /// </summary>
- public bool IsPaused => Provider.Paused;
- /// <summary>
- /// The latest location data.
- /// </summary>
- public LocationReading CurrentLocation => Provider.CurrentLocation;
- /// <summary>
- /// The previous location data.
- /// </summary>
- public LocationReading LastLocation => Provider.LastLocation;
- /// <summary>
- /// The current heading data.
- /// </summary>
- public HeadingReading CurrentHeading => Provider.CurrentHeading;
- /// <summary>
- /// Time since the location provider has started.
- /// </summary>
- public float TimeSinceStart => Time.time - Provider.StartTime;
- /// <summary>
- /// The distance from the initial measured position.
- /// </summary>
- public double DistanceFromStartPoint => Provider.DistanceFromStartPoint;
- private int measurementCount;
- private bool mute;
- public event LocationUpdatedDelegate OnLocationUpdatedDelegate;
- public event CompassUpdateDelegate OnCompassUpdateDelegate;
- public event Action OnRestartDelegate;
- public override void Awake()
- {
- base.Awake();
- #if UNITY_EDITOR
- Provider = new MockLocationProvider();
- if (MockLocationData != null)
- {
- Logger.LogFromMethod("ARLocationProvider", "Awake", $"Using mock location {MockLocationData}", DebugMode);
- ((MockLocationProvider) Provider).mockLocation = MockLocationData.Location;
- }
- #elif ARGPS_CUSTOM_PROVIDER
- // If you want to use a custom location provider, add 'ARGPS_CUSTOM_PROVIDER' to the define symbols in the Player
- // settings, create a implementation of ILocationProvider, and instantiate it in the line below.
- Provider = new ARGpsCustomLocationProvider();
- #else
- Provider = new UnityLocationProvider();
- #endif
- Logger.LogFromMethod("ARLocationProvider", "Awake",": Using provider " + Provider.Name, DebugMode);
- }
- private void InitProviderEventListeners()
- {
- Logger.LogFromMethod("ARLocationProvider", "InitProviderEventListeners","Initializing location provider listeners.", DebugMode);
- Provider.LocationUpdated += Provider_LocationUpdated;
- Provider.CompassUpdated += Provider_CompassUpdated;
- Provider.LocationUpdatedRaw += ProviderOnLocationUpdatedRaw;
- Provider.OnEnabled(OnProviderEnabledDelegate);
- if (Provider.IsEnabled)
- {
- ForceLocationUpdate();
- }
- }
- private void ProviderOnLocationUpdatedRaw(LocationReading currentLocation, LocationReading lastLocation)
- {
- OnRawLocationUpdated?.Invoke(currentLocation.ToLocation());
- }
- private void OnProviderEnabledDelegate()
- {
- Logger.LogFromMethod("ARLocationProvider", "OnProviderEnabledDelegate","Provider enabled; emitting 'OnEnabled' event.", DebugMode);
- OnEnabled?.Invoke(CurrentLocation.ToLocation());
- }
- IEnumerator Start()
- {
- InitProviderEventListeners();
- Provider.Options = LocationProviderSettings;
- Logger.LogFromMethod("ARLocationProvider", "Start","Starting the location provider", DebugMode);
- yield return StartCoroutine(Provider.Start(MaxWaitTime, StartUpDelay));
- }
- public void Mute()
- {
- Logger.LogFromMethod("ARLocationProvider", "Mute","Muting ARLocationProvider.", DebugMode);
- mute = true;
- }
- public void Unmute(bool emit = true)
- {
- Logger.LogFromMethod("ARLocationProvider", "Mute","Un-muting ARLocationProvider.", DebugMode);
- mute = false;
- if (Provider.IsEnabled && emit) ForceLocationUpdate();
- }
- private void Provider_CompassUpdated(HeadingReading heading, HeadingReading lastReading)
- {
- if (mute) return;
- OnCompassUpdateDelegate?.Invoke(heading, lastReading);
- OnCompassUpdated?.Invoke(heading);
- }
- private void Provider_LocationUpdated(LocationReading currentLocation, LocationReading lastLocation)
- {
- if (mute) return;
- measurementCount++;
- if ((LocationProviderSettings.MaxNumberOfUpdates > 0) && (measurementCount >= LocationProviderSettings.MaxNumberOfUpdates))
- {
- Provider.Pause();
- }
- Logger.LogFromMethod("ARLocationProvider", "Provider_LocationUpdated",$"New location {currentLocation}.", DebugMode);
- OnLocationUpdatedDelegate?.Invoke(currentLocation, lastLocation);
- OnLocationUpdated?.Invoke(currentLocation.ToLocation());
- }
- /// <summary>
- /// Force the provider to emit a location update event. This wont force a new read of location, just emit
- /// the last available measurement.
- /// </summary>
- public void ForceLocationUpdate()
- {
- Logger.LogFromMethod("ARLocationProvider", "ForceLocationUpdate","Emitting a forced location update", DebugMode);
- Provider.ForceLocationUpdate();
- }
- void Update()
- {
- if (Provider == null || !Provider.HasStarted)
- {
- return;
- }
- Provider.Update();
- }
- /// <summary>
- /// Pauses location updates
- /// </summary>
- public void Pause()
- {
- Logger.LogFromMethod("ARLocationProvider", "Pause","Pausing the location provider.", DebugMode);
- Provider?.Pause();
- }
- /// <summary>
- /// Resumes location updates
- /// </summary>
- public void Resume()
- {
- Logger.LogFromMethod("ARLocationProvider", "Resume","Resuming the location provider.", DebugMode);
- Provider?.Resume();
- }
- /// <summary>
- /// Resets the location provider.
- /// </summary>
- public void Restart()
- {
- Logger.LogFromMethod("ARLocationProvider", "Restart","Restarting the location provider.", DebugMode);
- Provider?.Restart();
- OnRestartDelegate?.Invoke();
- }
- /// <summary>
- /// Register a delegate to location updates.
- ///
- /// The `useRawIfEnabled` method if for situations where we want the latest data,
- /// like when we are adding objects at runtime.
- ///
- /// </summary>
- /// <param name="locationUpdatedDelegate"></param>
- /// <param name="useRawIfEnabled"></param>
- public void OnLocationUpdatedEvent(LocationUpdatedDelegate locationUpdatedDelegate, bool useRawIfEnabled = false)
- {
- if (IsEnabled)
- {
- locationUpdatedDelegate(CurrentLocation, useRawIfEnabled ? Provider.LastLocationRaw : LastLocation);
- }
- OnLocationUpdatedDelegate += locationUpdatedDelegate;
- }
- public void OnProviderRestartEvent(Action del)
- {
- OnRestartDelegate += del;
- }
- /// <summary>
- /// Register a delegate to compass/heading updates.
- /// </summary>
- /// <param name="compassUpdateDelegate"></param>
- public void OnCompassUpdatedEvent(CompassUpdateDelegate compassUpdateDelegate)
- {
- OnCompassUpdateDelegate += compassUpdateDelegate;
- }
- /// <summary>
- /// RegisterRegister delegate for when the provider enables location updates.
- /// </summary>
- /// <param name="del">Del.</param>
- public void OnEnabledEvent(LocationEnabledDelegate del)
- {
- Provider.OnEnabled(del);
- }
- /// <summary>
- /// Register a delegate for when the provider fails to initialize location services.
- /// </summary>
- /// <param name="del">Del.</param>
- public void OnFailedEvent(LocationFailedDelegate del)
- {
- Provider.OnFail(del);
- }
- }
- }
|