Tanoda
AnchorableBehaviourEditor.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 Leap.Unity;
10using Leap.Unity.Query;
11using System.Collections;
12using System.Collections.Generic;
13using UnityEditor;
14using UnityEngine;
15
16namespace Leap.Unity.Interaction {
17
18 [CanEditMultipleObjects]
19 [CustomEditor(typeof(AnchorableBehaviour))]
20 public class AnchorableBehaviourEditor : CustomEditorBase<AnchorableBehaviour> {
21
22 protected override void OnEnable() {
23 base.OnEnable();
24
25 deferProperty("_eventTable");
26 specifyCustomDrawer("_eventTable", drawEventTable);
27
28 specifyConditionalDrawing("lockWhenAttached",
29 "matchAnchorMotionWhileAttaching");
30
31 specifyConditionalDrawing("useTrajectory",
32 "_motionlessRangeFraction",
33 "_maxMotionlessRange",
34 "_maxAttachmentAngle");
35
36 specifyConditionalDrawing(() => { return target.interactionBehaviour != null; },
37 "detachWhenGrasped",
38 "_tryAnchorNearestOnGraspEnd",
39 "isAttractedByHand",
40 "maxAttractionReach",
41 "attractionReachByDistance");
42
43 specifyConditionalDrawing("isAttractedByHand",
44 "maxAttractionReach",
45 "attractionReachByDistance");
46 }
47
48 private EnumEventTableEditor _tableEditor;
49 private void drawEventTable(SerializedProperty property) {
50 if (_tableEditor == null) {
51 _tableEditor = new EnumEventTableEditor(property, typeof(AnchorableBehaviour.EventType));
52 }
53
54 _tableEditor.DoGuiLayout();
55 }
56
57 public override void OnInspectorGUI() {
58 drawWarningMessages();
59
60 drawAttachmentHelperButtons();
61
62 base.OnInspectorGUI();
63 }
64
65 private void drawWarningMessages() {
66 // While the editor application is playing, we expect there to be at least the empty lambda that initializes the Action
67 // and the UnityEvent subscription.
68 // While in edit-mode, we only expect there to be the empty lambda that initializes the Action.
69 int expectedMinimumActionListeners = EditorApplication.isPlaying ? 2 : 1;
70
71 bool hasInvalidPostGraspEndCallback = !target.tryAnchorNearestOnGraspEnd
72 && (target.OnPostTryAnchorOnGraspEnd.GetInvocationList().Length > expectedMinimumActionListeners
73 || (_tableEditor != null &&
74 _tableEditor.HasAnyCallbacks((int)AnchorableBehaviour.EventType.OnPostTryAnchorOnGraspEnd)));
75 if (hasInvalidPostGraspEndCallback) {
76 EditorGUILayout.HelpBox("This object's OnPostObjectGraspEnd is subscribed to, but the event will never "
77 + "fire because tryAnchorNearestOnGraspEnd is disabled.",
78 MessageType.Warning);
79 }
80 }
81
82 private void drawAttachmentHelperButtons() {
83 if (!EditorApplication.isPlaying) {
84 // Attach / Detach Object
85 EditorGUILayout.BeginHorizontal();
86
87 var anyTargetsCanAnchor = targets.Query().Any(t => t.anchor != null && !target.isAttached);
88
89 EditorGUI.BeginDisabledGroup(!anyTargetsCanAnchor);
90 if (GUILayout.Button(new GUIContent("Attach Object" + (targets.Length > 1 ? "s" : ""),
91 "Will attach the object to its anchor. If the object is not currently at its anchor, "
92 + "currently at its anchor, it will begin move to it when play mode begins."))) {
93 Undo.IncrementCurrentGroup();
94 foreach (var singleTarget in targets) {
95 Undo.RecordObject(singleTarget, "Try Attach Object");
96 singleTarget.TryAttach(ignoreRange: true);
97 }
98 }
99 EditorGUI.EndDisabledGroup();
100
101 var anyTargetsCanDetach = targets.Query().Any(t => t.isAttached);
102
103 EditorGUI.BeginDisabledGroup(!anyTargetsCanDetach);
104 if (GUILayout.Button(new GUIContent("Detach Object" + (targets.Length > 1 ? "s" : ""),
105 "Will detach the object from its anchor. AnchorableBehaviours won't seek out an anchor "
106 + "until they are specifically told to attach to one."))) {
107 Undo.IncrementCurrentGroup();
108 foreach (var singleTarget in targets) {
109 Undo.RecordObject(singleTarget, "Try Detach Object");
110 singleTarget.Detach();
111 }
112 }
113 EditorGUI.EndDisabledGroup();
114
115 EditorGUILayout.EndHorizontal();
116
117 // Move Object to Anchor
118
119 bool anyTranslatedFromAnchor = false;
120 bool anyRotatedFromAnchor = false;
121
122 foreach (var singleTarget in targets) {
123 anyTranslatedFromAnchor |= singleTarget.anchor != null && Vector3.Distance(singleTarget.transform.position, singleTarget.anchor.transform.position) > 0.0001F;
124 anyRotatedFromAnchor |= singleTarget.anchor != null && singleTarget.anchorRotation
125 && Quaternion.Angle(singleTarget.transform.rotation, singleTarget.anchor.transform.rotation) > 0.1F;
126 }
127
128 if (anyTranslatedFromAnchor || anyRotatedFromAnchor) {
129 if (GUILayout.Button(new GUIContent("Move Object" + (targets.Length > 1 ? "s" : "") + " To Anchor",
130 "Detected that the object is not currently at its anchor, but upon pressing play, "
131 + "the object will move to to match its anchor. If you'd like the object to move to "
132 + "its anchor now, click this button."))) {
133 Undo.IncrementCurrentGroup();
134 foreach (var singleTarget in targets) {
135 Undo.RecordObject(singleTarget.transform, "Move Target Transform to Anchor");
136 singleTarget.transform.position = singleTarget.anchor.transform.position;
137 if (singleTarget.anchorRotation) singleTarget.transform.rotation = singleTarget.anchor.transform.rotation;
138 }
139 }
140 }
141 }
142 }
143
144 }
145
146}
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 specifyCustomDrawer(string propertyName, Action< SerializedProperty > propertyDrawer)
Specify a callback to be used to draw a specific named property. Should be called in OnEnable.
AnchorableBehaviours mix well with InteractionBehaviours you'd like to be able to pick up and place i...