mixedreality/com.microsoft.mixedreality..../Runtime/API/ARMarker/ARMarkerManager.cs

184 lines
6.9 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.OpenXR.ARSubsystems;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Collections;
using Unity.XR.CoreUtils;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
namespace Microsoft.MixedReality.OpenXR
{
/// <summary>
/// A manager for <see cref="ARMarker"/>s. Creates, updates, and removes
/// <c>GameObject</c>s in response to detected surfaces in the physical
/// environment.
/// </summary>
[DefaultExecutionOrder(ARUpdateOrder.k_PlaneManager)]
[DisallowMultipleComponent]
#if USE_ARFOUNDATION_5_OR_NEWER
[RequireComponent(typeof(XROrigin))]
#else
[RequireComponent(typeof(ARSessionOrigin))]
#endif
public sealed class ARMarkerManager : ARTrackableManager<
XRMarkerSubsystem,
XRMarkerSubsystemDescriptor,
XRMarkerSubsystem.Provider,
XRMarker,
ARMarker>
{
private static ARMarkerManager m_instance = null;
/// <summary>
/// Singleton instance for ARMarkerManager
/// </summary>
public static ARMarkerManager Instance => m_instance;
/// <summary>
/// Getter or setter for the Marker Prefab.
/// </summary>
[Tooltip("If not null, instantiates this prefab for each created marker. Else, a default empty GameObject is created with the new ARMarker attached.")]
public GameObject markerPrefab;
/// <summary>
/// The list of <see cref="ARMarkerType"/>s that will be detected.
/// </summary>
[Tooltip("The list of ARMarker types that will be detected.")]
public ARMarkerType[] enabledMarkerTypes = { ARMarkerType.QRCode };
/// <summary>
/// Default <see cref="TransformMode"/> for newly detected markers.
/// </summary>
[Tooltip("Default transform mode for newly detected markers.")]
public TransformMode defaultTransformMode = TransformMode.MostStable;
/// <summary>
/// Invoked when markers have changed (been added, updated, or removed).
/// </summary>
public event Action<ARMarkersChangedEventArgs> markersChanged;
/// <summary>
/// Attempt to retrieve an existing <see cref="ARMarker"/> by <paramref name="trackableId"/>.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> of the marker to retrieve.</param>
/// <returns>The <see cref="ARMarker"/> with <paramref name="trackableId"/>, or <c>null</c> if it does not exist.</returns>
public ARMarker GetMarker(TrackableId trackableId) => m_Trackables.TryGetValue(trackableId, out ARMarker marker) ? marker : null;
/// <summary>
/// Set transform mode of an existing <see cref="ARMarker"/>.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> of the marker to be transformed.</param>
/// <param name="transformMode">The <see cref="TransformMode"/> to be applied.</param>
public void SetTransformMode(TrackableId trackableId, TransformMode transformMode)
{
if (enabled && subsystem != null)
{
subsystem.SetTransformMode(trackableId, transformMode);
}
}
/// <summary>
/// Get raw data for an existing <see cref="ARMarker"/>.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> of the marker.</param>
public NativeArray<byte> GetRawData(TrackableId trackableId, Allocator allocator)
{
if (enabled && subsystem != null)
{
return subsystem.GetRawData(trackableId, allocator);
}
return new NativeArray<byte>();
}
/// <summary>
/// Get decoded string for an existing <see cref="ARMarker"/>.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> of the marker.</param>
public string GetDecodedString(TrackableId trackableId)
{
if (enabled && subsystem != null)
{
return subsystem.GetDecodedString(trackableId);
}
return null;
}
/// <summary>
/// Get QR code properties for an existing <see cref="XRMarker"/> of type <see cref="ARMarkerType.QRCode"/>.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> of the QRCode marker.</param>
public QRCodeProperties GetQRCodeProperties(TrackableId trackableId)
{
if (enabled && subsystem != null)
{
return subsystem.GetQRCodeProperties(trackableId);
}
return new QRCodeProperties();
}
/// <summary>
/// Get the Prefab which will be instantiated for each <see cref="ARMarker"/>. Can be `null`.
/// </summary>
/// <returns>The Prefab which will be instantiated for each <see cref="ARMarker"/>.</returns>
protected override GameObject GetPrefab() => markerPrefab;
/// <summary>
/// Invoked when the base class detects trackable changes.
/// </summary>
/// <param name="added">The list of added <see cref="ARMarker"/>s.</param>
/// <param name="updated">The list of updated <see cref="ARMarker"/>s.</param>
/// <param name="removed">The list of removed <see cref="ARMarker"/>s.</param>
protected override void OnTrackablesChanged(
List<ARMarker> added,
List<ARMarker> updated,
List<ARMarker> removed)
{
if (markersChanged != null)
{
using (new ScopedProfiler("OnMarkersChanged"))
markersChanged(
new ARMarkersChangedEventArgs(
added,
updated,
removed));
}
}
protected override void Update()
{
base.Update();
if (enabled && subsystem != null)
{
Array.Sort(enabledMarkerTypes);
if (!enabledMarkerTypes.SequenceEqual(subsystem.EnabledMarkerTypes))
{
subsystem.EnabledMarkerTypes = enabledMarkerTypes;
}
if (defaultTransformMode != subsystem.DefaultTransformMode)
{
subsystem.DefaultTransformMode = defaultTransformMode;
}
}
}
protected override void OnEnable()
{
base.OnEnable();
// Replicating behavior in ARFoundation to initialize singleton instance
m_instance = this;
}
/// <summary>
/// The name to be used for the <c>GameObject</c> whenever a new marker object is created from <see cref="markerPrefab"/>.
/// </summary>
protected override string gameObjectName => "ARMarker";
}
}