// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2022) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
namespace UnityEngine.XR.MagicLeap
{
using System;
using System.Threading.Tasks;
///
/// This API can be used to scan markers. For QR codes it also provides 6DOF poses. The
/// scanner supports up to 16 markers. Identical markers will be treated as seperate
/// markers and reported individually.
/// List of currently supported trackable markers (with pose info):
/// - QR codes of Model 1 and Model 2
/// - ArUco markers
/// List of currently supported detectable markers (without pose info):
/// - EAN-13 (experimental)
/// - UPC-A (experimental)
///
public sealed partial class MLMarkerTracker : MLAutoAPISingleton
{
///
/// When any results are found from marker scanning, this event will be raised.
///
public static event Action OnMLMarkerTrackerResultsFound;
///
/// When any results are found from marker scanning, this event will be raised with an array of all markers found.
///
public static event Action OnMLMarkerTrackerResultsFoundArray;
///
/// A cache of the last requested settings value. Any new requested value will be
/// checked against this to verify that an update is needed.
///
private static TrackerSettings futureSettingsValue;
private static bool isPaused { get; set; } = false;
///
/// Are markers currently being scanned?
///
public static bool IsScanning => Instance.settings.EnableMarkerScanning;
///
/// Was Marker Tracker scanning before pausing the app?
///
private static bool wasScanning = false;
///
/// Instance.settings setter.
/// If called with the same value while a settings update operation is in progress,
/// nothing will happen.
///
public static async Task SetSettingsAsync(TrackerSettings value)
{
if (futureSettingsValue.Equals(value))
return MLResult.Create(MLResult.Code.Ok);
futureSettingsValue = value;
var resultCode = await MLMarkerTrackerSettingsUpdate(value);
if (resultCode.IsOk)
Instance.settings = value;
return resultCode;
}
private MLMarkerTracker.TrackerSettings settings = TrackerSettings.Create(false);
///
/// Asynchronous utility method to enable marker scanning using the current ScannerSettings .
/// Does nothing if scanning is already enabled.
/// Note that enabling scanning has a performance cost until scanning is disabled using
/// StopScanning or by setting ScannerSettings.enabled to false.
///
public static async Task StartScanningAsync(TrackerSettings? settings = null)
{
if (IsStarted && Instance.settings.EnableMarkerScanning == true)
return MLResult.Create(MLResult.Code.Ok);
settings ??= Instance.settings;
return await SetSettingsAsync(TrackerSettings.Create(true, settings.Value.MarkerTypes, settings.Value.QRCodeSize, settings.Value.ArucoDicitonary, settings.Value.ArucoMarkerSize));
}
///
/// Asynchronous method to disable marker scanning if previously activated.
/// Otherwise, this does nothing.
///
public async static Task StopScanningAsync()
{
// check future settings instead of current settings because this is asynchronous
if (!IsStarted || futureSettingsValue.EnableMarkerScanning == false)
return MLResult.Create(MLResult.Code.Ok);
return await SetSettingsAsync(TrackerSettings.Create(false, Instance.settings.MarkerTypes, Instance.settings.QRCodeSize, Instance.settings.ArucoDicitonary, Instance.settings.ArucoMarkerSize));
}
protected override MLResult.Code StopAPI()
{
if (IsScanning)
Task.Run(StopScanningAsync).Wait();
return NativeBindings.MLMarkerTrackerDestroy(Handle);
}
protected override MLResult.Code StartAPI() => MLMarkerTrackerCreate(Instance.settings);
///
/// Runs once per Unity Update loop.
///
protected override void Update()
{
if (IsScanning)
{
var results = MLMarkerTrackerGetResults();
foreach (var result in results)
OnMLMarkerTrackerResultsFound?.Invoke(result);
OnMLMarkerTrackerResultsFoundArray?.Invoke(results);
}
}
protected override void OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
HandleApplicationPause();
else
HandleApplicationUnpause();
}
private void HandleApplicationPause()
{
if (IsStarted)
{
wasScanning = IsScanning;
StopAPI();
isPaused = true;
}
}
private void HandleApplicationUnpause()
{
if (isPaused)
{
StartAPI();
isPaused = false;
if (wasScanning)
{
_ = StartScanningAsync();
}
}
}
}
}