PalmDirectionDetector.cs
7.97 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
/******************************************************************************
* 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 System.Collections;
using Leap.Unity.Attributes;
namespace Leap.Unity {
/**
* Detects whether the palm of the hand is pointing toward the specified direction.
* The detector activates when the palm direction is within OnAngle degrees of the
* desired direction and deactivates when it becomes more than OffAngle degrees.
*
* Directions can be specified relative to the global frame of reference, relative to
* the camera frame of reference, or using a combination of the two -- relative to the
* camera direction in the x-z plane, but not changing relative to the horizon.
*
* You can alternatively specify a target game object.
*
* If added to a HandModelBase instance or one of its children, this detector checks the
* palm direction at the interval specified by the Period variable. You can also specify
* which hand model to observe explicitly by setting handModel in the Unity editor or
* in code.
*
* @since 4.1.2
*/
public class PalmDirectionDetector : Detector {
/**
* The interval at which to check palm direction.
* @since 4.1.2
*/
[Units("seconds")]
[Tooltip("The interval in seconds at which to check this detector's conditions.")]
[MinValue(0)]
public float Period = .1f; //seconds
/**
* The HandModelBase instance to observe.
* Set automatically if not explicitly set in the editor.
* @since 4.1.2
*/
[Tooltip("The hand model to watch. Set automatically if detector is on a hand.")]
public HandModelBase HandModel = null;
/**
* Specifies how to interprete the direction specified by PointingDirection.
*
* - RelativeToCamera -- the target direction is defined relative to the camera's forward vector, i.e. (0, 0, 1) is the cmaera's
* local forward direction.
* - RelativeToHorizon -- the target direction is defined relative to the camera's forward vector,
* except that it does not change with pitch.
* - RelativeToWorld -- the target direction is defined as a global direction that does not change with camera movement. For example,
* (0, 1, 0) is always world up, no matter which way the camera is pointing.
* - AtTarget -- a target object is used as the pointing direction (The specified PointingDirection is ignored).
*
* In VR scenes, RelativeToHorizon with a direction of (0, 0, 1) for camera forward and RelativeToWorld with a direction
* of (0, 1, 0) for absolute up, are often the most useful settings.
* @since 4.1.2
*/
[Header("Direction Settings")]
[Tooltip("How to treat the target direction.")]
public PointingType PointingType = PointingType.RelativeToHorizon;
/**
* The target direction as interpreted by the PointingType setting.
* Ignored when Pointingtype is "AtTarget."
* @since 4.1.2
*/
[Tooltip("The target direction.")]
[DisableIf("PointingType", isEqualTo: PointingType.AtTarget)]
public Vector3 PointingDirection = Vector3.forward;
/**
* The object to point at when the PointingType is "AtTarget." Ignored otherwise.
*/
[Tooltip("A target object(optional). Use PointingType.AtTarget")]
[DisableIf("PointingType", isNotEqualTo: PointingType.AtTarget)]
public Transform TargetObject = null;
/**
* The turn-on angle. The detector activates when the palm points within this
* many degrees of the target direction.
* @since 4.1.2
*/
[Tooltip("The angle in degrees from the target direction at which to turn on.")]
[Range(0, 180)]
public float OnAngle = 45; // degrees
/**
* The turn-off angle. The detector deactivates when the palm points more than this
* many degrees away from the target direction. The off angle must be larger than the on angle.
* @since 4.1.2
*/
[Tooltip("The angle in degrees from the target direction at which to turn off.")]
[Range(0, 180)]
public float OffAngle = 65; //degrees
/** Whether to draw the detector's Gizmos for debugging. (Not every detector provides gizmos.)
* @since 4.1.2
*/
[Header("")]
[Tooltip("Draw this detector's Gizmos, if any. (Gizmos must be on in Unity edtor, too.)")]
public bool ShowGizmos = true;
private IEnumerator watcherCoroutine;
private void OnValidate(){
if( OffAngle < OnAngle){
OffAngle = OnAngle;
}
}
private void Awake () {
watcherCoroutine = palmWatcher();
}
private void OnEnable () {
StartCoroutine(watcherCoroutine);
}
private void OnDisable () {
StopCoroutine(watcherCoroutine);
Deactivate();
}
private IEnumerator palmWatcher() {
Hand hand;
Vector3 normal;
while(true){
if(HandModel != null){
hand = HandModel.GetLeapHand();
if(hand != null){
normal = hand.PalmNormal.ToVector3();
float angleTo = Vector3.Angle(normal, selectedDirection(hand.PalmPosition.ToVector3()));
if(angleTo <= OnAngle){
Activate();
} else if(angleTo > OffAngle) {
Deactivate();
}
}
}
yield return new WaitForSeconds(Period);
}
}
private Vector3 selectedDirection (Vector3 tipPosition) {
switch (PointingType) {
case PointingType.RelativeToHorizon:
Quaternion cameraRot = Camera.main.transform.rotation;
float cameraYaw = cameraRot.eulerAngles.y;
Quaternion rotator = Quaternion.AngleAxis(cameraYaw, Vector3.up);
return rotator * PointingDirection;
case PointingType.RelativeToCamera:
return Camera.main.transform.TransformDirection(PointingDirection);
case PointingType.RelativeToWorld:
return PointingDirection;
case PointingType.AtTarget:
if (TargetObject != null)
return TargetObject.position - tipPosition;
else return Vector3.zero;
default:
return PointingDirection;
}
}
#if UNITY_EDITOR
private void OnDrawGizmos(){
if(ShowGizmos && HandModel != null && HandModel.IsTracked){
Color centerColor;
if (IsActive) {
centerColor = OnColor;
} else {
centerColor = OffColor;
}
Hand hand = HandModel.GetLeapHand();
Utils.DrawCone(hand.PalmPosition.ToVector3(), hand.PalmNormal.ToVector3(), OnAngle, hand.PalmWidth, centerColor, 8);
Utils.DrawCone(hand.PalmPosition.ToVector3(), hand.PalmNormal.ToVector3(), OffAngle, hand.PalmWidth, LimitColor, 8);
Gizmos.color = DirectionColor;
Gizmos.DrawRay(hand.PalmPosition.ToVector3(), selectedDirection(hand.PalmPosition.ToVector3()));
}
}
#endif
}
/**
* Settings for handling pointing conditions
* - RelativeToCamera -- the target direction is defined relative to the camera's forward vector.
* - RelativeToHorizon -- the target direction is defined relative to the camera's forward vector,
* except that it does not change with pitch.
* - RelativeToWorld -- the target direction is defined as a global direction that does not change with camera movement.
* - AtTarget -- a target object is used to determine the pointing direction.
*
* @since 4.1.2
*/
public enum PointingType { RelativeToCamera, RelativeToHorizon, RelativeToWorld, AtTarget }
}