Add ultimate xr

This commit is contained in:
2024-08-06 21:58:35 +02:00
parent 864033bf10
commit 7165bacd9d
3952 changed files with 2162037 additions and 35 deletions

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb3459a5e0294a478dcf6712b27704b1
timeCreated: 1640709321

View File

@@ -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
}
}

View File

@@ -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:

View File

@@ -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
}
}

View File

@@ -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:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eea1951b7bec08642a2234cbfa8dc391
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96e14cd674acb2e458e6fcb725350787
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -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:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0968a5f9d3d5caf4d91cd3e2011250d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: