rabidus-test/Assets/BNG Framework/Scripts/Helpers/RingHelper.cs

232 lines
7.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace BNG {
/// <summary>
/// Shows a ring at the grab point of a grabbable if within a certain distance
/// </summary>
public class RingHelper : MonoBehaviour {
[Tooltip("The Grabbable Object to Observe")]
public Grabbable grabbable;
[Tooltip("(Optional) If specified, the ring helper will only be valid if this Grabpoint is the nearest on the the grabbable object")]
public GrabPoint Grabpoint;
[Tooltip("Default Color of the ring")]
public Color RingColor = Color.white;
/// <summary>
/// Color to use if selected by primary controller
/// </summary>
[Tooltip("Color to use if selected by primary controller")]
public Color RingSelectedColor = Color.white;
/// <summary>
/// Color to use if selected by secondary controller
/// </summary>
[Tooltip("Color to use if selected by secondary controller")]
public Color RingSecondarySelectedColor = Color.white;
public float ringSizeInRange = 1500f;
public float ringSizeGrabbable = 1100f; // Lower pixel size the bigger the font
/// <summary>
/// Don't show grab rings if left and right controllers / grabbers are holding something
/// </summary>
[Tooltip("Don't show grab rings if left and right controllers / grabbers are holding something")]
public bool HideIfHandsAreFull = true;
/// <summary>
/// How fast to lerp the opacity if being hidden / shown
/// </summary>
[Tooltip("How fast to lerp the opacity if being hidden / shown")]
public float RingFadeSpeed = 5;
Canvas canvas;
Text text;
CanvasScaler scaler;
/// <summary>
/// Used to determine if hands are full
/// </summary>
Grabber leftGrabber;
Grabber rightGrabber;
Grabber closestGrabber;
bool handsFull = false;
// Animate opacity
private float _initalOpacity;
private float _currentOpacity;
Transform mainCam;
void Start() {
AssignCamera();
if (grabbable == null) {
grabbable = transform.parent.GetComponent<Grabbable>();
}
canvas = GetComponent<Canvas>();
scaler = GetComponent<CanvasScaler>();
text = GetComponent<Text>();
if(text == null) {
Debug.LogWarning("No Text Component Found on RingHelper");
return;
}
_initalOpacity = text.color.a;
_currentOpacity = _initalOpacity;
AssignGrabbers();
}
void Update() {
// Double check for mainCam
AssignCamera();
// Bail if Text Component was removed or doesn't exist
if (text == null || mainCam == null || grabbable == null) {
return;
}
bool grabbersExist = leftGrabber != null && rightGrabber != null;
// Holding Item
handsFull = grabbersExist && leftGrabber.HoldingItem && rightGrabber.HoldingItem;
// Not a valid Grab
if(grabbersExist && grabbable.GrabButton == GrabButton.Grip && !leftGrabber.FreshGrip && !rightGrabber.FreshGrip) {
handsFull = true;
}
bool showRings = handsFull;
// If being held or not active, immediately hide the ring
if (grabbable.BeingHeld || !grabbable.isActiveAndEnabled) {
canvas.enabled = false;
return;
}
// Requires another Grabbable to be held. Can exit immediately
if(grabbable.OtherGrabbableMustBeGrabbed != null && grabbable.OtherGrabbableMustBeGrabbed.BeingHeld == false) {
canvas.enabled = false;
return;
}
// Show if within range
float currentDistance = Vector3.Distance(transform.position, mainCam.position);
if(!handsFull && currentDistance <= grabbable.RemoteGrabDistance) {
showRings = true;
}
else {
showRings = false;
}
// Animate ring opacity in / out
if(showRings) {
canvas.enabled = true;
canvas.transform.LookAt(mainCam);
// Resetting the text refreshes the render
text.text = "o";
bool isClosest = grabbable.GetClosestGrabber() != null && grabbable.IsGrabbable();
// Check if grabpoint was specified
if(Grabpoint != null) {
}
// If a valid grabbable, increase size a bit
if (isClosest) {
scaler.dynamicPixelsPerUnit = ringSizeGrabbable;
text.color = getSelectedColor();
}
else {
scaler.dynamicPixelsPerUnit = ringSizeInRange;
text.color = RingColor;
}
_currentOpacity += Time.deltaTime * RingFadeSpeed;
if (_currentOpacity > _initalOpacity) {
_currentOpacity = _initalOpacity;
}
Color colorCurrent = text.color;
colorCurrent.a = _currentOpacity;
text.color = colorCurrent;
}
else {
_currentOpacity -= Time.deltaTime * RingFadeSpeed;
if (_currentOpacity <= 0) {
_currentOpacity = 0;
canvas.enabled = false;
}
else {
canvas.enabled = true;
Color colorCurrent = text.color;
colorCurrent.a = _currentOpacity;
text.color = colorCurrent;
}
}
}
public virtual void AssignCamera() {
if (mainCam == null) {
// Find By Tag instead of Camera.main as the camera could be disabled
if(GameObject.FindGameObjectWithTag("MainCamera") != null) {
mainCam = GameObject.FindGameObjectWithTag("MainCamera").transform;
}
}
}
public virtual void AssignGrabbers() {
// Assign left / right grabbers
Grabber[] grabs;
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player) {
grabs = player.GetComponentsInChildren<Grabber>();
}
else {
// Fall back to all grabbers
grabs = FindObjectsOfType<Grabber>();
}
// Check grabber assignment
for (int x = 0; x < grabs.Length; x++) {
Grabber g = grabs[x];
if (g.HandSide == ControllerHand.Left) {
leftGrabber = g;
}
else if (g.HandSide == ControllerHand.Right) {
rightGrabber = g;
}
}
}
Color getSelectedColor() {
// Use secondary color if closest grabber is on the left hand
closestGrabber = grabbable.GetClosestGrabber();
if (grabbable != null && closestGrabber != null) {
if (closestGrabber.HandSide == ControllerHand.Left) {
return RingSecondarySelectedColor;
}
}
return RingSelectedColor;
}
}
}