Files
dungeons/Assets/UltimateXR/Runtime/Scripts/UI/UxrFingerTip.cs
2024-08-06 21:58:35 +02:00

147 lines
4.8 KiB
C#

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrFingerTip.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Avatar;
using UltimateXR.Avatar.Rig;
using UltimateXR.Core;
using UltimateXR.Core.Components.Composite;
using UltimateXR.Extensions.Unity.Math;
using UltimateXR.Manipulation;
using UnityEngine;
namespace UltimateXR.UI
{
/// <summary>
/// Component that, added to the tip of an <see cref="UxrAvatar" /> finger, allows it to interact with user interfaces.
/// It is normally added only to the index fingers so that other fingers don't generate unwanted interactions, but it
/// can be added to any finger.
/// </summary>
public class UxrFingerTip : UxrAvatarComponent<UxrFingerTip>
{
#region Public Types & Data
/// <summary>
/// Gets whether the <see cref="UxrGrabber" /> component belonging to the same hand the finger tip is, is currently
/// grabbing something.
/// </summary>
public bool IsHandGrabbing => HandGrabber && HandGrabber.GrabbedObject != null;
/// <summary>
/// Gets the current world position.
/// </summary>
public Vector3 WorldPos => transform.position;
/// <summary>
/// Gets the current world direction. The direction points in the direction the finger would be pointing. It is used to
/// filter out interactions where the forward vector is not perpendicular enough to the UI to interact with it.
/// </summary>
public Vector3 WorldDir => transform.forward;
/// <summary>
/// Gets the current world speed the finger tip is travelling at.
/// </summary>
public Vector3 WorldSpeed => _updateCount >= 2 ? (_currentWorldPos - _lastWorldPos) / Time.deltaTime : Vector3.zero;
/// <summary>
/// Gets the hand the finger tip belongs to.
/// </summary>
public UxrHandSide Side { get; private set; }
/// <summary>
/// Gets the <see cref="UxrGrabber" /> component of the hand the finger tip belongs to.
/// </summary>
public UxrGrabber HandGrabber { get; private set; }
#endregion
#region Public Methods
/// <summary>
/// Checks whether the finger tip is inside a box collider.
/// </summary>
/// <param name="box">Box collider</param>
/// <param name="allowWhileGrabbing">
/// Whether the operation that the check is for allows the hand to be grabbing something.
/// This means if the value is false and the hand is currently grabbing, it will always return false no matter the
/// finger tip is inside the box or not
/// </param>
/// <returns>Whether the finger tip is inside</returns>
public bool IsInside(BoxCollider box, bool allowWhileGrabbing = false)
{
if (!allowWhileGrabbing && IsHandGrabbing)
{
return false;
}
return box != null && transform.position.IsInsideBox(box);
}
#endregion
#region Unity
/// <summary>
/// Initializes the component.
/// </summary>
protected override void Awake()
{
base.Awake();
UxrAvatarRig.GetHandSide(transform, out UxrHandSide handSide);
Side = handSide;
}
/// <summary>
/// Resets the internal state.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
_updateCount = 0;
}
/// <summary>
/// Initializes the component.
/// </summary>
protected override void Start()
{
base.Start();
if (!(Avatar && Avatar.AvatarController))
{
return;
}
foreach (UxrGrabber grabber in UxrGrabber.GetComponents(Avatar, true))
{
if (grabber.Side == Side)
{
HandGrabber = grabber;
break;
}
}
}
/// <summary>
/// Updates the component.
/// </summary>
private void Update()
{
_lastWorldPos = _currentWorldPos;
_currentWorldPos = transform.position;
_updateCount++;
}
#endregion
#region Private Types & Data
private int _updateCount;
private Vector3 _currentWorldPos;
private Vector3 _lastWorldPos;
#endregion
}
}