// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using UltimateXR.Avatar; using UltimateXR.Core; using UltimateXR.Core.Components; using UltimateXR.Extensions.Unity; using UnityEngine; using UnityEngine.UI; namespace UltimateXR.UI.UnityInputModule { /// /// Component that, added to a with a component, enables interaction /// using components or components. /// public class UxrCanvas : UxrComponent { #region Inspector Properties/Serialized Fields [SerializeField] protected UxrInteractionType _interactionType; [SerializeField] protected float _fingerTipMinHoverDistance = UxrFingerTipRaycaster.FingerTipMinHoverDistanceDefault; [SerializeField] protected bool _autoEnableLaserPointer; [SerializeField] protected float _autoEnableDistance = 5.0f; [SerializeField] protected bool _allowLeftHand = true; [SerializeField] protected bool _allowRightHand = true; #endregion #region Public Types & Data /// /// Gets the Unity component. /// public Canvas UnityCanvas => GetCachedComponent(); /// /// Gets or sets whether the components will automatically show their laser while /// pointing towards the canvas. /// public bool AutoEnableLaserPointer { get => _autoEnableLaserPointer; set => _autoEnableLaserPointer = value; } /// /// Gets or sets the distance below which the will automatically show the laser while /// pointing towards the canvas. /// public float AutoEnableDistance { get => _autoEnableDistance; set => _autoEnableDistance = value; } /// /// Gets or sets the type of interaction with the UI components in the canvas. /// public UxrInteractionType CanvasInteractionType { get => _interactionType; set { _interactionType = value; if (_oldRaycaster != null) { DestroyVRCanvas(); CreateVRCanvas(); } } } /// /// Gets or sets the distance below which a component will generate hovering events. /// public float FingerTipMinHoverDistance { get => _fingerTipMinHoverDistance; set => _fingerTipMinHoverDistance = value; } #endregion #region Public Methods /// /// Checks if the canvas can be used with the given hand. This allows some canvases to work for the left or /// right hand only. /// /// Which hand to check /// Boolean telling whether the given hand is compatible or not public bool IsCompatible(UxrHandSide handSide) { return (handSide == UxrHandSide.Left && _allowLeftHand) || (handSide == UxrHandSide.Right && _allowRightHand); } /// /// Sets up the canvas so that it can be used with . /// /// The input module public void SetupCanvas(UxrPointerInputModule inputModule) { CanvasInteractionType = inputModule.InteractionTypeOnAutoEnable; if (_newRaycasterFingerTips != null) { _newRaycasterFingerTips.FingerTipMinHoverDistance = inputModule.FingerTipMinHoverDistance; } } #endregion #region Unity /// /// Initializes the component. /// protected override void Start() { base.Start(); if (UxrPointerInputModule.Instance && UxrPointerInputModule.Instance.AutoAssignEventCamera && UnityCanvas && UxrAvatar.LocalAvatar) { UnityCanvas.worldCamera = UxrAvatar.LocalAvatar.CameraComponent; } if (_newRaycasterFingerTips == null && _newRaycasterLaserPointer == null) { CreateVRCanvas(); } } #endregion #region Private Methods /// /// Creates the raycaster required to use the component with /// . /// private void CreateVRCanvas() { if (UnityCanvas == null) { return; } if (_oldRaycaster == null) { _oldRaycaster = UnityCanvas.gameObject.GetComponent(); } if (_interactionType == UxrInteractionType.FingerTips) { _newRaycasterFingerTips = GetOrAddRaycaster(_oldRaycaster); _newRaycasterFingerTips.FingerTipMinHoverDistance = _fingerTipMinHoverDistance; } else if (_interactionType == UxrInteractionType.LaserPointers) { _newRaycasterLaserPointer = GetOrAddRaycaster(_oldRaycaster); } } /// /// Sets up the new raycaster. /// /// /// /// private T GetOrAddRaycaster(GraphicRaycaster oldRaycaster) where T : GraphicRaycaster { bool copyParameters = UnityCanvas.GetComponent() == null; T rayCaster = UnityCanvas.GetOrAddComponent(); rayCaster.enabled = true; if (oldRaycaster && rayCaster) { if (copyParameters) { rayCaster.ignoreReversedGraphics = oldRaycaster.ignoreReversedGraphics; rayCaster.blockingObjects = GraphicRaycaster.BlockingObjects.All; rayCaster.blockingMask = oldRaycaster.blockingMask; } oldRaycaster.enabled = false; } return rayCaster; } /// /// Destroys the new raycaster and restores the old one. /// private void DestroyVRCanvas() { if (_newRaycasterFingerTips) { Destroy(_newRaycasterFingerTips); } if (_newRaycasterLaserPointer) { Destroy(_newRaycasterLaserPointer); } if (_oldRaycaster && _oldRaycaster.enabled == false) { _oldRaycaster.enabled = true; } } #endregion #region Private Types & Data private GraphicRaycaster _oldRaycaster; private UxrFingerTipRaycaster _newRaycasterFingerTips; private UxrLaserPointerRaycaster _newRaycasterLaserPointer; #endregion } }