This repository has been archived on 2025-04-28. You can view files and clone it, but cannot push or open issues or pull requests.
ARPlusSystem/ARPlusSystem-250418/Assets/ARLocation/Scripts/Components/ARLocationProvider.cs

318 lines
11 KiB
C#

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();
// Provider = LocProviderManager.GetProvider();
#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);
}
}
}