forked from microsoft/MixedRealityToolkit-Unity
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDirectionIndicator.cs
More file actions
166 lines (132 loc) · 6.62 KB
/
DirectionIndicator.cs
File metadata and controls
166 lines (132 loc) · 6.62 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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using UnityEngine;
namespace HoloToolkit.Unity
{
/// <summary>
/// DirectionIndicator creates an indicator around the cursor showing
/// what direction to turn to find this GameObject.
/// </summary>
public class DirectionIndicator : MonoBehaviour
{
[Tooltip("The Cursor object the direction indicator will be positioned around.")]
public GameObject Cursor;
[Tooltip("Model to display the direction to the object this script is attached to.")]
public GameObject DirectionIndicatorObject;
[Tooltip("Color to shade the direction indicator.")]
public Color DirectionIndicatorColor = Color.blue;
[Tooltip("Allowable percentage inside the holographic frame to continue to show a directional indicator.")]
[Range(-0.3f, 0.3f)]
public float VisibilitySafeFactor = 0.1f;
[Tooltip("Multiplier to decrease the distance from the cursor center an object is rendered to keep it in view.")]
[Range(0.1f, 1.0f)]
public float MetersFromCursor = 0.3f;
// The default rotation of the cursor direction indicator.
private Quaternion directionIndicatorDefaultRotation = Quaternion.identity;
// Cache the MeshRenderer for the on-cursor indicator since it will be enabled and disabled frequently.
private Renderer directionIndicatorRenderer;
// Cache the Material to prevent material leak.
private Material indicatorMaterial;
// Check if the cursor direction indicator is visible.
private bool isDirectionIndicatorVisible;
public void Awake()
{
if (Cursor == null)
{
Debug.LogError("Please include a GameObject for the cursor.");
}
if (DirectionIndicatorObject == null)
{
Debug.LogError("Please include a GameObject for the Direction Indicator.");
}
// Instantiate the direction indicator.
DirectionIndicatorObject = InstantiateDirectionIndicator(DirectionIndicatorObject);
if (DirectionIndicatorObject == null)
{
Debug.LogError("Direction Indicator failed to instantiate.");
}
}
public void OnDestroy()
{
DestroyImmediate(indicatorMaterial);
Destroy(DirectionIndicatorObject);
}
private GameObject InstantiateDirectionIndicator(GameObject directionIndicator)
{
if (directionIndicator == null)
{
return null;
}
GameObject indicator = Instantiate(directionIndicator);
// Set local variables for the indicator.
directionIndicatorDefaultRotation = indicator.transform.rotation;
directionIndicatorRenderer = indicator.GetComponent<Renderer>();
// Start with the indicator disabled.
directionIndicatorRenderer.enabled = false;
// Remove any colliders and rigidbodies so the indicators do not interfere with Unity's physics system.
foreach (Collider indicatorCollider in indicator.GetComponents<Collider>())
{
Destroy(indicatorCollider);
}
foreach (Rigidbody rigidBody in indicator.GetComponents<Rigidbody>())
{
Destroy(rigidBody);
}
indicatorMaterial = directionIndicatorRenderer.material;
indicatorMaterial.color = DirectionIndicatorColor;
indicatorMaterial.SetColor("_TintColor", DirectionIndicatorColor);
return indicator;
}
public void Update()
{
if (DirectionIndicatorObject == null)
{
return;
}
// Direction from the Main Camera to this script's parent gameObject.
Vector3 camToObjectDirection = gameObject.transform.position - Camera.main.transform.position;
camToObjectDirection.Normalize();
// The cursor indicator should only be visible if the target is not visible.
isDirectionIndicatorVisible = !IsTargetVisible();
directionIndicatorRenderer.enabled = isDirectionIndicatorVisible;
if (isDirectionIndicatorVisible)
{
Vector3 position;
Quaternion rotation;
GetDirectionIndicatorPositionAndRotation(
camToObjectDirection,
out position,
out rotation);
DirectionIndicatorObject.transform.position = position;
DirectionIndicatorObject.transform.rotation = rotation;
}
}
private bool IsTargetVisible()
{
// This will return true if the target's mesh is within the Main Camera's view frustums.
Vector3 targetViewportPosition = Camera.main.WorldToViewportPoint(gameObject.transform.position);
return (targetViewportPosition.x > VisibilitySafeFactor && targetViewportPosition.x < 1 - VisibilitySafeFactor &&
targetViewportPosition.y > VisibilitySafeFactor && targetViewportPosition.y < 1 - VisibilitySafeFactor &&
targetViewportPosition.z > 0);
}
private void GetDirectionIndicatorPositionAndRotation(Vector3 camToObjectDirection, out Vector3 position, out Quaternion rotation)
{
// Find position:
// Save the cursor transform position in a variable.
Vector3 origin = Cursor.transform.position;
// Project the camera to target direction onto the screen plane.
Vector3 cursorIndicatorDirection = Vector3.ProjectOnPlane(camToObjectDirection, -1 * Camera.main.transform.forward);
cursorIndicatorDirection.Normalize();
// If the direction is 0, set the direction to the right.
// This will only happen if the camera is facing directly away from the target.
if (cursorIndicatorDirection == Vector3.zero)
{
cursorIndicatorDirection = Camera.main.transform.right;
}
// The final position is translated from the center of the screen along this direction vector.
position = origin + cursorIndicatorDirection * MetersFromCursor;
// Find the rotation from the facing direction to the target object.
rotation = Quaternion.LookRotation(Camera.main.transform.forward, cursorIndicatorDirection) * directionIndicatorDefaultRotation;
}
}
}