XRPlaneSubsystem.cs
11.5 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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
using System;
using Unity.Collections;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.SubsystemsImplementation;
#endif
namespace UnityEngine.XR.ARSubsystems
{
/// <summary>
/// Base class for plane subsystems.
/// </summary>
/// <remarks>
/// This subsystem surfaces information regarding plane (i.e., flat surface) detection in the physical environment.
/// Implementations are typically found in other provider or platform-specific packages.
/// </remarks>
#if UNITY_2020_2_OR_NEWER
public class XRPlaneSubsystem
: TrackingSubsystem<BoundedPlane, XRPlaneSubsystem, XRPlaneSubsystemDescriptor, XRPlaneSubsystem.Provider>
#else
public abstract class XRPlaneSubsystem
: TrackingSubsystem<BoundedPlane, XRPlaneSubsystemDescriptor>
#endif
{
/// <summary>
/// Constructs a plane subsystem. Do not invoked directly; call <c>Create</c> on the <see cref="XRPlaneSubsystemDescriptor"/> instead.
/// </summary>
public XRPlaneSubsystem()
{
#if !UNITY_2020_2_OR_NEWER
provider = CreateProvider();
#endif
}
#if !UNITY_2020_2_OR_NEWER
/// <summary>
/// Start the plane subsystem, i.e., start tracking planes.
/// </summary>
protected sealed override void OnStart() => provider.Start();
/// <summary>
/// Destroy the plane subsystem.
/// </summary>
protected sealed override void OnDestroyed() => provider.Destroy();
/// <summary>
/// Stop the subsystem, i.e., stop tracking planes.
/// </summary>
protected sealed override void OnStop() => provider.Stop();
#endif
/// <summary>
/// Get or set the requested <see cref="PlaneDetectionMode"/>, e.g.,
/// to enable different modes of detection.
/// </summary>
/// <exception cref="System.NotSupportedException">Thrown if <see cref="requestedPlaneDetectionMode"/> is set to
/// something other than <see cref="PlaneDetectionMode.None"/> when plane detection is not supported.</exception>
public PlaneDetectionMode requestedPlaneDetectionMode
{
get => provider.requestedPlaneDetectionMode;
set => provider.requestedPlaneDetectionMode = value;
}
/// <summary>
/// Get the current <see cref="PlaneDetectionMode"/> in use by the provider.
/// </summary>
public PlaneDetectionMode currentPlaneDetectionMode => provider.currentPlaneDetectionMode;
/// <summary>
/// Get the changes (added, updated, and removed) planes since the last call to <see cref="GetChanges(Allocator)"/>.
/// </summary>
/// <param name="allocator">An <c>Allocator</c> to use when allocating the returned <c>NativeArray</c>s.</param>
/// <returns>
/// <see cref="TrackableChanges{T}"/> describing the planes that have been added, updated, and removed
/// since the last call to <see cref="GetChanges(Allocator)"/>. The caller owns the memory allocated with <c>Allocator</c>.
/// </returns>
public override TrackableChanges<BoundedPlane> GetChanges(Allocator allocator)
{
var changes = provider.GetChanges(BoundedPlane.defaultValue, allocator);
#if DEVELOPMENT_BUILD || UNITY_EDITOR
m_ValidationUtility.ValidateAndDisposeIfThrown(changes);
#endif
return changes;
}
/// <summary>
/// Gets the boundary polygon describing the plane.
/// </summary>
/// <param name="trackableId">The <see cref="TrackableId"/> associated with the plane of which to retrieve the boundary.</param>
/// <param name="allocator">An <c>Allocator</c> to use if <paramref name="boundary"/> needs to be created. <c>Allocator.Temp</c> is not supported; use <c>Allocator.TempJob</c> if you need temporary memory.</param>
/// <param name="boundary">The boundary will be stored here. If <c>boundary</c> is the same length as the new boundary,
/// it is simply overwritten with the new data. Otherwise, it is disposed and recreated with the correct length.</param>
public void GetBoundary(
TrackableId trackableId,
Allocator allocator,
ref NativeArray<Vector2> boundary)
{
if (allocator == Allocator.Temp)
throw new InvalidOperationException("Allocator.Temp is not supported. Use Allocator.TempJob if you wish to use a temporary allocator.");
if (allocator == Allocator.None)
throw new InvalidOperationException("Allocator.None is not a valid allocator.");
provider.GetBoundary(trackableId, allocator, ref boundary);
}
#if !UNITY_2020_2_OR_NEWER
/// <summary>
/// Concrete classes must implement this to provide the provider-specific implementation.
/// </summary>
/// <returns></returns>
protected abstract Provider CreateProvider();
#endif
/// <summary>
/// Creates or resizes the <paramref name="array"/> if necessary. If <paramref name="array"/>
/// has been allocated and its length is equal to <paramref name="length"/>, then this method
/// does nothing. If its length is different, then it is first disposed before being assigned
/// to a new <c>NativeArray</c>.
/// </summary>
/// <param name="length">The length that <paramref name="array"/> will have after this method returns.</param>
/// <param name="allocator">If allocation is necessary, this allocator will be used to create the new <c>NativeArray</c>.</param>
/// <param name="array">The array to create or resize.</param>
/// <typeparam name="T">The type of elements held by the <paramref name="array"/>.</typeparam>
protected static void CreateOrResizeNativeArrayIfNecessary<T>(
int length,
Allocator allocator,
ref NativeArray<T> array) where T : struct
{
if (array.IsCreated)
{
if (array.Length != length)
{
array.Dispose();
array = new NativeArray<T>(length, allocator);
}
}
else
{
array = new NativeArray<T>(length, allocator);
}
}
/// <summary>
/// The API that derived classes must implement.
/// </summary>
public abstract class Provider
#if UNITY_2020_2_OR_NEWER
: SubsystemProvider<XRPlaneSubsystem>
#endif
{
#if UNITY_2020_2_OR_NEWER
/// <summary>
/// Creates or resizes the <paramref name="array"/> if necessary. If <paramref name="array"/>
/// has been allocated and its length is equal to <paramref name="length"/>, then this method
/// does nothing. If its length is different, then it is first disposed before being assigned
/// to a new <c>NativeArray</c>.
/// </summary>
/// <param name="length">The length that <paramref name="array"/> will have after this method returns.</param>
/// <param name="allocator">If allocation is necessary, this allocator will be used to create the new <c>NativeArray</c>.</param>
/// <param name="array">The array to create or resize.</param>
/// <typeparam name="T">The type of elements held by the <paramref name="array"/>.</typeparam>
protected static void CreateOrResizeNativeArrayIfNecessary<T>(
int length,
Allocator allocator,
ref NativeArray<T> array) where T : struct
{
if (array.IsCreated)
{
if (array.Length != length)
{
array.Dispose();
array = new NativeArray<T>(length, allocator);
}
}
else
{
array = new NativeArray<T>(length, allocator);
}
}
#else
/// <summary>
/// Start the plane subsystem, i.e., start tracking planes.
/// </summary>
public virtual void Start() { }
/// <summary>
/// Stop the subsystem, i.e., stop tracking planes.
/// </summary>
public virtual void Stop() { }
/// <summary>
/// Destroy the plane subsystem. <see cref="Stop"/> is always called first.
/// </summary>
public virtual void Destroy() { }
#endif
/// <summary>
/// Retrieves the boundary points of the plane with <paramref name="trackableId"/>.
/// </summary>
/// <param name="trackableId">The id of the plane.</param>
/// <param name="allocator">An <c>Allocator</c> to use for the returned <c>NativeArray</c>.</param>
/// <param name="boundary">An existing <c>NativeArray</c> to update or recreate if necessary.
/// See <see cref="CreateOrResizeNativeArrayIfNecessary{T}(int, Allocator, ref NativeArray{T})"/>.</param>
public virtual void GetBoundary(
TrackableId trackableId,
Allocator allocator,
ref NativeArray<Vector2> boundary)
{
throw new NotSupportedException("Boundary vertices are not supported.");
}
/// <summary>
/// Get the changes (added, updated, and removed) planes since the last call to
/// <see cref="GetChanges(BoundedPlane,Allocator)"/>.
/// </summary>
/// <param name="defaultPlane">
/// The default plane. This should be used to initialize the returned <c>NativeArray</c>s for backwards compatibility.
/// See <see cref="TrackableChanges{T}.TrackableChanges(void*, int, void*, int, void*, int, T, int, Allocator)"/>.
/// </param>
/// <param name="allocator">An <c>Allocator</c> to use when allocating the returned <c>NativeArray</c>s.</param>
/// <returns>
/// <see cref="TrackableChanges{T}"/> describing the planes that have been added, updated, and removed
/// since the last call to <see cref="GetChanges(BoundedPlane,Allocator)"/>. The changes should be allocated using
/// <paramref name="allocator"/>.
/// </returns>
public abstract TrackableChanges<BoundedPlane> GetChanges(BoundedPlane defaultPlane, Allocator allocator);
/// <summary>
/// Get or set the requested <see cref="PlaneDetectionMode"/>.
/// </summary>
public virtual PlaneDetectionMode requestedPlaneDetectionMode
{
get => PlaneDetectionMode.None;
set
{
if (value != PlaneDetectionMode.None)
{
throw new NotSupportedException("Plane detection is not supported.");
}
}
}
/// <summary>
/// Get the current plane detection mode in use by the provider.
/// </summary>
public virtual PlaneDetectionMode currentPlaneDetectionMode => PlaneDetectionMode.None;
}
#if !UNITY_2020_2_OR_NEWER
/// <summary>
/// The provider created by the implementation that contains the required plane tracking functionality.
/// </summary>
protected Provider provider { get; }
#endif
#if DEVELOPMENT_BUILD || UNITY_EDITOR
ValidationUtility<BoundedPlane> m_ValidationUtility =
new ValidationUtility<BoundedPlane>();
#endif
}
}