Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
d2871d28eThis file is pinned to the selected release. Download the original to open it in your design tool.
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2018. *
* 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 Leap.Unity.Query;
using UnityEditor;
using UnityEngine;
namespace Leap.Unity.Interaction {
[CanEditMultipleObjects]
[CustomEditor(typeof(InteractionBehaviour), editorForChildClasses: true)]
public class InteractionBehaviourEditor : CustomEditorBase<InteractionBehaviour> {
private EnumEventTableEditor _tableEditor;
protected override void OnEnable() {
base.OnEnable();
// Interaction Manager hookup.
specifyCustomDecorator("_manager", drawInteractionManagerDecorator);
deferProperty("_eventTable");
specifyCustomDrawer("_eventTable", drawEventTable);
specifyConditionalDrawing(() => !targets.Query().All(intObj => intObj.ignoreContact),
"_contactForceMode");
specifyConditionalDrawing(() => !targets.Query().All(intObj => intObj.ignoreGrasping),
"_allowMultiGrasp",
"_moveObjectWhenGrasped",
"graspedMovementType");
// Layer Overrides
specifyConditionalDrawing(() => targets.Query().Any(intObj => intObj.overrideInteractionLayer),
"_interactionLayer");
specifyCustomDecorator("_interactionLayer", drawInteractionLayerDecorator);
specifyConditionalDrawing(() => targets.Query().Any(intObj => intObj.overrideNoContactLayer),
"_noContactLayer");
specifyCustomDecorator("_noContactLayer", drawNoContactLayerDecorator);
}
private void drawInteractionManagerDecorator(SerializedProperty property) {
bool shouldDrawInteractionManagerNotSetWarning = false;
foreach (var target in targets) {
if (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab) continue;
if (target.manager == null) {
shouldDrawInteractionManagerNotSetWarning = true;
break;
}
}
if (shouldDrawInteractionManagerNotSetWarning) {
bool pluralTargets = targets.Length > 1;
string noManagerSetWarningMessage = "";
if (pluralTargets) {
noManagerSetWarningMessage = "One or more of the currently selected interaction "
+ "objects doesn't have its Interaction Manager set. ";
}
else {
noManagerSetWarningMessage = "The currently selected interaction object doesn't "
+ "have its Interaction Manager set. ";
}
noManagerSetWarningMessage += " Object validation requires a configured manager "
+ "property.";
drawSetManagerWarningBox(noManagerSetWarningMessage, MessageType.Error);
}
}
private void drawSetManagerWarningBox(string warningMessage, MessageType messageType) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.HelpBox(warningMessage, messageType);
Rect buttonRect = EditorGUILayout.GetControlRect(GUILayout.MaxWidth(100F),
GUILayout.ExpandHeight(true),
GUILayout.MaxHeight(40F));
InteractionManager manager = InteractionManager.instance;
EditorGUI.BeginDisabledGroup(manager == null);
if (GUI.Button(buttonRect, new GUIContent("Auto-Fix",
manager == null ? "Please add an Interaction Manager to "
+ "your scene."
: "Use InteractionManager.instance to "
+ "automatically set the manager of the "
+ "selected interaction objects."))) {
if (manager == null) {
Debug.LogError("Attempt to find an InteractionManager instance failed. Is there "
+ "an InteractionManager in your scene?");
}
else {
foreach (var target in targets) {
if (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab) continue;
Undo.RecordObject(target, "Auto-set Interaction Manager");
target.manager = manager;
}
}
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
}
private void drawInteractionLayerDecorator(SerializedProperty property) {
bool shouldDrawWarning = false;
foreach (var target in targets) {
if (target.manager == null) continue; // Can't check.
if (target.overrideInteractionLayer
&& !target.manager.autoGenerateLayers
&& Physics.GetIgnoreLayerCollision(target.interactionLayer.layerIndex,
target.manager.contactBoneLayer.layerIndex)) {
shouldDrawWarning = true;
break;
}
}
if (shouldDrawWarning) {
bool pluralTargets = targets.Length > 1;
string message;
if (pluralTargets) {
message = "One or more of the selected interaction objects has its "
+ "Interaction layer set NOT to collide with the contact bone "
+ "layer. ";
}
else {
message = "The selected interaction object has its Interaction layer set "
+ "NOT to collide with the contact bone layer. ";
}
message += "This will prevent an interaction object from supporting contact with "
+ "any hands or controllers.";
EditorGUILayout.HelpBox(message, MessageType.Warning);
}
}
private void drawNoContactLayerDecorator(SerializedProperty property) {
bool shouldDrawCollisionWarning = false;
foreach (var target in targets) {
if (target.manager == null) continue; // Can't check.
if (target.overrideNoContactLayer
&& !target.manager.autoGenerateLayers
&& !Physics.GetIgnoreLayerCollision(target.noContactLayer.layerIndex,
target.manager.contactBoneLayer.layerIndex)) {
shouldDrawCollisionWarning = true;
break;
}
}
if (shouldDrawCollisionWarning) {
bool pluralTargets = targets.Length > 1;
string noContactErrorMessage;
if (pluralTargets) {
noContactErrorMessage = "One or more selected interaction objects has its No "
+ "Contact layer set to collide with the contact bone "
+ "layer. ";
}
else {
noContactErrorMessage = "This interaction object has its No Contact layer set "
+ "to collide with the contact bone layer. ";
}
noContactErrorMessage += "Please ensure the Interaction Manager's contact bone "
+ "layer is set not to collide with any interaction "
+ "object's No Contact layer.";
EditorGUILayout.HelpBox(noContactErrorMessage, MessageType.Error);
}
}
public override void OnInspectorGUI() {
checkHasColliders();
base.OnInspectorGUI();
}
private void checkHasColliders() {
bool anyMissingColliders = false;
foreach (var singleTarget in targets) {
if (singleTarget.GetComponentsInChildren<Collider>().Length == 0) {
anyMissingColliders = true; break;
}
}
if (anyMissingColliders) {
bool pluralObjects = targets.Length > 1;
string message;
if (pluralObjects) {
message = "One or more of the currently selected interaction objects have no "
+ "colliders. Interaction objects without any Colliders cannot be "
+ "interacted with.";
}
else {
message = "This interaction object has no Colliders. Interaction objects "
+ "without any Colliders cannot be interacted with.";
}
EditorGUILayout.HelpBox(message, MessageType.Warning);
}
}
private void drawEventTable(SerializedProperty property) {
if (_tableEditor == null) {
_tableEditor = new EnumEventTableEditor(property, typeof(InteractionBehaviour.EventType));
}
_tableEditor.DoGuiLayout();
}
}
}