2025-05-15 16:25:40 +02:00

274 lines
8.6 KiB
C#

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
#if META_SDK
using Oculus.Interaction;
#endif
namespace VRUIP
{
public class VRUIPManager : MonoBehaviour
{
public static VRUIPManager instance;
// Properties
public ColorThemeMode colorMode;
public ColorTheme customColorTheme;
// Framework Specific Components
public Camera mainCamera;
#if !META_SDK
public LineRenderer lineRenderer;
#else
public RayInteractor handRayInteractor;
public RayInteractor controllerRayInteractor;
public GrabInteractor controllerGrabInteractor;
#endif
#if OCULUS_INTEGRATION
public LaserPointer laserPointer;
public OVRGrabber leftHand;
public OVRGrabber rightHand;
#endif
// UI
public ScaleUIButton scaleButton;
[SerializeField] private Keyboard keyboardPrefab;
// PROPERTIES
/// <summary>
/// Returns the current Color theme, or sets it.
/// </summary>
public ColorTheme CurrentColorTheme
{
get => _colorThemes[colorMode];
set
{
colorMode = ColorThemeMode.Custom;
customColorTheme = value;
SetTheme();
}
}
public bool IsVR { get; private set; }
public AudioSource AudioSource => _audioSource;
public bool IsKeyboardOnInput { get; set; } = false;
private List<A_ColorController> _colorControllers = new();
private Dictionary<ColorThemeMode, ColorTheme> _colorThemes;
private AudioSource _audioSource;
private Keyboard _keyboard;
private void Awake()
{
SetupInstance();
}
private void Start()
{
#if OCULUS_INTEGRATION
laserPointer.laserBeamBehavior = LaserPointer.LaserBeamBehavior.OnWhenHitTarget;
#endif
}
private void SetupInstance()
{
if (instance == null)
{
instance = this;
#if !META_SDK
if (lineRenderer != null) lineRenderer.sortingOrder = 30001;
#endif
if (_audioSource == null) _audioSource = GetComponentInChildren<AudioSource>();
SetupThemes();
#if (OCULUS_INTEGRATION || XR_ITK || META_SDK)
IsVR = true;
#else
IsVR = false;
#endif
}
}
public void GoToScene(string scene)
{
SceneManager.LoadScene(scene);
}
public void ShowKeyboard()
{
// if there is no keyboard assigned, throw an error
if (keyboardPrefab == null)
{
Debug.LogWarning("Error: Please assign a keyboard prefab to the VRUIPManager.");
return;
}
// calculate the spawn point of the keyboard
var spawnPoint = CalculateSpawnPoint();
// if the keyboard has not been spawned yet, spawn it
if (_keyboard == null)
{
// if first time showing the keyboard, spawn it
_keyboard = keyboardPrefab.Create(spawnPoint.Item1, spawnPoint.Item2, spawnPoint.Item3, true);
}
else
{
// if the keyboard has already been spawned, just move it to the spawn point and fade it in
var keyboardTransform = _keyboard.transform;
keyboardTransform.position = spawnPoint.Item1;
keyboardTransform.rotation = spawnPoint.Item2;
_keyboard.SetContentRotation(spawnPoint.Item3);
keyboardTransform.eulerAngles = new Vector3(0, keyboardTransform.eulerAngles.y, 0);
// if the keyboard is not active, activate it and set the alpha to 0 since the FadeInCanvas function activates the canvas object not the keyboards.
if (!_keyboard.gameObject.activeInHierarchy)
{
_keyboard.gameObject.SetActive(true);
_keyboard.SetAlpha(0);
}
// fade in the keyboard
_keyboard.FadeInCanvas();
}
}
public void HideKeyboard()
{
// if there is no keyboard assigned, return
if (_keyboard == null) return;
// if the keyboard is active, fade it out
if (_keyboard.gameObject.activeInHierarchy)
{
_keyboard.FadeOutCanvas();
}
}
#if META_SDK
/// <summary>
/// Get the position of the ray interactor that is currently active.
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public bool GetRayInteractorPosition(out Vector3 position)
{
position = Vector3.zero;
if (handRayInteractor.isActiveAndEnabled)
{
if (handRayInteractor.CollisionInfo.HasValue)
{
position = handRayInteractor.CollisionInfo.Value.Point;
return true;
}
}
else if (controllerRayInteractor.isActiveAndEnabled)
{
if (controllerRayInteractor.CollisionInfo.HasValue)
{
position = controllerRayInteractor.CollisionInfo.Value.Point;
return true;
}
}
return false;
}
#endif
/// <summary>
/// Set the input field for the default keyboard.
/// </summary>
/// <param name="inputField"></param>
public void SetKeyboardInput(TMP_InputField inputField)
{
if (_keyboard == null)
{
Debug.LogError("Error: Keyboard is not spawned yet.");
return;
}
_keyboard.SetInput(inputField);
}
private (Vector3, Quaternion, Vector3) CalculateSpawnPoint()
{
var cameraTransform = mainCamera.transform;
var forward = cameraTransform.forward;
var spawnPosition = cameraTransform.position + forward * .6f + new Vector3(0, -0.4f, 0); // Adjust the spawn distance as needed
var spawnRotation = Quaternion.LookRotation(spawnPosition - cameraTransform.position);
var contentRotation = new Vector3(0f, 0f, 0f);
return (spawnPosition, spawnRotation, contentRotation);
}
/// <summary>
/// Set the theme of the UI.
/// </summary>
public void SetTheme()
{
foreach (var controller in _colorControllers)
{
controller.SetupElement(_colorThemes[colorMode]);
}
}
private void SetupThemes()
{
// Dark Mode
var darkPrimary = Util.HexToColor("#262626");
var darkSecondary = Util.HexToColor("#b8b8b8");
var darkThird = Util.HexToColor("#454545");
var darkFourth = Util.HexToColor("#8e65bf");
// Light Mode:
var lightPrimary = Util.HexToColor("#FFFFFF");
var lightSecondary = Util.HexToColor("#4d4d4d");
var lightThird = Util.HexToColor("#dedede");
var lightFourth = Util.HexToColor("#498feb");
_colorThemes = new Dictionary<ColorThemeMode, ColorTheme>
{
{ ColorThemeMode.DarkMode, new ColorTheme(darkPrimary, darkSecondary, darkThird, darkFourth) },
{ ColorThemeMode.LightMode, new ColorTheme(lightPrimary, lightSecondary, lightThird, lightFourth) },
{ ColorThemeMode.Custom, customColorTheme }
};
}
public void RegisterElement(A_ColorController element)
{
_colorControllers.Add(element);
}
// ENUMS ----------
public enum TargetFramework
{
UnityEditorTesting,
OculusIntegration,
XRInteractionToolkit,
MetaSDK
}
public enum ColorThemeMode
{
DarkMode,
LightMode,
Custom
}
// ----------
#if UNITY_EDITOR
private void OnValidate()
{
if (IsPrefab()) return;
SetupInstance();
}
private bool IsPrefab()
{
return string.IsNullOrEmpty(gameObject.scene.path) || string.IsNullOrEmpty(gameObject.scene.name);
}
#endif
}
}