Tanoda
LeapServiceProviderEditor.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
9using LeapInternal;
10using System;
11using System.Collections.Generic;
12using System.IO;
13using System.Linq;
14using System.Text.RegularExpressions;
15using UnityEditor;
16using UnityEngine;
17
18namespace Leap.Unity {
19
20 [CustomEditor(typeof(LeapServiceProvider))]
21 public class LeapServiceProviderEditor : CustomEditorBase<LeapServiceProvider> {
22
23 internal const float INTERACTION_VOLUME_MODEL_IMPORT_SCALE_FACTOR = 0.001f;
24
25 protected Quaternion deviceRotation = Quaternion.identity;
26 protected bool isVRProvider = false;
27
28 protected Vector3 controllerOffset = Vector3.zero;
29
30 private const float LMC_BOX_RADIUS = 0.45f;
31 private const float LMC_BOX_WIDTH = 0.965f;
32 private const float LMC_BOX_DEPTH = 0.6671f;
33
34 private Mesh _stereoIR170InteractionZoneMesh;
35 private Material _stereoIR170InteractionMaterial;
36 private readonly Vector3 _stereoIR170InteractionZoneMeshOffset = new Vector3(0.0523f, 0, 0.005f);
37
38 private LeapServiceProvider _leapServiceProvider;
39 private Controller _leapController;
40
41
42 protected override void OnEnable() {
43
44 base.OnEnable();
45
46 ParseStereoIR170InteractionMeshData();
47
48 specifyCustomDecorator("_frameOptimization", frameOptimizationWarning);
49
50 specifyConditionalDrawing("_frameOptimization",
52 "_physicsExtrapolation",
53 "_physicsExtrapolationTime");
54
55 specifyConditionalDrawing("_physicsExtrapolation",
57 "_physicsExtrapolationTime");
58
59 deferProperty("_serverNameSpace");
60 deferProperty("_workerThreadProfiling");
61
63 addPropertyToFoldout("_trackingOptimization", "Advanced Options");
64 }
65 addPropertyToFoldout("_workerThreadProfiling", "Advanced Options");
66 addPropertyToFoldout("_serverNameSpace" , "Advanced Options");
67 }
68
69 private void frameOptimizationWarning(SerializedProperty property) {
70 var mode = (LeapServiceProvider.FrameOptimizationMode)property.intValue;
71 string warningText;
72
73 switch (mode) {
74 case LeapServiceProvider.FrameOptimizationMode.ReuseUpdateForPhysics:
75 warningText = "Reusing update frames for physics introduces a frame of latency "
76 + "for physics interactions.";
77 break;
78 case LeapServiceProvider.FrameOptimizationMode.ReusePhysicsForUpdate:
79 warningText = "This optimization REQUIRES physics framerate to match your "
80 + "target framerate EXACTLY.";
81 break;
82 default:
83 return;
84 }
85
86 EditorGUILayout.HelpBox(warningText, MessageType.Warning);
87 }
88
89 public override void OnInspectorGUI() {
90
91#if UNITY_2019_3_OR_NEWER
92 // Easily tracking VR-enabled-or-not requires an XR package installed, so remove this warning for now.
93#else
94 if (UnityEditor.PlayerSettings.virtualRealitySupported && !isVRProvider) {
95 EditorGUILayout.HelpBox(
96 "VR support is enabled. If your Leap is mounted to your headset, you should be "
97 + "using LeapXRServiceProvider instead of LeapServiceProvider. (If your Leap "
98 + "is not mounted to your headset, you can safely ignore this warning.)",
99 MessageType.Warning);
100 }
101#endif
102
103 base.OnInspectorGUI();
104 }
105
106 public virtual void OnSceneGUI() {
107
108 switch (GetSelectedInteractionVolume()) {
110 break;
111 case LeapServiceProvider.InteractionVolumeVisualization.LeapMotionController:
112 DrawLeapMotionControllerInteractionZone(LMC_BOX_WIDTH, LMC_BOX_DEPTH, LMC_BOX_RADIUS, Color.white);
113 break;
115 DrawStereoIR170InteractionZoneMesh();
116 break;
118 DetectConnectedDevice();
119 break;
120 default:
121 break;
122 }
123
124 }
125
126 private void ParseStereoIR170InteractionMeshData() {
127
128 if (_stereoIR170InteractionZoneMesh == null) {
129 _stereoIR170InteractionZoneMesh = (Mesh)AssetDatabase.LoadAssetAtPath(Path.Combine("Assets", "Plugins", "LeapMotion", "Core", "Models", "StereoIR170-interaction-cone.obj"), typeof(Mesh));
130 }
131
132 if (_stereoIR170InteractionMaterial == null) {
133 _stereoIR170InteractionMaterial = (Material)AssetDatabase.LoadAssetAtPath(Path.Combine("Assets", "Plugins", "LeapMotion", "Core", "Materials", "StereoIR170InteractionVolume.mat"), typeof(Material));
134 }
135
136 }
137
139 get {
140
141 if (this._leapServiceProvider != null) {
142 return this._leapServiceProvider;
143 }
144 else {
145 this._leapServiceProvider = this.target.GetComponent<LeapServiceProvider>();
146
147 return this._leapServiceProvider;
148 }
149 }
150 }
151
152 private Controller LeapController {
153 get {
154
155 if (this._leapController != null) {
156 return this._leapController;
157 }
158 else
159 {
160 this._leapController = LeapServiceProvider?.GetLeapController();
161
162 if (this._leapController != null) {
163 this._leapController.Device += _leapController_DeviceChanged;
164 this._leapController.DeviceLost += _leapController_DeviceChanged;
165 }
166
167 return this._leapController;
168 }
169 }
170 }
171
172 private void _leapController_DeviceChanged(object sender, DeviceEventArgs e) {
173 EditorWindow view = EditorWindow.GetWindow<SceneView>();
174 view.Repaint();
175 }
176
177 private void DetectConnectedDevice() {
178
179 if (LeapController?.Devices?.Count == 1)
180 {
181 if (LeapController.Devices.First().Type == Device.DeviceType.TYPE_RIGEL) {
182 DrawStereoIR170InteractionZoneMesh();
183 }
184 else if (LeapController.Devices.First().Type == Device.DeviceType.TYPE_PERIPHERAL) {
185 DrawLeapMotionControllerInteractionZone(LMC_BOX_WIDTH, LMC_BOX_DEPTH, LMC_BOX_RADIUS, Color.white);
186 }
187 }
188 }
189
190 private LeapServiceProvider.InteractionVolumeVisualization? GetSelectedInteractionVolume() {
191
193 }
194
195 private void DrawStereoIR170InteractionZoneMesh() {
196
197 if (_stereoIR170InteractionMaterial != null && _stereoIR170InteractionZoneMesh != null) {
198 _stereoIR170InteractionMaterial.SetPass(0);
199
200 Graphics.DrawMeshNow(_stereoIR170InteractionZoneMesh,
201 target.transform.localToWorldMatrix *
202 Matrix4x4.TRS(controllerOffset + _stereoIR170InteractionZoneMeshOffset, deviceRotation * Quaternion.Euler(-90, 0, 0), Vector3.one * 0.001f));
203 }
204 }
205
206 private void DrawLeapMotionControllerInteractionZone(float box_width, float box_depth, float box_radius, Color interactionZoneColor) {
207
208 Color previousColor = Handles.color;
209 Handles.color = interactionZoneColor;
210
211 Vector3 origin = target.transform.TransformPoint(controllerOffset);
212 Vector3 local_top_left, top_left, local_top_right, top_right, local_bottom_left, bottom_left, local_bottom_right, bottom_right;
213 getLocalGlobalPoint(-1, 1, 1, box_width, box_depth, box_radius, out local_top_left , out top_left);
214 getLocalGlobalPoint( 1, 1, 1, box_width, box_depth, box_radius, out local_top_right , out top_right);
215 getLocalGlobalPoint(-1, 1, -1, box_width, box_depth, box_radius, out local_bottom_left , out bottom_left);
216 getLocalGlobalPoint( 1, 1, -1, box_width, box_depth, box_radius, out local_bottom_right, out bottom_right);
217
218 Handles.DrawAAPolyLine(origin, top_left);
219 Handles.DrawAAPolyLine(origin, top_right);
220 Handles.DrawAAPolyLine(origin, bottom_left);
221 Handles.DrawAAPolyLine(origin, bottom_right);
222
223 drawControllerEdge(origin, local_top_left, local_top_right, box_radius);
224 drawControllerEdge(origin, local_bottom_left, local_top_left, box_radius);
225 drawControllerEdge(origin, local_bottom_left, local_bottom_right, box_radius);
226 drawControllerEdge(origin, local_bottom_right, local_top_right, box_radius);
227
228 drawControllerArc(origin, local_top_left, local_bottom_left, local_top_right,
229 local_bottom_right, box_radius);
230 drawControllerArc(origin, local_top_left, local_top_right, local_bottom_left,
231 local_bottom_right, box_radius);
232
233 Handles.color = previousColor;
234 }
235
236 private void getLocalGlobalPoint(int x, int y, int z, float box_width, float box_depth, float box_radius, out Vector3 local, out Vector3 global) {
237
238 local = deviceRotation * new Vector3(x * box_width, y * box_radius, z * box_depth);
239 global = target.transform.TransformPoint(controllerOffset
240 + box_radius * local.normalized);
241 }
242
243 private void drawControllerEdge(Vector3 origin,
244 Vector3 edge0, Vector3 edge1,
245 float box_radius) {
246 Vector3 right_normal = target.transform
247 .TransformDirection(Vector3.Cross(edge0, edge1));
248 float right_angle = Vector3.Angle(edge0, edge1);
249
250 Handles.DrawWireArc(origin, right_normal, target.transform.TransformDirection(edge0),
251 right_angle, target.transform.lossyScale.x * box_radius);
252 }
253
254 private void drawControllerArc(Vector3 origin,
255 Vector3 edgeA0, Vector3 edgeA1,
256 Vector3 edgeB0, Vector3 edgeB1,
257 float box_radius) {
258
259 Vector3 faceA = target.transform.rotation * Vector3.Lerp(edgeA0, edgeA1, 0.5f);
260 Vector3 faceB = target.transform.rotation * Vector3.Lerp(edgeB0, edgeB1, 0.5f);
261
262 float resolutionIncrement = 1f / 50f;
263 for (float i = 0f; i < 1f; i += resolutionIncrement) {
264 Vector3 begin = Vector3.Lerp(faceA, faceB, i).normalized
265 * target.transform.lossyScale.x * box_radius;
266 Vector3 end = Vector3.Lerp(faceA, faceB, i + resolutionIncrement).normalized
267 * target.transform.lossyScale.x * box_radius;
268
269 Handles.DrawAAPolyLine(origin + begin, origin + end);
270 }
271 }
272 }
273}
274
275
UnityEngine.Color Color
Definition: TestScript.cs:32
The Controller class is your main interface to the Leap Motion Controller.
EventHandler< DeviceEventArgs > DeviceLost
Dispatched when a Leap Motion device is disconnected.
DeviceList Devices
The list of currently attached and recognized Leap Motion controller devices.
EventHandler< DeviceEventArgs > Device
Dispatched when a Leap Motion device is connected.
Dispatched when a device is plugged in.
Definition: Events.cs:181
The Device class represents a physically connected device.
Definition: Device.cs:29
DeviceType
The available types of Leap Motion controllers.
Definition: Device.cs:265
void specifyConditionalDrawing(string conditionalName, params string[] dependantProperties)
Specify a list of properties that should only be displayed if the conditional property has a value of...
void deferProperty(string propertyName)
Defer rendering of a property until the end of the inspector. Deferred properties are drawn in the RE...
void addPropertyToFoldout(string propertyName, string foldoutName, bool foldoutStartOpen=false)
Condition the drawing of a property based on the status of a foldout drop-down.
void specifyCustomDecorator(string propertyName, Action< SerializedProperty > decoratorDrawer)
Specify a callback to be used to draw a decorator for a specific named property. Should be called in ...
The LeapServiceProvider provides tracked Leap Hand data and images from the device via the Leap servi...
Controller GetLeapController()
Returns the Leap Controller instance.
InteractionVolumeVisualization SelectedInteractionVolumeVisualization
The LeapXRServiceProvider expands on the standard LeapServiceProvider to account for the offset of th...