Add ultimate xr
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrButton3D.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.UI.UnityInputModule.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class to simplify interacting with 3D button objects by programming 2D UI elements.
|
||||
/// A 2D Unity UI Canvas is placed on top of the 3D buttons. The Canvas will contain invisible
|
||||
/// <see cref="UxrControlInput" /> UI components by using <see cref="UxrNonDrawingGraphic" /> instead of images.
|
||||
/// The <see cref="UxrControlInput" /> components will get the user input and through child implementations of
|
||||
/// <see cref="UxrButton3D" /> the 3D objects will be "pushed", "rotated" creating 3D behaviour using 2D logic.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(UxrControlInput))]
|
||||
public class UxrButton3D : UxrComponent<Canvas, UxrButton3D>
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private Transform _targetTransform;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UI input component.
|
||||
/// </summary>
|
||||
public UxrControlInput ControlInput => GetCachedComponent<UxrControlInput>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Transform" /> of the 3D object that is going to move, rotate, scale...
|
||||
/// </summary>
|
||||
public Transform Target => _targetTransform;
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="Target" />'s local position during Awake().
|
||||
/// </summary>
|
||||
public Vector3 InitialTargetLocalPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="Target" />'s local rotation during Awake().
|
||||
/// </summary>
|
||||
public Quaternion InitialTargetLocalRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="Target" />'s world position during Awake().
|
||||
/// </summary>
|
||||
public Vector3 InitialTargetPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="Target" />'s world rotation during Awake().
|
||||
/// </summary>
|
||||
public Quaternion InitialTargetRotation { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the component.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
if (Target != null)
|
||||
{
|
||||
InitialTargetLocalPosition = Target.localPosition;
|
||||
InitialTargetLocalRotation = Target.localRotation;
|
||||
InitialTargetPosition = Target.position;
|
||||
InitialTargetRotation = Target.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to the input control events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
if (ControlInput)
|
||||
{
|
||||
ControlInput.Pressed += ControlInput_Pressed;
|
||||
ControlInput.Released += ControlInput_Released;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from the input control events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
if (ControlInput)
|
||||
{
|
||||
ControlInput.Pressed -= ControlInput_Pressed;
|
||||
ControlInput.Released -= ControlInput_Released;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Receives the key down event.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
private void ControlInput_Pressed(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
OnKeyPressed(controlInput, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives the key up event.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
private void ControlInput_Released(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
OnKeyReleased(controlInput, eventData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Trigger Methods
|
||||
|
||||
/// <summary>
|
||||
/// Event trigger for the key pressed event. It can be overridden in child classes to handle key presses without
|
||||
/// subscribing to events.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected virtual void OnKeyPressed(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event trigger for the key released event. It can be overridden in child classes to handle key releases without
|
||||
/// subscribing to events.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected virtual void OnKeyReleased(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb3459a5e0294a478dcf6712b27704b1
|
||||
timeCreated: 1640709321
|
||||
@@ -0,0 +1,60 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrButton3DPress.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.UI.UnityInputModule.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that moves a 3D object when a given UI control is being pressed
|
||||
/// </summary>
|
||||
public class UxrButton3DPress : UxrButton3D
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private Vector3 _pressedLocalOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Trigger Methods
|
||||
|
||||
/// <summary>
|
||||
/// Key down event. The object is moved to the pressed local coordinates.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected override void OnKeyPressed(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
if (Target)
|
||||
{
|
||||
Vector3 pressedLocalOffset = _pressedLocalOffset;
|
||||
|
||||
if (Target.parent != null)
|
||||
{
|
||||
pressedLocalOffset = Target.parent.InverseTransformDirection(Target.TransformDirection(pressedLocalOffset));
|
||||
}
|
||||
|
||||
Target.localPosition = InitialTargetLocalPosition + pressedLocalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Key up event. The original object position is restored.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected override void OnKeyReleased(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
if (Target)
|
||||
{
|
||||
Target.localPosition = InitialTargetLocalPosition;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11f37e36dfbb79d448e633e26928b45b
|
||||
timeCreated: 1531470375
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrButton3DRotate.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.UI.UnityInputModule.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that rotates a 3D object when a given UI control is being pressed.
|
||||
/// This allows to model buttons that rotate depending on the point of pressure.
|
||||
/// The axis of rotation will be computed automatically, the center will be given by <see cref="UxrButton3D.Target" />
|
||||
/// and the pressure applied will be on the transform of this component.
|
||||
/// </summary>
|
||||
public class UxrButton3DRotate : UxrButton3D
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private Vector3 _buttonLocalUpAxis = Vector3.up;
|
||||
[SerializeField] private float _pressedDegrees = 2.0f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Trigger Methods
|
||||
|
||||
/// <summary>
|
||||
/// Key down event. The object is rotated according to the pressing point.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected override void OnKeyPressed(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
if (Target)
|
||||
{
|
||||
Vector3 rotationAxis = Vector3.Cross(_buttonLocalUpAxis, Target.InverseTransformVector(Target.position - transform.position).normalized);
|
||||
Target.Rotate(rotationAxis, -_pressedDegrees, Space.Self);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Key up event. The original object rotation is restored.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that triggered the event</param>
|
||||
/// <param name="eventData">Input event data</param>
|
||||
protected override void OnKeyReleased(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
if (Target)
|
||||
{
|
||||
Target.localRotation = InitialTargetLocalRotation;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4edbb5eee02f6f41a8193c5b29c0421
|
||||
timeCreated: 1531470375
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrControlInputDestroyOnPress.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.UI.UnityInputModule.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that, added to a <see cref="GameObject" /> with a <see cref="UxrControlInput" /> component, will destroy
|
||||
/// the GameObject whenever the control is clicked.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(UxrControlInput))]
|
||||
public class UxrControlInputDestroyOnPress : UxrComponent
|
||||
{
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UxrControlInput" /> component.
|
||||
/// </summary>
|
||||
public UxrControlInput ControlInput => GetCachedComponent<UxrControlInput>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
ControlInput.Clicked += Control_Clicked;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
ControlInput.Clicked -= Control_Clicked;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called when the object was clicked.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control that was clicked</param>
|
||||
/// <param name="eventData">Event data</param>
|
||||
private void Control_Clicked(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eea1951b7bec08642a2234cbfa8dc391
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrDynamicPixelsPerUnit.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Avatar;
|
||||
using UltimateXR.Core;
|
||||
using UltimateXR.Core.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that adjusts the dynamic pixels per unit value in a <see cref="Canvas" /> component depending on
|
||||
/// the distance to the avatar. It helps removing filtering artifacts when using composition layers is not
|
||||
/// possible.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(CanvasScaler))]
|
||||
public class UxrDynamicPixelsPerUnit : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private float _updateSeconds = 0.3f;
|
||||
[SerializeField] private float _rangeNear = 0.3f;
|
||||
[SerializeField] private float _rangeFar = 4.0f;
|
||||
[SerializeField] private float _pixelsPerUnitNear = 1.0f;
|
||||
[SerializeField] private float _pixelsPerUnitFar = 0.1f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Caches components.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_canvasScaler = GetComponent<CanvasScaler>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
UxrAvatar.GlobalAvatarMoved += UxrAvatar_GlobalAvatarMoved;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
UxrAvatar.GlobalAvatarMoved += UxrAvatar_GlobalAvatarMoved;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called when an avatar moved: Adjusts the dynamic pixels per unit.
|
||||
/// </summary>
|
||||
/// <param name="sender">Event sender</param>
|
||||
/// <param name="e">Event parameters</param>
|
||||
private void UxrAvatar_GlobalAvatarMoved(object sender, UxrAvatarMoveEventArgs e)
|
||||
{
|
||||
UxrAvatar avatar = sender as UxrAvatar;
|
||||
|
||||
if (avatar == UxrAvatar.LocalAvatar && Time.time - _timeLastUpdate > _updateSeconds)
|
||||
{
|
||||
_timeLastUpdate = Time.time;
|
||||
float distance = Vector3.Distance(avatar.CameraPosition, _canvasScaler.transform.position);
|
||||
_canvasScaler.dynamicPixelsPerUnit = Mathf.Lerp(_pixelsPerUnitNear, _pixelsPerUnitFar, Mathf.Clamp01((distance - _rangeNear) / (_rangeFar - _rangeNear)));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private float _timeLastUpdate = -1.0f;
|
||||
private CanvasScaler _canvasScaler;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96e14cd674acb2e458e6fcb725350787
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,155 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrHoverTimerClick.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Core;
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.Core.Settings;
|
||||
using UltimateXR.UI.UnityInputModule.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that, added to a <see cref="GameObject" /> with a <see cref="UxrControlInput" /> component, will
|
||||
/// automatically generate a Click event on the control whenever the cursor spends a given amount of time over it.
|
||||
/// It can be used to implement clicks using the gaze pointer (<see cref="UxrCameraPointer" />).
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(UxrControlInput))]
|
||||
public class UxrHoverTimerClick : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] [Tooltip("Number of seconds the user will need to hover over this element to trigger the Click event")] private float _lookAtSecondsToClick = 2.0f;
|
||||
[SerializeField] [Tooltip("Unscaled time will use the real device timer. If this parameter is unchecked it will use the scaled timer affected by pauses, bullet-times etc.")] private bool _useUnscaledTime = true;
|
||||
[SerializeField] [Tooltip("Will update the fill value of the Image component on this same GameObject to represent the timer progress. Needs an Image component.")] private bool _useFillImage = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the component.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_image = GetComponent<Image>();
|
||||
_controlInput = GetComponent<UxrControlInput>();
|
||||
|
||||
_timer = _lookAtSecondsToClick;
|
||||
|
||||
if (_useFillImage && _image == null)
|
||||
{
|
||||
if (UxrGlobalSettings.Instance.LogLevelUI >= UxrLogLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"{UxrConstants.UiModule} UseFillImage was specified on {GetType().Name} component of GameObject {name} but there is no Image component on it to update fill.");
|
||||
}
|
||||
}
|
||||
else if (_useFillImage && _image != null && _image.type != Image.Type.Filled)
|
||||
{
|
||||
if (UxrGlobalSettings.Instance.LogLevelUI >= UxrLogLevel.Warnings)
|
||||
{
|
||||
Debug.LogWarning($"{UxrConstants.UiModule} UseFillImage was specified on {GetType().Name} component of GameObject {name} but the Image component is not of a filled type (Image Type property).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_controlInput.CursorEntered += Input_Entered;
|
||||
_controlInput.CursorExited += Input_Exited;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
_controlInput.CursorEntered -= Input_Entered;
|
||||
_controlInput.CursorExited -= Input_Exited;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the progress and checks whether to generate the Click event.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (_timer > 0.0f)
|
||||
{
|
||||
_timer -= _useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
|
||||
if (_timer <= 0.0f)
|
||||
{
|
||||
_timer = -1.0f;
|
||||
|
||||
if (_useFillImage && _image)
|
||||
{
|
||||
_image.fillAmount = 1.0f;
|
||||
}
|
||||
|
||||
ExecuteEvents.ExecuteHierarchy(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_useFillImage && _image)
|
||||
{
|
||||
_image.fillAmount = Mathf.Clamp01(1.0f - _timer / _lookAtSecondsToClick);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_useFillImage && _image)
|
||||
{
|
||||
_image.fillAmount = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the pointer entered the control's Rect.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control input</param>
|
||||
/// <param name="eventData">Event data</param>
|
||||
private void Input_Entered(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
_timer = _lookAtSecondsToClick;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the pointer exited the control's Rect.
|
||||
/// </summary>
|
||||
/// <param name="controlInput">Control input</param>
|
||||
/// <param name="eventData">Event data</param>
|
||||
private void Input_Exited(UxrControlInput controlInput, PointerEventData eventData)
|
||||
{
|
||||
_timer = -1.0f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private Image _image;
|
||||
private UxrControlInput _controlInput;
|
||||
private float _timer;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bac92ce8624fe1144ab04b50f88194c8
|
||||
timeCreated: 1521406790
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,326 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrRightToLeftSupport.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.Extensions.System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if ULTIMATEXR_UNITY_TMPRO
|
||||
using TMPro;
|
||||
#endif
|
||||
|
||||
namespace UltimateXR.UI.UnityInputModule.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Component that, added to a UI element, will enable support for left-to-right and right-to-left languages.
|
||||
/// Right-to-left languages not only work by setting text alignment to right, they also require the whole layout to
|
||||
/// be right-to-left.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To switch from one to another use the static property <see cref="UseRightToLeft" />.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The supported UI components are:
|
||||
/// </para>
|
||||
/// <list type="bullet">
|
||||
/// <item><see cref="Text" /> (Unity UI)</item>
|
||||
/// <item>Text UI (TextMeshPro)</item>
|
||||
/// <item><see cref="HorizontalLayoutGroup" /> (Unity UI)</item>
|
||||
/// <item><see cref="VerticalLayoutGroup" /> (Unity UI)</item>
|
||||
/// <item><see cref="GridLayoutGroup" /> (Unity UI)</item>
|
||||
/// <item><see cref="Image" /> fill origin (Unity UI)</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public class UxrRightToLeftSupport : UxrComponent<UxrRightToLeftSupport>
|
||||
{
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Sets the global right-to-left setting, changing all <see cref="UxrRightToLeftSupport" /> components.
|
||||
/// Disabled components, or newly instantiated components, will be aligned correctly too.
|
||||
/// </summary>
|
||||
public static bool UseRightToLeft
|
||||
{
|
||||
get => s_useRightToLeft;
|
||||
set
|
||||
{
|
||||
s_useRightToLeft = value;
|
||||
EnabledComponents.ForEach(c => c.SetRightToLeft(value));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the component.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
CheckInitialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the RtoL setting when the component is enabled.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
SetRightToLeft(s_useRightToLeft);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
#if ULTIMATEXR_UNITY_TMPRO
|
||||
/// <summary>
|
||||
/// Transforms a TMPro alignment value from LtoR to RtoL.
|
||||
/// </summary>
|
||||
/// <param name="alignment">Alignment to transform</param>
|
||||
/// <returns>RtoL value</returns>
|
||||
private static TextAlignmentOptions GetRtoLAlignmentTMPro(TextAlignmentOptions alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case TextAlignmentOptions.TopRight: return TextAlignmentOptions.TopLeft;
|
||||
case TextAlignmentOptions.Right: return TextAlignmentOptions.Left;
|
||||
case TextAlignmentOptions.BottomRight: return TextAlignmentOptions.BottomLeft;
|
||||
case TextAlignmentOptions.BaselineRight: return TextAlignmentOptions.BaselineLeft;
|
||||
case TextAlignmentOptions.MidlineRight: return TextAlignmentOptions.MidlineLeft;
|
||||
case TextAlignmentOptions.CaplineRight: return TextAlignmentOptions.CaplineLeft;
|
||||
case TextAlignmentOptions.TopLeft: return TextAlignmentOptions.TopRight;
|
||||
case TextAlignmentOptions.Left: return TextAlignmentOptions.Right;
|
||||
case TextAlignmentOptions.BottomLeft: return TextAlignmentOptions.BottomRight;
|
||||
case TextAlignmentOptions.BaselineLeft: return TextAlignmentOptions.BaselineRight;
|
||||
case TextAlignmentOptions.MidlineLeft: return TextAlignmentOptions.MidlineRight;
|
||||
case TextAlignmentOptions.CaplineLeft: return TextAlignmentOptions.CaplineRight;
|
||||
}
|
||||
|
||||
return alignment;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a Unity UI alignment value from LtoR to RtoL.
|
||||
/// </summary>
|
||||
/// <param name="alignment">Alignment to transform</param>
|
||||
/// <returns>RtoL value</returns>
|
||||
private static TextAnchor GetRtoLAlignment(TextAnchor alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case TextAnchor.UpperLeft: return TextAnchor.UpperRight;
|
||||
case TextAnchor.UpperRight: return TextAnchor.UpperLeft;
|
||||
case TextAnchor.MiddleLeft: return TextAnchor.MiddleRight;
|
||||
case TextAnchor.MiddleRight: return TextAnchor.MiddleLeft;
|
||||
case TextAnchor.LowerLeft: return TextAnchor.LowerRight;
|
||||
case TextAnchor.LowerRight: return TextAnchor.LowerLeft;
|
||||
}
|
||||
|
||||
return alignment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a Unity UI corner value from LtoR to RtoL.
|
||||
/// </summary>
|
||||
/// <param name="corner">Corner to transform</param>
|
||||
/// <returns>RtoL value</returns>
|
||||
private static GridLayoutGroup.Corner GetRtoLCorner(GridLayoutGroup.Corner corner)
|
||||
{
|
||||
switch (corner)
|
||||
{
|
||||
case GridLayoutGroup.Corner.UpperLeft: return GridLayoutGroup.Corner.UpperRight;
|
||||
case GridLayoutGroup.Corner.UpperRight: return GridLayoutGroup.Corner.UpperLeft;
|
||||
case GridLayoutGroup.Corner.LowerLeft: return GridLayoutGroup.Corner.LowerRight;
|
||||
case GridLayoutGroup.Corner.LowerRight: return GridLayoutGroup.Corner.LowerLeft;
|
||||
}
|
||||
|
||||
return corner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a Unity UI fill origin value from LtoR to RtoL.
|
||||
/// </summary>
|
||||
/// <param name="fillMethod">Fill method used</param>
|
||||
/// <param name="fillOrigin">fill origin to transform</param>
|
||||
/// <returns>RtoL value</returns>
|
||||
private static int GetRtoLFillOrigin(Image.FillMethod fillMethod, int fillOrigin)
|
||||
{
|
||||
if (fillMethod == Image.FillMethod.Horizontal)
|
||||
{
|
||||
switch (fillOrigin)
|
||||
{
|
||||
case (int)Image.OriginHorizontal.Left: return (int)Image.OriginHorizontal.Right;
|
||||
case (int)Image.OriginHorizontal.Right: return (int)Image.OriginHorizontal.Left;
|
||||
}
|
||||
}
|
||||
else if (fillMethod == Image.FillMethod.Radial90)
|
||||
{
|
||||
switch (fillOrigin)
|
||||
{
|
||||
case (int)Image.Origin90.BottomLeft: return (int)Image.Origin90.BottomRight;
|
||||
case (int)Image.Origin90.BottomRight: return (int)Image.Origin90.BottomLeft;
|
||||
case (int)Image.Origin90.TopLeft: return (int)Image.Origin90.TopRight;
|
||||
case (int)Image.Origin90.TopRight: return (int)Image.Origin90.TopLeft;
|
||||
}
|
||||
}
|
||||
else if (fillMethod == Image.FillMethod.Radial180)
|
||||
{
|
||||
switch (fillOrigin)
|
||||
{
|
||||
case (int)Image.Origin180.Left: return (int)Image.Origin180.Right;
|
||||
case (int)Image.Origin180.Right: return (int)Image.Origin180.Left;
|
||||
}
|
||||
}
|
||||
else if (fillMethod == Image.FillMethod.Radial360)
|
||||
{
|
||||
switch (fillOrigin)
|
||||
{
|
||||
case (int)Image.Origin360.Left: return (int)Image.Origin360.Right;
|
||||
case (int)Image.Origin360.Right: return (int)Image.Origin360.Left;
|
||||
}
|
||||
}
|
||||
|
||||
return fillOrigin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the component references and stores the initial values.
|
||||
/// </summary>
|
||||
private void CheckInitialize()
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if ULTIMATEXR_UNITY_TMPRO
|
||||
_textTMPro = GetComponent<TextMeshProUGUI>();
|
||||
|
||||
if (_textTMPro != null)
|
||||
{
|
||||
_alignmentTMPro = _textTMPro.alignment;
|
||||
}
|
||||
#endif
|
||||
_text = GetComponent<Text>();
|
||||
|
||||
if (_text != null)
|
||||
{
|
||||
_textAlignment = _text.alignment;
|
||||
}
|
||||
|
||||
_horizontalLayout = GetComponent<HorizontalLayoutGroup>();
|
||||
|
||||
if (_horizontalLayout)
|
||||
{
|
||||
_horLayoutAlignment = _horizontalLayout.childAlignment;
|
||||
_horLayoutReversed = _horizontalLayout.reverseArrangement;
|
||||
}
|
||||
|
||||
_verticalLayout = GetComponent<VerticalLayoutGroup>();
|
||||
|
||||
if (_verticalLayout)
|
||||
{
|
||||
_verLayoutAlignment = _verticalLayout.childAlignment;
|
||||
}
|
||||
|
||||
_gridLayout = GetComponent<GridLayoutGroup>();
|
||||
|
||||
if (_gridLayout)
|
||||
{
|
||||
_gridStartCorner = _gridLayout.startCorner;
|
||||
_gridChildAlignment = _gridLayout.childAlignment;
|
||||
}
|
||||
|
||||
_fillImage = GetComponent<Image>();
|
||||
|
||||
if (_fillImage != null && _fillImage.type == Image.Type.Filled)
|
||||
{
|
||||
_fillOrigin = _fillImage.fillOrigin;
|
||||
}
|
||||
else
|
||||
{
|
||||
_fillImage = null;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches this component to LtoR or RtoL.
|
||||
/// </summary>
|
||||
/// <param name="useRightToLeft">Whether to use RtoL (true) or LtoR (false)</param>
|
||||
private void SetRightToLeft(bool useRightToLeft)
|
||||
{
|
||||
CheckInitialize();
|
||||
|
||||
#if ULTIMATEXR_UNITY_TMPRO
|
||||
if (_textTMPro != null)
|
||||
{
|
||||
_textTMPro.alignment = useRightToLeft ? GetRtoLAlignmentTMPro(_alignmentTMPro) : _alignmentTMPro;
|
||||
}
|
||||
#endif
|
||||
if (_text != null)
|
||||
{
|
||||
_text.alignment = useRightToLeft ? GetRtoLAlignment(_textAlignment) : _textAlignment;
|
||||
}
|
||||
|
||||
if (_horizontalLayout != null)
|
||||
{
|
||||
_horizontalLayout.childAlignment = useRightToLeft ? GetRtoLAlignment(_horLayoutAlignment) : _horLayoutAlignment;
|
||||
_horizontalLayout.reverseArrangement = useRightToLeft ? !_horLayoutReversed : _horLayoutReversed;
|
||||
}
|
||||
|
||||
if (_verticalLayout != null)
|
||||
{
|
||||
_verticalLayout.childAlignment = useRightToLeft ? GetRtoLAlignment(_verLayoutAlignment) : _verLayoutAlignment;
|
||||
}
|
||||
|
||||
if (_gridLayout != null)
|
||||
{
|
||||
_gridLayout.startCorner = useRightToLeft ? GetRtoLCorner(_gridStartCorner) : _gridStartCorner;
|
||||
_gridLayout.childAlignment = useRightToLeft ? GetRtoLAlignment(_gridChildAlignment) : _gridChildAlignment;
|
||||
}
|
||||
|
||||
if (_fillImage != null)
|
||||
{
|
||||
_fillImage.fillOrigin = useRightToLeft ? GetRtoLFillOrigin(_fillImage.fillMethod, _fillOrigin) : _fillOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private static bool s_useRightToLeft;
|
||||
|
||||
private bool _initialized;
|
||||
private Text _text;
|
||||
private TextAnchor _textAlignment;
|
||||
private HorizontalLayoutGroup _horizontalLayout;
|
||||
private TextAnchor _horLayoutAlignment;
|
||||
private bool _horLayoutReversed;
|
||||
private VerticalLayoutGroup _verticalLayout;
|
||||
private TextAnchor _verLayoutAlignment;
|
||||
private GridLayoutGroup _gridLayout;
|
||||
private GridLayoutGroup.Corner _gridStartCorner;
|
||||
private TextAnchor _gridChildAlignment;
|
||||
private Image _fillImage;
|
||||
private int _fillOrigin;
|
||||
|
||||
#if ULTIMATEXR_UNITY_TMPRO
|
||||
private TextMeshProUGUI _textTMPro;
|
||||
private TextAlignmentOptions _alignmentTMPro;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0968a5f9d3d5caf4d91cd3e2011250d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user