Tanoda
CompressibleUI.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 UnityEngine;
12using UnityEngine.UI;
13using System;
14using System.Collections.Generic;
15
16namespace Leap.Unity.InputModule {
22 public class CompressibleUI : MonoBehaviour, ILeapWidget {
23 [Tooltip("A list of RectTransforms that are floated relative to this GameObject.")]
25 public Layer[] Layers;
26
28 [System.Serializable]
29 public struct Layer {
30 [HideInInspector]
32 public string Label;
33
34 [Tooltip("The child UI Element to hover above the canvas")]
36 public RectTransform LayerTransform;
37 [Tooltip("The height above this (base) element that the Layer will float")]
39 public float MaxFloatDistance;
40 [Tooltip("The minimum height that this layer can be compressed to.")]
42 public float MinFloatDistance;
43 [Tooltip("OPTIONAL: If you have a dropshadow image that you would like to opacity fade on compression, add one here")]
45 public UnityEngine.UI.Image Shadow;
46 [Tooltip("If the shadow effect is not childed to this layer, but the layer above it (for masking purposes)")]
48 public bool ShadowOnAboveLayer;
49 [Tooltip("If the event is triggered upon touching this layer (useful for ratcheted sounds)")]
51 public bool TriggerLayerEvent;
52
53 [HideInInspector]
55 public float MaxShadowOpacity;
56 [HideInInspector]
59 [HideInInspector]
61 public bool touchingFinger;
62 [HideInInspector]
65 [HideInInspector]
68 }
69
70 [Tooltip("The movement speed of this element when the expansion event is triggered; between 0-1")]
72 public float ExpandSpeed = 0.1f;
73 [Tooltip("The movement speed of this element when the compression event is triggered; between 0-1")]
75 public float ContractSpeed = 0.1f;
76 [Tooltip("Padding below the selection threshold that the element begins depressing")]
78 public float PushPaddingDistance = 0.01f;
79 //public bool RetractWhenOutsideofTouchingDistance = false;
80
81 [Tooltip("Triggered when the layers that have 'TriggerLayerEvent' enabled go from 'Expanded' to 'Partially Expanded'")]
83 public UnityEvent LayerDepress;
84 [Tooltip("Triggered when the layers that have 'TriggerLayerEvent' enabled go from 'Expanded' or 'Partially Expanded' to 'Collapsed'")]
86 public UnityEvent LayerCollapse;
87 [Tooltip("Triggered when the layers that have 'TriggerLayerEvent' enabled go from 'Collapsed' to 'Partially Expanded' or 'Expanded'")]
89 public UnityEvent LayerExpand;
90
91 //How quickly the button layers are Lerping
92 private float curLerpSpeed = 0.1f;
93
94 //How far the finger is from the base of the button
95 private float HoveringDistance = 0f;
96
97 //Whether or not the buttons are currently in float mode
98 private bool currentlyFloating = false;
99
100 private float TimeLastHovered = 0f;
101
102 //Reset the Positions of the UI Elements on both Start and Quit
103 void Start() {
104 for (int i = 0; i < Layers.Length; i++) {
105 if (Layers[i].LayerTransform != null && Layers[i].LayerTransform != transform) {
106 Layers[i].LayerTransform.localPosition = new Vector3(Layers[i].LayerTransform.localPosition.x, Layers[i].LayerTransform.localPosition.y, 0f);
107
108 if (Layers[i].Shadow != null) {
109 Layers[i].MaxShadowOpacity = Layers[i].Shadow.color.a;
110 Layers[i].Shadow.color = new Color(Layers[i].Shadow.color.r, Layers[i].Shadow.color.g, Layers[i].Shadow.color.b, 0f);
111 }
112 } else {
113 Debug.LogWarning("Ensure that the layers that you have allotted are children of CompressibleUI object and have UI Elements in them!");
114 }
115 }
116 //if (!RetractWhenOutsideofTouchingDistance) {
117 Expand();
118 //}
119 }
120
121 void OnApplicationQuit() {
122 for (int i = 0; i < Layers.Length; i++) {
123 if (Layers[i].LayerTransform != null) {
124 Layers[i].LayerTransform.localPosition = new Vector3(Layers[i].LayerTransform.localPosition.x, Layers[i].LayerTransform.localPosition.y, 0f);
125 }
126 }
127 }
128
129 void Update() {
130 //Reset Hovering Distance when "HoverDistance" isn't being called
131 if (Time.time > TimeLastHovered + 0.1f && HoveringDistance != 100f) {
132 HoveringDistance = 100f;
133 }
134 for (int i = 0; i < Layers.Length; i++) {
135 //Only float the UI Elements when a hand is near a set of buttons...
136 if (currentlyFloating) {
137 if (Layers[i].LayerTransform != null) {
138 if (HoveringDistance < Layers[i].MaxFloatDistance && HoveringDistance > Layers[i].MinFloatDistance) {
139 Layers[i].CurrentFloatingDistance = Mathf.Lerp(Layers[i].CurrentFloatingDistance, HoveringDistance, 0.7f); //Set lower than 1f for delayed touching
140 if (Layers[i].TriggerLayerEvent && !Layers[i].touchingFinger) {
141 Layers[i].touchingFinger = true;
142 LayerDepress.Invoke();
143 }
144 } else if (HoveringDistance < Layers[i].MinFloatDistance) {
145 if (Layers[i].TriggerLayerEvent) {
146 if (!Layers[i].touchingFinger) {
147 Layers[i].touchingFinger = true;
148 }
149 if (Layers[i].CurrentFloatingDistance > Layers[i].MinFloatDistance) {
150 LayerCollapse.Invoke();
151 }
152 }
154 } else {
155 Layers[i].CurrentFloatingDistance = Mathf.Lerp(Layers[i].CurrentFloatingDistance, Layers[i].MaxFloatDistance, curLerpSpeed);
156 if (Layers[i].TriggerLayerEvent && Layers[i].touchingFinger) {
157 Layers[i].touchingFinger = false;
158 LayerExpand.Invoke();
159 }
160 }
161 }
162 //else Just lay them flat so they're not bothering any cursors.
163 } else {
164 if (Layers[i].LayerTransform != null) {
165 Layers[i].CurrentFloatingDistance = Mathf.Lerp(Layers[i].CurrentFloatingDistance, 0f, curLerpSpeed);
166 if (Layers[i].TriggerLayerEvent && Layers[i].touchingFinger) {
167 Layers[i].touchingFinger = false;
168 }
169 }
170 }
171
172 //If we have a shadow, let's lerp its opacity based on this element's distance to the layer above.
173 if (Layers[i].Shadow != null) {
174 if (Layers[i].ShadowOnAboveLayer) {
175 if (i == 0) {
178 } else {
181 }
182 Layers[i].Shadow.color = new Color(Layers[i].Shadow.color.r, Layers[i].Shadow.color.g, Layers[i].Shadow.color.b, Layers[i].distanceToAboveLayer.Remap(0f, Layers[i].maxDistanceToAboveLayer, 0f, Layers[i].MaxShadowOpacity));
183 } else {
184 Layers[i].Shadow.color = new Color(Layers[i].Shadow.color.r, Layers[i].Shadow.color.g, Layers[i].Shadow.color.b, Layers[i].CurrentFloatingDistance.Remap(Layers[i].MinFloatDistance, Layers[i].MaxFloatDistance, 0f, Layers[i].MaxShadowOpacity));
185 }
186 }
187 if (Layers[i].LayerTransform != null) {
188 Vector3 LocalPosition = Layers[i].LayerTransform.parent.InverseTransformPoint(transform.TransformPoint(new Vector3(0f, 0f, -Layers[i].CurrentFloatingDistance / transform.lossyScale.z)));
189 Layers[i].LayerTransform.localPosition = new Vector3(Layers[i].LayerTransform.localPosition.x, Layers[i].LayerTransform.localPosition.y, LocalPosition.z);
190 }
191 }
192 }
193
197 public void HoverDistance(float distance) {
198 HoveringDistance = distance - PushPaddingDistance;
199 TimeLastHovered = Time.time;
200 }
201
203 public void Expand() {
204 currentlyFloating = true;
205 curLerpSpeed = ExpandSpeed;
206 }
207
209 public void Retract() {
210 //if (RetractWhenOutsideofTouchingDistance) {
211 currentlyFloating = false;
212 curLerpSpeed = ContractSpeed;
213 //}
214 }
215
216 public void DivideLayerHeightsOnToggle(Toggle toggle) {
217 if (toggle.isOn) {
218 for (int i = 0; i < Layers.Length; i++) {
219 Layers[i].MinFloatDistance /= 2f;
220 Layers[i].MaxFloatDistance /= 2f;
221 }
222 } else {
223 for (int i = 0; i < Layers.Length; i++) {
224 Layers[i].MinFloatDistance *= 2f;
225 Layers[i].MaxFloatDistance *= 2f;
226 }
227 }
228 }
229
230 void OnValidate() {
231 for (int i = 0; i < Layers.Length; i++) {
232 if (Layers[i].LayerTransform != null) {
233 Layers[i].Label = Layers[i].LayerTransform.gameObject.name + " Layer";
234 }
235 }
236 }
237 }
238
239 public static class ExtensionMethods {
240 public static float Remap(this float value, float from1, float to1, float from2, float to2) {
241 return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
242 }
243 }
244}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
UnityEngine.Color Color
Definition: TestScript.cs:32
void DivideLayerHeightsOnToggle(Toggle toggle)