ARFaceManager.cs
5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Collections.Generic;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.Serialization;
namespace UnityEngine.XR.ARFoundation
{
/// <summary>
/// Creates, updates, and removes <c>GameObject</c>s with <see cref="ARFace"/> components under the
/// <see cref="ARSessionOrigin"/>'s <see cref="ARSessionOrigin.trackablesParent"/>.
/// </summary>
/// <remarks>
/// When enabled, this component subscribes to <see cref="ARFaceManager.facesChanged"/> event to update face data.
/// If this component is disabled, and there are no other subscribers to those events,
/// face detection will be disabled on the device.
/// </remarks>
[RequireComponent(typeof(ARSessionOrigin))]
[DisallowMultipleComponent]
[DefaultExecutionOrder(ARUpdateOrder.k_FaceManager)]
[HelpURL(HelpUrls.ApiWithNamespace + nameof(ARFaceManager) + ".html")]
public sealed class ARFaceManager : ARTrackableManager<
XRFaceSubsystem,
XRFaceSubsystemDescriptor,
#if UNITY_2020_2_OR_NEWER
XRFaceSubsystem.Provider,
#endif
XRFace,
ARFace>
{
[SerializeField]
[Tooltip("If not null, instantiates this prefab for each created face.")]
GameObject m_FacePrefab;
/// <summary>
/// Getter/setter for the Face Prefab.
/// </summary>
public GameObject facePrefab
{
get => m_FacePrefab;
set => m_FacePrefab = value;
}
[SerializeField]
[Tooltip("The maximum number of faces to track simultaneously.")]
int m_MaximumFaceCount = 1;
/// <summary>
/// Get or set the requested maximum number of faces to track simultaneously
/// </summary>
public int requestedMaximumFaceCount
{
get => subsystem?.requestedMaximumFaceCount ?? m_MaximumFaceCount;
set
{
m_MaximumFaceCount = value;
if (enabled && subsystem != null)
{
subsystem.requestedMaximumFaceCount = value;
}
}
}
/// <summary>
/// Get or set the maximum number of faces to track simultaneously. This method is obsolete.
/// Use <see cref="currentMaximumFaceCount"/> or <see cref="requestedMaximumFaceCount"/> instead.
/// </summary>
[Obsolete("Use requestedMaximumFaceCount or currentMaximumFaceCount instead. (2020-01-14)")]
public int maximumFaceCount
{
get => subsystem?.currentMaximumFaceCount ?? m_MaximumFaceCount;
set => requestedMaximumFaceCount = value;
}
/// <summary>
/// Get the maximum number of faces to track simultaneously.
/// </summary>
public int currentMaximumFaceCount => subsystem?.currentMaximumFaceCount ?? 0;
/// <summary>
/// Get the supported number of faces that can be tracked simultaneously. This value
/// may change when the configuration changes.
/// </summary>
public int supportedFaceCount => subsystem?.supportedFaceCount ?? 0;
/// <summary>
/// Raised for each new <see cref="ARFace"/> detected in the environment.
/// </summary>
public event Action<ARFacesChangedEventArgs> facesChanged;
/// <summary>
/// Attempts to retrieve an <see cref="ARFace"/>.
/// </summary>
/// <param name="faceId">The <c>TrackableId</c> associated with the <see cref="ARFace"/>.</param>
/// <returns>The <see cref="ARFace"/>if found. <c>null</c> otherwise.</returns>
public ARFace TryGetFace(TrackableId faceId)
{
m_Trackables.TryGetValue(faceId, out ARFace face);
return face;
}
/// <summary>
/// Invoked just before calling `Start` on the Subsystem. Used to set the `requestedMaximumFaceCount`
/// on the subsystem.
/// </summary>
protected override void OnBeforeStart()
{
subsystem.requestedMaximumFaceCount = m_MaximumFaceCount;
}
/// <summary>
/// Invoked just after a <see cref="ARFace"/> has been updated.
/// </summary>
/// <param name="face"></param>
/// <param name="sessionRelativeData"></param>
protected override void OnAfterSetSessionRelativeData(
ARFace face,
XRFace sessionRelativeData)
{
face.UpdateMesh(subsystem);
#if UNITY_2020_2_OR_NEWER
if (subsystem.subsystemDescriptor.supportsEyeTracking)
#else
if (subsystem.SubsystemDescriptor.supportsEyeTracking)
#endif
face.UpdateEyes();
}
/// <summary>
/// Invoked when the base class detects trackable changes.
/// </summary>
/// <param name="added">The list of added <see cref="ARFace"/>s.</param>
/// <param name="updated">The list of updated <see cref="ARFace"/>s.</param>
/// <param name="removed">The list of removed <see cref="ARFace"/>s.</param>
protected override void OnTrackablesChanged(
List<ARFace> added,
List<ARFace> updated,
List<ARFace> removed)
{
if (facesChanged != null)
{
using (new ScopedProfiler("OnFacesChanged"))
facesChanged(new ARFacesChangedEventArgs(added, updated, removed));
}
}
/// <summary>
/// Get the prefab that will be instantiated for each <see cref="ARFace"/>. May be `null`.
/// </summary>
/// <returns>The prefab that will be instantiated for each <see cref="ARFace"/>.</returns>
protected override GameObject GetPrefab() => m_FacePrefab;
/// <summary>
/// The name assigned to each `GameObject` belonging to each <see cref="ARFace"/>.
/// </summary>
protected override string gameObjectName => "ARFace";
}
}