Tanoda
ActivityManager.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
10using Leap.Unity.Space;
11using System;
12using System.Collections.Generic;
13using UnityEngine;
14
15namespace Leap.Unity.Interaction {
16
23 public class ActivityManager<T> {
24
26 public float activationRadius;
27
37 public int activationLayerMask = ~0;
38
44 public Func<int> activationLayerFunction = null;
45
53 public Func<Collider, T> filter = null;
54
55 private HashSet<T> _activeObjects = new HashSet<T>();
59 public HashSet<T> ActiveObjects { get { return _activeObjects; } }
60
65 public bool trackStateChanges = false;
66 private HashSet<T> _activeObjectsLastFrame = new HashSet<T>();
67 private HashSet<T> _beganActiveObjects = new HashSet<T>();
72 public HashSet<T> BeganActive {
73 get { return _beganActiveObjects; }
74 }
75 private HashSet<T> _endedActiveObjects = new HashSet<T>();
80 public HashSet<T> EndedActive {
81 get { return _endedActiveObjects; }
82 }
83
84 public ActivityManager(float activationRadius, Func<Collider, T> filter) {
85 this.activationRadius = activationRadius;
86 this.filter = filter;
87 }
88
89 [ThreadStatic]
90 private static Collider[] s_colliderResultsBuffer = new Collider[32];
91 public void UpdateActivityQuery(Vector3? queryPosition, List<LeapSpace> spaces = null) {
92 using (new ProfilerSample("Update Activity Manager")) {
93 using (new ProfilerSample("Initialize Buffers")) {
94 _activeObjects.Clear();
95
96 // Make sure collider results buffer exists (for other threads; see ThreadStatic)
97 if (s_colliderResultsBuffer == null || s_colliderResultsBuffer.Length < 32) {
98 s_colliderResultsBuffer = new Collider[32];
99 }
100 }
101
102 // Update object activity by activation radius around the query position (PhysX colliders necessary).
103 // queryPosition can be null, in which case no objects will be found, and they will all become inactive.
104 if (queryPosition.HasValue) {
105 Vector3 actualQueryPosition = queryPosition.GetValueOrDefault();
106
107 int count = GetSphereColliderResults(actualQueryPosition, ref s_colliderResultsBuffer);
108 UpdateActiveList(count, s_colliderResultsBuffer);
109
110 using (new ProfilerSample("Check GUI Spaces")) {
111 if (spaces != null) {
112 //Check once in each of the GUI's subspaces
113 foreach (LeapSpace space in spaces) {
114 count = GetSphereColliderResults(transformPoint(actualQueryPosition, space), ref s_colliderResultsBuffer);
115 UpdateActiveList(count, s_colliderResultsBuffer);
116 }
117 }
118 }
119 }
120
121 using (new ProfilerSample("Track State Changes")) {
122 if (trackStateChanges) {
123 _endedActiveObjects.Clear();
124 _beganActiveObjects.Clear();
125
126 foreach (var behaviour in _activeObjects) {
127 if (!_activeObjectsLastFrame.Contains(behaviour)) {
128 _beganActiveObjects.Add(behaviour);
129 }
130 }
131
132 foreach (var behaviour in _activeObjectsLastFrame) {
133 if (!_activeObjects.Contains(behaviour)) {
134 _endedActiveObjects.Add(behaviour);
135 }
136 }
137
138 _activeObjectsLastFrame.Clear();
139 foreach (var behaviour in _activeObjects) {
140 _activeObjectsLastFrame.Add(behaviour);
141 }
142 }
143 }
144 }
145 }
146
147 private int GetSphereColliderResults(Vector3 position, ref Collider[] resultsBuffer) {
148 using (new ProfilerSample("GetSphereColliderResults()")) {
149
151 int overlapCount = 0;
152 while (true) {
153 overlapCount = Physics.OverlapSphereNonAlloc(position,
155 resultsBuffer,
156 layerMask,
157 QueryTriggerInteraction.Collide);
158 if (overlapCount < resultsBuffer.Length) {
159 break;
160 } else {
161 // Non-allocating sphere-overlap fills the existing _resultsBuffer array.
162 // If the output overlapCount is equal to the array's length, there might be more collision results
163 // that couldn't be returned because the array wasn't large enough, so try again with increased length.
164 // The _in, _out argument setup allows allocating a new array from within this function.
165 resultsBuffer = new Collider[resultsBuffer.Length * 2];
166 }
167 }
168 return overlapCount;
169 }
170 }
171
172 private void UpdateActiveList(int numResults, Collider[] results) {
173 if (filter == null) {
174 Debug.LogWarning("[ActivityManager] No filter provided for this ActivityManager; no objects will ever be returned."
175 + "Please make sure you specify a non-null filter property of any ActivityManagers you wish to use.");
176 return;
177 }
178
179 for (int i = 0; i < numResults; i++) {
180 T obj = filter(results[i]);
181 if (obj != null) {
182 _activeObjects.Add(obj);
183 }
184 }
185 }
186
187 private Vector3 transformPoint(Vector3 worldPoint, LeapSpace space) {
188 Vector3 localPalmPos = space.transform.InverseTransformPoint(worldPoint);
189 return space.transform.TransformPoint(space.transformer.InverseTransformPoint(localPalmPos));
190 }
191 }
192}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
ActivityManager is a wrapper around PhysX sphere queries for arbitrary Unity objects....
bool trackStateChanges
If set to true, BeganActive and EndedActive will be calculated and populated every time a new query o...
ActivityManager(float activationRadius, Func< Collider, T > filter)
void UpdateActivityQuery(Vector3? queryPosition, List< LeapSpace > spaces=null)
Func< int > activationLayerFunction
This function, if set to a non-null value, overrides the activationLayerMask setting with the result ...
HashSet< T > ActiveObjects
Returns the currently "active" objects – objects that were within the latest sphere query.
HashSet< T > EndedActive
If trackStateChanges is enabled (on by default), contains the objects that just stopped being active ...
int activationLayerMask
The layer mask against which to query for active objects. The ActivityManager will only find objects ...
HashSet< T > BeganActive
If trackStateChanges is enabled (on by default), contains the objects that just started being active ...
Func< Collider, T > filter
This is the function by which the ActivityManager converts the Colliders it finds through PhysX queri...
float activationRadius
The radius of the query in world-space.
Vector3 InverseTransformPoint(Vector3 localWarpedSpace)
Transform a point from warped space to rect space.
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....