GvrTooltip.cs
9.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
//-----------------------------------------------------------------------
// <copyright file="GvrTooltip.cs" company="Google Inc.">
// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// A tooltip for displaying control schemes overlaying the controller visual using a Unity Canvas.
/// </summary>
/// <remarks>
/// Automatically changes what side of the controller the tooltip is shown on depending on the
/// handedness setting for the player. Automatically fades out when the controller visual is too
/// close or too far away from the player's head. Look at the prefab GvrControllerPointer to see an
/// example of how to use this script.
/// </remarks>
[RequireComponent(typeof(CanvasGroup))]
[RequireComponent(typeof(RectTransform))]
[ExecuteInEditMode]
[HelpURL("https://developers.google.com/vr/reference/unity/class/GvrTooltip")]
public class GvrTooltip : MonoBehaviour, IGvrArmModelReceiver
{
/// <summary>
/// Y Position for touch pad tooltips based on the standard controller visual.
/// </summary>
protected const float TOUCH_PAD_Y_POSITION_METERS = 0.0385f;
/// <summary>
/// Y position for app button tooltips based on the standard controller visual.
/// </summary>
protected const float APP_BUTTON_Y_POSITION_METERS = 0.0105f;
/// <summary>Z position for all tooltips based on the standard controller visual.</summary>
protected const float TOOLTIP_Z_POSITION_METERS = 0.0098f;
/// <summary>
/// Rotation for a tooltip when it is displayed on the right side of the controller visual.
/// </summary>
protected static readonly Quaternion RIGHT_SIDE_ROTATION = Quaternion.Euler(0.0f, 0.0f, 0.0f);
/// <summary>
/// Rotation for a tooltip when it is displayed on the left side of the controller visual.
/// </summary>
protected static readonly Quaternion LEFT_SIDE_ROTATION = Quaternion.Euler(0.0f, 0.0f, 180.0f);
/// <summary>
/// Anchor point for a tooltip, used for controlling what side the tooltip is on.
/// </summary>
protected static readonly Vector2 SQUARE_CENTER = new Vector2(0.5f, 0.5f);
/// <summary>
/// Pivot point for a tooltip, used for controlling what side the tooltip is on.
/// </summary>
protected static readonly Vector2 PIVOT = new Vector2(-0.5f, 0.5f);
[Tooltip("The location to display the tooltip at relative to the controller visual.")]
[SerializeField]
private Location location;
[Tooltip("The text field for this tooltip.")]
[SerializeField]
private Text text;
[Tooltip(
"Determines if the tooltip is always visible regardless of the controller's location.")]
[SerializeField]
private bool alwaysVisible;
private bool isOnLeft = false;
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
/// <summary>Options for where the controller should be displayed.</summary>
/// <remarks>
/// If set to custom, then the manually set localPosition of the tooltip is used. This is
/// useful when displaying a tooltip for a non-standard controller visual.
/// </remarks>
internal enum Location
{
TouchPadOutside,
TouchPadInside,
AppButtonOutside,
AppButtonInside,
Custom
}
/// <summary>Gets the text field for this tooltip.</summary>
/// <value>The tooltip text.</value>
public Text TooltipText
{
get { return text; }
}
/// <summary>Gets or sets the arm model reference.</summary>
/// <value>The arm model reference.</value>
public GvrBaseArmModel ArmModel { get; set; }
/// <summary>
/// Returns `true` if this tooltip is set to display on the inside of the controller.
/// </summary>
/// <returns>Returns `true` if this instance is tooltip inside; otherwise, `false`.</returns>
public bool IsTooltipInside()
{
switch (location)
{
case Location.TouchPadInside:
case Location.AppButtonInside:
case Location.Custom:
return true;
case Location.TouchPadOutside:
case Location.AppButtonOutside:
default:
return false;
}
}
/// <summary>
/// Returns `true` if the tooltip should display on the left side of the controller.
/// </summary>
/// <remarks>
/// This will change based on the handedness of the controller, as well as if the tooltip is set
/// to display inside or outside.
/// </remarks>
/// <returns>Returns `true` if this instance is tooltip on left; otherwise, `false`.</returns>
public bool IsTooltipOnLeft()
{
bool isInside = IsTooltipInside();
GvrSettings.UserPrefsHandedness handedness = GvrSettings.Handedness;
if (handedness == GvrSettings.UserPrefsHandedness.Left)
{
return !isInside;
}
else
{
return isInside;
}
}
/// <summary>
/// Refreshes how the tooltip is being displayed based on what side it is being shown on.
/// </summary>
/// <remarks>Override to add custom display functionality.</remarks>
/// <param name="IsLocationOnLeft">Whether the location is on the left.</param>
protected virtual void OnSideChanged(bool IsLocationOnLeft)
{
transform.localRotation = isOnLeft ? LEFT_SIDE_ROTATION : RIGHT_SIDE_ROTATION;
if (text != null)
{
text.transform.localRotation =
IsLocationOnLeft ? LEFT_SIDE_ROTATION : RIGHT_SIDE_ROTATION;
text.alignment = IsLocationOnLeft ? TextAnchor.MiddleRight : TextAnchor.MiddleLeft;
}
}
/// <summary>Gets the meters-to-canvas scale.</summary>
/// <returns>The meters-to-canvas scale.</returns>
protected float GetMetersToCanvasScale()
{
return GvrUIHelpers.GetMetersToCanvasScale(transform);
}
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
canvasGroup = GetComponent<CanvasGroup>();
isOnLeft = IsTooltipOnLeft();
RefreshTooltip();
}
private void OnEnable()
{
// Update using OnPostControllerInputUpdated.
// This way, the position and rotation will be correct for the entire frame
// so that it doesn't matter what order Updates get called in.
if (Application.isPlaying)
{
GvrControllerInput.OnPostControllerInputUpdated += OnPostControllerInputUpdated;
}
}
private void OnDisable()
{
GvrControllerInput.OnPostControllerInputUpdated -= OnPostControllerInputUpdated;
}
private void OnPostControllerInputUpdated()
{
CheckTooltipSide();
if (canvasGroup != null && ArmModel != null)
{
canvasGroup.alpha = alwaysVisible ? 1.0f : ArmModel.TooltipAlphaValue;
}
}
private void OnValidate()
{
rectTransform = GetComponent<RectTransform>();
RefreshTooltip();
}
#if UNITY_EDITOR
private void OnRenderObject()
{
if (!Application.isPlaying)
{
CheckTooltipSide();
}
}
#endif // UNITY_EDITOR
private Vector3 GetLocalPosition()
{
float metersToCanvasScale = GetMetersToCanvasScale();
// Return early if we didn't find a valid metersToCanvasScale.
if (metersToCanvasScale == 0.0f)
{
return rectTransform.anchoredPosition3D;
}
float tooltipZPosition = TOOLTIP_Z_POSITION_METERS / metersToCanvasScale;
switch (location)
{
case Location.TouchPadOutside:
case Location.TouchPadInside:
float touchPadYPosition = TOUCH_PAD_Y_POSITION_METERS / metersToCanvasScale;
return new Vector3(0.0f, touchPadYPosition, tooltipZPosition);
case Location.AppButtonOutside:
case Location.AppButtonInside:
float appButtonYPosition = APP_BUTTON_Y_POSITION_METERS / metersToCanvasScale;
return new Vector3(0.0f, appButtonYPosition, tooltipZPosition);
case Location.Custom:
default:
return rectTransform.anchoredPosition3D;
}
}
private void CheckTooltipSide()
{
// If handedness changes, the tooltip will switch sides.
bool newIsOnLeft = IsTooltipOnLeft();
if (newIsOnLeft != isOnLeft)
{
isOnLeft = newIsOnLeft;
RefreshTooltip();
}
}
private void RefreshTooltip()
{
rectTransform.anchorMax = SQUARE_CENTER;
rectTransform.anchorMax = SQUARE_CENTER;
rectTransform.pivot = PIVOT;
rectTransform.anchoredPosition3D = GetLocalPosition();
OnSideChanged(isOnLeft);
}
}