9using System.Collections;
10using System.Collections.Generic;
19 [CustomEditor(typeof(InteractionManager))]
29 SerializedProperty autoGenerateLayerProperty = serializedObject.FindProperty(
"_autoGenerateLayers");
34 "_interactionNoContactLayer",
43 base.OnInspectorGUI();
47 return Application.isPlaying;
50 private void drawInteractionLayerDecorator(SerializedProperty property) {
51 if (!
Physics.GetIgnoreLayerCollision(
target.interactionNoContactLayer.layerIndex,
52 target.contactBoneLayer.layerIndex)) {
53 EditorGUILayout.HelpBox(
"The No Contact layer should NOT collide with the Contact "
54 +
"Bone layer. (Check your layer collision settings in Edit "
55 +
"/Project Settings/Physics.)", MessageType.Error);
58 if (
Physics.GetIgnoreLayerCollision(
target.interactionLayer.layerIndex,
59 target.contactBoneLayer.layerIndex)) {
60 EditorGUILayout.HelpBox(
"The Interaction layer should collide with the Contact "
61 +
"Bone layer. (Check your layer collision settings in Edit "
62 +
"/Project Settings/Physics.)", MessageType.Error);
68 private void drawControllerRuntimeGizmoDecorator(SerializedProperty property) {
69 if (property.boolValue && _runtimeGizmoManager ==
null) {
70 _runtimeGizmoManager = FindObjectOfType<RuntimeGizmoManager>();
72 if (_runtimeGizmoManager ==
null) {
73 EditorGUILayout.Space();
74 EditorGUILayout.Space();
75 EditorGUILayout.HelpBox(
"Draw Controller Runtime Gizmos is checked, but there "
76 +
"is no RuntimeGizmoManager in your scene, or it is "
77 +
"disabled.", MessageType.Warning);
82 private void drawPostControllerRuntimeGizmoDecorator(SerializedProperty property) {
83 if (property.boolValue && _runtimeGizmoManager !=
null) {
89 EditorGUILayout.Space();
90 EditorGUILayout.LabelField(
"Controller Gizmos Legend", EditorStyles.boldLabel);
92 EditorGUI.BeginDisabledGroup(
true);
94 EditorGUILayout.ColorField(
new GUIContent(
"Contact Bone Colliders",
95 "The gizmo color for contact bone colliders "
96 +
"when soft contact is disabled."),
98 EditorGUILayout.ColorField(
new GUIContent(
"Soft Contact Bone Colliders",
99 "The gizmo color for contact bones colliders "
100 +
"when soft contact is enabled."),
103 EditorGUILayout.Space();
104 EditorGUILayout.ColorField(
new GUIContent(
"Hover Points",
105 "The gizmo color for hover points. Gizmo "
106 +
"does not reflect the actual hover radius."),
108 EditorGUILayout.ColorField(
new GUIContent(
"Primary Hover Points",
109 "The gizmo color for primary hover points."),
112 EditorGUILayout.Space();
113 EditorGUILayout.ColorField(
new GUIContent(
"Grasp Points",
114 "The gizmo color for grasp points. "
115 +
"InteractionHands do not use grasp points, "
116 +
"so no gizmo is drawn for them."),
118 EditorGUILayout.ColorField(
new GUIContent(
"Graspable Objects",
119 "The gizmo color for the wire sphere "
120 +
"that appears at objects when they are "
121 +
"graspable by an interaction controller. "),
124 EditorGUI.EndDisabledGroup();
127 private void drawControllersStatusEditor(SerializedProperty property) {
128 EditorGUILayout.Space();
129 EditorGUILayout.LabelField(
"Interaction Controller Status", EditorStyles.boldLabel);
131 if (
target.interactionControllers.Count == 0) {
132 EditorGUILayout.HelpBox(
"This Interaction Manager has no interaction controllers "
133 +
"assigned to it. Please add at least one InteractionHand "
134 +
"or an InteractionVRController as a child of this object.",
135 MessageType.Warning);
140 EditorGUILayout.BeginVertical();
142 _leftVRNodeController =
null;
143 _rightVRNodeController =
null;
144 foreach (var controller
in target.interactionControllers) {
145 EditorGUILayout.BeginHorizontal();
147 drawControllerStatusEditor(controller);
149 EditorGUILayout.EndHorizontal();
152 EditorGUILayout.EndVertical();
155 public static class Colors {
156 public static Color DarkGray {
get {
return new Color(0.4F, 0.4F, 0.4F); } }
157 public static Color LightGray {
get {
return new Color(0.7F, 0.7F, 0.7F); } }
159 public static Color Good {
get {
return Color.Lerp(
Color.green, LightGray, 0.2F); } }
160 public static Color Caution {
get {
return Color.Lerp(Good,
Color.yellow, 0.8F); } }
165 private struct ControllerStatusMessage {
166 public string message;
167 public string tooltip;
170 private List<ControllerStatusMessage> statusMessagesBuffer =
new List<ControllerStatusMessage>();
172 private void drawControllerStatusEditor(InteractionController controller) {
174 EditorGUI.BeginDisabledGroup(
true);
175 EditorGUILayout.ObjectField(controller, typeof(InteractionController),
true);
176 EditorGUI.EndDisabledGroup();
179 var messages = statusMessagesBuffer;
183 checkTrackingStatus(controller, messages);
185 if (controller.intHand !=
null) {
186 checkInteractionHandStatus(controller.intHand, messages);
188 else if (controller is InteractionXRController) {
189 checkInteractionVRControllerStatus(controller as InteractionXRController, messages);
193 Rect statusMessagesRect = EditorGUILayout.BeginVertical(GUILayout.MinHeight(20));
195 EditorGUI.DrawRect(statusMessagesRect, Colors.DarkGray);
196 statusMessagesRect = statusMessagesRect.ShrinkOne();
197 EditorGUI.DrawRect(statusMessagesRect, Colors.LightGray);
198 statusMessagesRect = statusMessagesRect.ShrinkOne();
199 EditorGUI.DrawRect(statusMessagesRect, Colors.DarkGray);
201 if (messages.Count == 0) {
202 messages.Add(
new ControllerStatusMessage() {
203 message =
"No Status Messages",
209 foreach (var statusMessage
in messages) {
210 var messageColorStyle =
new GUIStyle(EditorStyles.label);
211 messageColorStyle.normal.textColor = statusMessage.color;
213 EditorGUILayout.LabelField(
new GUIContent(
"[" + statusMessage.message +
"]",
214 statusMessage.tooltip),
220 EditorGUILayout.EndVertical();
223 private void checkTrackingStatus(InteractionController controller,
224 List<ControllerStatusMessage> messages) {
225 if (Application.isPlaying) {
226 if (controller.isTracked) {
227 if (controller.isBeingMoved) {
228 messages.Add(
new ControllerStatusMessage() {
230 tooltip =
"This interaction controller is currently being tracked.",
234 messages.Add(
new ControllerStatusMessage() {
235 message =
"Not Moving",
236 tooltip =
"This interaction controller is currently not being moved.",
237 color = Colors.Caution
241 messages.Add(
new ControllerStatusMessage() {
242 message =
"Untracked",
243 tooltip =
"This interaction controller is not currently being tracked.",
244 color = Colors.Warning
250 private LeapProvider _provider =
null;
252 private void checkInteractionHandStatus(InteractionHand intHand,
253 List<ControllerStatusMessage> messages) {
254 if (!Application.isPlaying) {
257 messages.Add(
new ControllerStatusMessage() {
258 message =
"HandDataMode: Custom",
259 tooltip =
"This interaction hand has its data mode set to Custom. "
260 +
"A custom script will be required to ensure hand data gets to "
261 +
"the interaction hand properly. Upon pressing play, an error will "
262 +
"be raised by the hand itself if it is misconfigured.",
263 color = Colors.Caution
268 if (_provider ==
null) {
269 _provider = FindObjectOfType<LeapProvider>();
271 if (_provider ==
null) {
272 messages.Add(
new ControllerStatusMessage() {
273 message =
"No LeapProvider",
274 tooltip =
"No LeapProvider object was found in your scene. "
275 +
"InteractionHands require a LeapProvider to function; consider "
276 +
"dragging in the LeapHeadMountedRig prefab or creating and "
277 +
"configuring a LeapServiceProvider.",
278 color = Colors.Warning
286 int index =
target.interactionControllers.Query().IndexOf(intHand);
288 if (
target.interactionControllers.Query().
290 OfType<InteractionHand>().
291 Where(h => h.handDataMode == intHand.handDataMode).
292 Where(h => h.leapProvider == intHand.leapProvider).
294 messages.Add(
new ControllerStatusMessage() {
295 message =
"Duplicate Hand",
296 tooltip =
"You already have a hand with this data mode in your scene. "
297 +
"You should remove one of the duplicates.",
298 color = Colors.Problem
304 private InteractionXRController _leftVRNodeController;
305 private InteractionXRController _rightVRNodeController;
307 private void checkInteractionVRControllerStatus(InteractionXRController controller,
308 List<ControllerStatusMessage> messages) {
311 if (controller.isUsingCustomTracking) {
312 messages.Add(
new ControllerStatusMessage() {
313 message =
"Custom Tracking Provider",
314 tooltip =
"You are using a custom tracking provider for this VR controller.",
315 color = Colors.Caution
320 bool isLeftVRNodeController = controller.trackingProvider is DefaultXRNodeTrackingProvider
321 && controller.chirality ==
Chirality.Left;
322 bool isRightVRNodeController = controller.trackingProvider is DefaultXRNodeTrackingProvider
323 && controller.chirality ==
Chirality.Right;
325 if (isLeftVRNodeController && _leftVRNodeController !=
null
326 || isRightVRNodeController && _rightVRNodeController !=
null) {
328 var alreadyExistsController = isLeftVRNodeController ? _leftVRNodeController : _rightVRNodeController;
334 if (controller.deviceJoystickTokens.Equals(alreadyExistsController.deviceJoystickTokens)) {
335 message =
"Duplicate VR Controller";
336 tooltip =
"You already have a VRNode controller with this chirality and device "
337 +
"string in your scene. You should remove one of the duplicates.";
338 color = Colors.Problem;
340 message =
"Multiple VR Controllers";
341 tooltip =
"You have multiple VR controllers of the same chirality enabled with "
342 +
"different device strings. If both device strings match attached "
343 +
"Unity joysticks, you may get duplicate controllers.";
344 color = Colors.Caution;
347 messages.Add(
new ControllerStatusMessage() {
354 if (isLeftVRNodeController) {
355 _leftVRNodeController = controller;
357 if (isRightVRNodeController) {
358 _rightVRNodeController = controller;
361 string wrongChiralityToken = controller.isLeft ?
"right" :
"left";
362 if (controller.deviceJoystickTokens.Contains(wrongChiralityToken)) {
363 messages.Add(
new ControllerStatusMessage() {
364 message =
"Wrong Chirality?",
365 tooltip =
"This VR controller's device joystick string specifies a chirality "
366 +
"that is different from the chirality of the controller itself. You "
367 +
"should confirm this controller's device string or chirality setting.",
368 color = Colors.Warning
376 public static class Extensions {
378 public static Rect ShrinkOne(
this Rect rect) {
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 specifyCustomPostDecorator(string propertyName, Action< SerializedProperty > decoratorDrawer)
Specify a callback to be used to draw a decorator AFTER a specific named property.
void specifyCustomDrawer(string propertyName, Action< SerializedProperty > propertyDrawer)
Specify a callback to be used to draw a specific named property. Should be called in OnEnable.
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 ...
void drawControllerRuntimeGizmosColorLegend()
override bool RequiresConstantRepaint()
override void OnInspectorGUI()