AbstractHoldDetector.cs
7.03 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
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2017. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using UnityEngine;
using Leap.Unity.Attributes;
namespace Leap.Unity {
/**
* A base class for implementing detectors that detect a holding pose of a hand.
*
* Such detectors might use the PinchStrength, PinchDistance, GrabStrength, or GrabAngle
* properties of the Hand or might use a more complex heuristic.
*/
public abstract class AbstractHoldDetector : Detector {
/** Implementations must implement this method. */
protected abstract void ensureUpToDate();
[SerializeField]
protected HandModelBase _handModel;
public HandModelBase HandModel { get { return _handModel; } set { _handModel = value; } }
/**
* Whether the Transform of the object containing this Detector script
* is transformed by the Position and Rotation of the hand when IsHolding is true.
*
* If false, the Transform is not affected.
*/
[Tooltip("Whether to change the transform of the parent object.")]
public bool ControlsTransform = true;
/** Whether to draw the detector's Gizmos for debugging. (Not every detector provides gizmos.)
* @since 4.1.2
*/
[Tooltip("Draw this detector's Gizmos, if any. (Gizmos must be on in Unity edtor, too.)")]
public bool ShowGizmos = true;
protected int _lastUpdateFrame = -1;
protected bool _didChange = false;
protected Vector3 _position;
protected Quaternion _rotation;
protected Vector3 _direction = Vector3.forward;
protected Vector3 _normal = Vector3.up;
protected float _distance;
protected float _lastHoldTime = 0.0f;
protected float _lastReleaseTime = 0.0f;
protected Vector3 _lastPosition = Vector3.zero;
protected Quaternion _lastRotation = Quaternion.identity;
protected Vector3 _lastDirection = Vector3.forward;
protected Vector3 _lastNormal = Vector3.up;
protected float _lastDistance = 1.0f;
protected virtual void Awake() {
if (GetComponent<HandModelBase>() != null && ControlsTransform == true) {
Debug.LogWarning("Detector should not be control the HandModelBase's transform. Either attach it to its own transform or set ControlsTransform to false.");
}
if (_handModel == null) {
_handModel = GetComponentInParent<HandModelBase>();
if (_handModel == null) {
Debug.LogWarning("The HandModel field of Detector was unassigned and the detector has been disabled.");
enabled = false;
}
}
}
protected virtual void Update() {
//We ensure the data is up to date at all times because
//there are some values (like LastPinchTime) that cannot
//be updated on demand
ensureUpToDate();
}
/// <summary>
/// Returns whether or not the dectector is currently detecting a pinch or grab.
/// </summary>
public virtual bool IsHolding {
get {
ensureUpToDate();
return IsActive;
}
}
/// <summary>
/// Returns whether or not the value of IsPinching is different than the value reported during
/// the previous frame.
/// </summary>
public virtual bool DidChangeFromLastFrame {
get {
ensureUpToDate();
return _didChange;
}
}
/// <summary>
/// Returns whether or not the value of IsHolding changed to true between this frame and the previous.
/// </summary>
public virtual bool DidStartHold {
get {
ensureUpToDate();
return DidChangeFromLastFrame && IsHolding;
}
}
/// <summary>
/// Returns whether or not the value of IsHolding changed to false between this frame and the previous.
/// </summary>
public virtual bool DidRelease {
get {
ensureUpToDate();
return DidChangeFromLastFrame && !IsHolding;
}
}
/// <summary>
/// Returns the value of Time.time during the most recent pinch event.
/// </summary>
public float LastHoldTime {
get {
ensureUpToDate();
return _lastHoldTime;
}
}
/// <summary>
/// Returns the value of Time.time during the most recent unpinch event.
/// </summary>
public float LastReleaseTime {
get {
ensureUpToDate();
return _lastReleaseTime;
}
}
/// <summary>
/// Returns the position value of the detected pinch or grab. If a pinch or grab is not currently being
/// detected, returns the most recent position value.
/// </summary>
public Vector3 Position {
get {
ensureUpToDate();
return _position;
}
}
public Vector3 LastActivePosition { get { return _lastPosition; } }
/// <summary>
/// Returns the rotation value of the detected pinch or grab. If a pinch or grab is not currently being
/// detected, returns the most recent rotation value.
/// </summary>
public Quaternion Rotation {
get {
ensureUpToDate();
return _rotation;
}
}
public Quaternion LastActiveRotation { get { return _lastRotation; } }
public Vector3 Direction { get { return _direction; } }
public Vector3 LastActiveDirection { get { return _lastDirection; } }
public Vector3 Normal { get { return _normal; } }
public Vector3 LastActiveNormal { get { return _lastNormal; } }
public float Distance { get { return _distance; } }
public float LastActiveDistance { get { return _lastDistance; } }
protected virtual void changeState(bool shouldBeActive) {
bool currentState = IsActive;
if (shouldBeActive) {
_lastHoldTime = Time.time;
Activate();
} else {
_lastReleaseTime = Time.time;
Deactivate();
}
if (currentState != IsActive) {
_didChange = true;
}
}
#if UNITY_EDITOR
protected virtual void OnDrawGizmos () {
if (ShowGizmos) {
ensureUpToDate();
Color centerColor;
Vector3 centerPosition = _position;
Quaternion circleRotation = _rotation;
if (IsHolding) {
centerColor = OnColor;
} else {
centerColor = OffColor;
}
Vector3 axis;
float angle;
circleRotation.ToAngleAxis(out angle, out axis);
Utils.DrawCircle(centerPosition, Normal, Distance / 2, centerColor);
Gizmos.color = NormalColor;
Gizmos.DrawLine(centerPosition, centerPosition + Direction * Distance / 2);
Gizmos.color = DirectionColor;
Gizmos.DrawLine(centerPosition, centerPosition + Normal * Distance / 2);
}
}
#endif
}
}