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,3 @@
fileFormatVersion: 2
guid: 342bbee74e734c30970bd3ce59da488b
timeCreated: 1644566116

View File

@@ -0,0 +1,155 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAvatarComponent.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using UltimateXR.Avatar;
using UltimateXR.Extensions.Unity;
using UnityEngine;
namespace UltimateXR.Core.Components.Composite
{
/// <summary>
/// Generic base class for components that are added to an <see cref="UxrAvatar" /> and we want to keep track of.
/// It allows to enumerate components using static methods.
/// This class could have instead inherited from <see cref="UxrComponent{TP,TC}" /> but we avoided
/// this to not have redundancy between Avatar/Parent properties and methods.
/// </summary>
/// <typeparam name="T">Component type</typeparam>
public abstract class UxrAvatarComponent<T> : UxrComponent<T> where T : UxrAvatarComponent<T>
{
#region Public Types & Data
/// <summary>
/// Gets all the components, enabled or not, of this specific type that belong to the local avatar.
/// </summary>
/// <remarks>
/// Components that have never been enabled are not returned. Components are automatically registered through their
/// Awake() call, which is never called if the object has never been enabled. In this case it is recommended to resort
/// to <see cref="UnityEngine.GameObject.GetComponentsInChildren{T}(bool)">GetComponentsInChildren</see>.
/// </remarks>
public static IEnumerable<T> AllComponentsInLocalAvatar => AllComponents.Where(c => c.Avatar != null && c.Avatar.AvatarMode == UxrAvatarMode.Local);
/// <summary>
/// Gets all the enabled components of this specific type that belong to the local avatar.
/// </summary>
public static IEnumerable<T> EnabledComponentsInLocalAvatar => AllComponents.Where(c => c.Avatar != null && c.Avatar.AvatarMode == UxrAvatarMode.Local && c.isActiveAndEnabled);
/// <summary>
/// Gets the local avatar or null if there is none.
/// </summary>
public static UxrAvatar LocalAvatar
{
get
{
T component = AllComponents.FirstOrDefault(c => c.Avatar != null && c.Avatar.AvatarMode == UxrAvatarMode.Local);
return component == null ? null : component.Avatar;
}
}
/// <summary>
/// Gets all the components, enabled of not, of this specific type that belong to this instance of the avatar.
/// </summary>
/// <remarks>
/// Components that have never been enabled are not returned. Components are automatically registered through their
/// Awake() call, which is never called if the object has never been enabled. In this case it is recommended to resort
/// to <see cref="GameObject.GetComponentsInChildren{T}(bool)" />.
/// </remarks>
public IEnumerable<T> AllComponentsInAvatar => GetComponents(Avatar, true);
/// <summary>
/// Gets only the enabled components of this specific type that belong to this instance of the avatar.
/// </summary>
public IEnumerable<T> EnabledComponentsInAvatar => GetComponents(Avatar);
/// <summary>
/// Gets the <see cref="UxrAvatar" /> the component belongs to.
/// </summary>
public UxrAvatar Avatar
{
get
{
if (_avatar == null)
{
_avatar = this.SafeGetComponentInParent<UxrAvatar>();
}
return _avatar;
}
}
#endregion
#region Public Methods
/// <summary>
/// Gets the components of a specific avatar.
/// </summary>
/// <param name="avatar">Avatar to get the components from</param>
/// <param name="includeDisabled">Whether to include disabled components or not</param>
/// <returns>Components meeting the criteria</returns>
/// <remarks>
/// When using the <paramref name="includeDisabled" /> parameter, components that have never been enabled are not
/// returned. Components are automatically registered through their Awake() call, which is never called if the object
/// has never been enabled. In this case it is recommended to resort to
/// <see cref="GameObject.GetComponentsInChildren{T}(bool)" />.
/// </remarks>
public static IEnumerable<T> GetComponents(UxrAvatar avatar, bool includeDisabled = false)
{
if (includeDisabled)
{
return AllComponents.Where(c => c.Avatar == avatar);
}
return AllComponents.Where(c => c.Avatar == avatar && c.isActiveAndEnabled);
}
/// <summary>
/// Gets the components of a specific avatar.
/// </summary>
/// <param name="avatar">Avatar to get the components from</param>
/// <param name="includeDisabled">Whether to include disabled components or not</param>
/// <returns>Components meeting the criteria</returns>
/// <remarks>
/// When using the <paramref name="includeDisabled" /> parameter, components that have never been enabled are not
/// returned. Components are automatically registered through their Awake() call, which is never called if the object
/// has never been enabled. In this case it is recommended to resort to
/// <see cref="GameObject.GetComponentsInChildren{T}(bool)" />.
/// </remarks>
public static IEnumerable<TC> GetComponents<TC>(UxrAvatar avatar, bool includeDisabled = false) where TC : T
{
if (includeDisabled)
{
return AllComponents.OfType<TC>().Where(c => c.Avatar == avatar);
}
return AllComponents.OfType<TC>().Where(c => c.Avatar == avatar && c.isActiveAndEnabled);
}
#endregion
#region Unity
/// <summary>
/// Pre-caches the avatar component.
/// </summary>
protected override void Awake()
{
base.Awake();
if (_avatar == null)
{
_avatar = GetComponentInParent<UxrAvatar>();
}
}
#endregion
#region Private Types & Data
private UxrAvatar _avatar;
#endregion
}
}

View File

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

View File

@@ -0,0 +1,320 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrGrabbableObjectComponent.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core.Settings;
using UltimateXR.Manipulation;
using UltimateXR.Extensions.Unity;
using UnityEngine;
namespace UltimateXR.Core.Components.Composite
{
/// <summary>
/// Generic base class for components belonging to an object that also has a <see cref="UxrGrabbableObject" />
/// or in any of its parents. It allows to leverage some of the work related to accessing the
/// <see cref="UxrGrabbableObject" /> component and processing the events without the need to subscribe or
/// unsubscribe to them. Instead, events can be processed by overriding the different event triggers
/// (OnXXX methods).
/// <para>
/// The component has also all the benefits derived from <see cref="UxrComponent" />.
/// </para>
/// </summary>
/// <typeparam name="T">Component type</typeparam>
public abstract class UxrGrabbableObjectComponent<T> : UxrComponent<T> where T : UxrGrabbableObjectComponent<T>
{
#region Public Types & Data
/// <summary>
/// Gets whether the grabbable object is currently being grabbed.
/// </summary>
public bool IsBeingGrabbed => GrabbableObject && GrabbableObject.IsBeingGrabbed;
/// <summary>
/// Gets the grabbable object component.
/// </summary>
public UxrGrabbableObject GrabbableObject
{
get
{
if (_grabbableObject == null)
{
_grabbableObject = this.SafeGetComponentInParent<UxrGrabbableObject>();
}
return _grabbableObject;
}
private set => _grabbableObject = value;
}
#endregion
#region Unity
/// <summary>
/// Caches the grabbable object component.
/// </summary>
protected override void Awake()
{
base.Awake();
GrabbableObject = GetComponentInParent<UxrGrabbableObject>();
if (GrabbableObject == null && IsGrabbableObjectRequired)
{
if (UxrGlobalSettings.Instance.LogLevelManipulation >= UxrLogLevel.Errors)
{
Debug.LogError($"Component {nameof(T)} requires a {nameof(UxrGrabbableObject)} component in the same object or any of its parents.");
}
}
}
/// <summary>
/// Subscribes to events.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
if (GrabbableObject)
{
GrabbableObject.Grabbing += GrabbableObject_Grabbing;
GrabbableObject.Grabbed += GrabbableObject_Grabbed;
GrabbableObject.Releasing += GrabbableObject_Releasing;
GrabbableObject.Released += GrabbableObject_Released;
GrabbableObject.Placing += GrabbableObject_Placing;
GrabbableObject.Placed += GrabbableObject_Placed;
GrabbableObject.ConstraintsApplying += GrabbableObject_ConstraintsApplying;
GrabbableObject.ConstraintsApplied += GrabbableObject_ConstraintsApplied;
GrabbableObject.ConstraintsFinished += GrabbableObject_ConstraintsFinished;
}
}
/// <summary>
/// Unsubscribes from events.
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
if (GrabbableObject)
{
GrabbableObject.Grabbing -= GrabbableObject_Grabbing;
GrabbableObject.Grabbed -= GrabbableObject_Grabbed;
GrabbableObject.Releasing -= GrabbableObject_Releasing;
GrabbableObject.Released -= GrabbableObject_Released;
GrabbableObject.Placing -= GrabbableObject_Placing;
GrabbableObject.Placed -= GrabbableObject_Placed;
GrabbableObject.ConstraintsApplying -= GrabbableObject_ConstraintsApplying;
GrabbableObject.ConstraintsApplied -= GrabbableObject_ConstraintsApplied;
GrabbableObject.ConstraintsFinished -= GrabbableObject_ConstraintsFinished;
}
}
#endregion
#region Event Handling Methods
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Grabbing" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Grabbing(object sender, UxrManipulationEventArgs e)
{
OnObjectGrabbing(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Grabbed" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Grabbed(object sender, UxrManipulationEventArgs e)
{
OnObjectGrabbed(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Releasing" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Releasing(object sender, UxrManipulationEventArgs e)
{
OnObjectReleasing(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Released" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Released(object sender, UxrManipulationEventArgs e)
{
OnObjectReleased(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Placing" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Placing(object sender, UxrManipulationEventArgs e)
{
OnObjectPlacing(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.Placed" /> event. It will call the overridable event
/// trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_Placed(object sender, UxrManipulationEventArgs e)
{
OnObjectPlaced(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.ConstraintsApplying" /> event. It will call the
/// overridable event trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_ConstraintsApplying(object sender, UxrApplyConstraintsEventArgs e)
{
OnObjectConstraintsApplying(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.ConstraintsApplied" /> event. It will call the
/// overridable event trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_ConstraintsApplied(object sender, UxrApplyConstraintsEventArgs e)
{
OnObjectConstraintsApplied(e);
}
/// <summary>
/// Event handling method for the <see cref="UxrGrabbableObject.ConstraintsFinished" /> event. It will call the
/// overridable event trigger so that child classes don't need to subscribe to the event and can override the method instead.
/// </summary>
/// <param name="sender">The event sender</param>
/// <param name="e">The event parameters</param>
private void GrabbableObject_ConstraintsFinished(object sender, UxrApplyConstraintsEventArgs e)
{
OnObjectConstraintsFinished(e);
}
#endregion
#region Event Trigger Methods
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Grabbing" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectGrabbing(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Grabbed" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectGrabbed(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Releasing" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectReleasing(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Released" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectReleased(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Placing" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectPlacing(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.Placed" /> event that can be used to
/// handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectPlaced(UxrManipulationEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.ConstraintsApplying" /> event that can be
/// used to handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectConstraintsApplying(UxrApplyConstraintsEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.ConstraintsApplied" /> event that can be
/// used to handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectConstraintsApplied(UxrApplyConstraintsEventArgs e)
{
}
/// <summary>
/// Overridable event trigger method for the <see cref="UxrGrabbableObject.ConstraintsFinished" /> event that can be
/// used to handle it without requiring to subscribe/unsubscribe.
/// </summary>
/// <param name="e">Event parameters</param>
protected virtual void OnObjectConstraintsFinished(UxrApplyConstraintsEventArgs e)
{
}
#endregion
#region Protected Types & Data
/// <summary>
/// Gets whether the grabbable object component is required or it's not. By default it is required but it can be
/// overriden in child classes so that it is optional.
/// </summary>
protected virtual bool IsGrabbableObjectRequired => true;
#endregion
#region Private Types & Data
private UxrGrabbableObject _grabbableObject;
#endregion
}
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8dbb0a618ef647dd974f5201e2e40347
timeCreated: 1644249537

View File

@@ -0,0 +1,14 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IUxrSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// Interface for all classes that are singletons.
/// </summary>
public interface IUxrSingleton
{
}
}

View File

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

View File

@@ -0,0 +1,36 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAbstractSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// Singleton base class.
/// </summary>
public abstract class UxrAbstractSingleton : UxrComponent
{
#region Protected Overrides UxrComponent
/// <summary>
/// Singletons generate unique ID based on full type name. This ensures that the IDs are the same on all devices and
/// message exchanges will work correctly.
/// </summary>
protected override bool UniqueIdIsTypeName => true;
/// <inheritdoc />
protected override int SerializationOrder => UxrConstants.Serialization.SerializationOrderSingleton;
#endregion
#region Protected Types & Data
/// <summary>
/// Whether the singleton requires <see cref="UnityEngine.Object.DontDestroyOnLoad" /> applied to the GameObject so
/// that it doesn't get destroyed when a new scene is loaded.
/// </summary>
protected virtual bool NeedsDontDestroyOnLoad => true;
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e12d9e4e2a7b44819a93a23b5d53ddcc
timeCreated: 1644249666

View File

@@ -0,0 +1,239 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAbstractSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Threading;
using UltimateXR.Core.Settings;
using UltimateXR.Core.Threading;
using UnityEngine;
using UnityEngine.Assertions;
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// <para>
/// Base class for singletons that can be used with abstract classes.
/// </para>
/// <para>
/// The difference with <see cref="UxrSingleton{T}" /> is that <see cref="UxrSingleton{T}" /> guarantees
/// that an instance will always be available in the scene by instantiating the component if it's not found.
/// This means <see cref="UxrSingleton{T}.Instance" /> will always be non-null and can be used with or
/// without an instance available in the scene. <see cref="UxrSingleton{T}" /> also allows to use automatic
/// prefab instantiation if a compatible singleton prefab is present in a special Resources folder.
/// Since abstract classes can't be instantiated, <see cref="Instance" /> in <see cref="UxrAbstractSingleton{T}" />
/// will be non-null only if a child component is available somewhere in the scene.
/// </para>
/// <para>
/// For design purposes, a singleton may still be desirable when programming an abstract class, hence
/// this <see cref="UxrAbstractSingleton{T}" /> component base class.
/// </para>
/// </summary>
/// <typeparam name="T">Class the singleton is for</typeparam>
/// <remarks>
/// <list type="bullet">
/// <item>Make sure to call base.Awake() first in child classes where <see cref="Awake" /> is used.</item>
/// <item>Use <see cref="HasInstance" /> to check whether the instance exists.</item>
/// </list>
/// </remarks>
public abstract class UxrAbstractSingleton<T> : UxrAbstractSingleton, IUxrSingleton where T : UxrAbstractSingleton<T>
{
#region Public Types & Data
/// <summary>
/// Gets the unique, global instance of the given component.
/// </summary>
public static T Instance
{
get
{
if (s_instance is null)
{
UxrMonoDispatcher.RunOnMainThread(FindInstance);
while (s_instance is null && !UxrMonoDispatcher.IsCurrentThreadMain)
{
Thread.Sleep(25);
}
}
return s_instance;
}
}
/// <summary>
/// Gets whether there is a singleton instance available.
/// </summary>
public static bool HasInstance => s_instance != null;
/// <summary>
/// Gets or sets whether the singleton has been initialized.
/// </summary>
public bool IsInitialized { get; private set; }
#endregion
#region Unity
/// <summary>
/// Tries to set the singleton instance.
/// </summary>
protected override void Awake()
{
base.Awake();
TrySetInstance(this);
}
/// <summary>
/// Destroys the singleton instance.
/// </summary>
protected override void OnDestroy()
{
base.OnDestroy();
if (ReferenceEquals(this, s_instance))
{
Release();
}
}
#endregion
#region Protected Methods
/// <summary>
/// Gets the singleton instance.
/// </summary>
/// <returns></returns>
protected static T GetInstance()
{
return s_instance;
}
/// <summary>
/// Tries to set the singleton instance.
/// </summary>
/// <param name="value">Candidate to set as singleton instance</param>
/// <returns>Whether the instance was set</returns>
protected static bool TrySetInstance(UxrAbstractSingleton<T> value)
{
if (value is null)
{
return false;
}
if (ReferenceEquals(s_instance, value))
{
return true;
}
if (!(s_instance is null))
{
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Warnings)
{
Debug.LogWarning($"{UxrConstants.CoreModule} {typeof(T).Name} singleton already added. Destroying second instance @ {value.gameObject}", value);
}
Destroy(value);
return false;
}
Assert.IsTrue(value is T, $"Incoherent types: {value.GetType().Name} vs {typeof(T).Name}");
if (Application.isPlaying && value.NeedsDontDestroyOnLoad)
{
DontDestroyOnLoad(value.gameObject);
}
s_instance = (T)value;
s_instance.Init();
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Relevant)
{
Debug.Log($"{UxrConstants.CoreModule} {typeof(T).Name} singleton successfully initialized", s_instance);
}
return true;
}
/// <summary>
/// The default internal initialization. Child classes can override this method if they require initialization code.
/// </summary>
/// <param name="initializedCallback">Callback called when the initialization finished.</param>
protected virtual void InitInternal(Action initializedCallback)
{
initializedCallback?.Invoke();
}
/// <summary>
/// The default internal release. Child classes can override this method if they required deallocation code.
/// </summary>
/// <param name="releasedCallback">Callback called when the releasing finished.</param>
protected virtual void ReleaseInternal(Action releasedCallback)
{
releasedCallback?.Invoke();
}
#endregion
#region Private Methods
/*
/// <summary>
/// Called by Unity before a scene is loaded. Calls <see cref="TryFindInstance" />.
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void BeforeSceneLoad()
{
TryFindInstance();
}
*/
/// <summary>
/// Tries to find a pre-existing instance in the scene and set it as the singleton instance.
/// </summary>
/// <returns></returns>
private static bool TryFindInstance()
{
return TrySetInstance(FindObjectOfType<T>());
}
/// <summary>
/// Tries to find a pre-existing instance in the scene.
/// </summary>
private static void FindInstance()
{
TryFindInstance();
}
/// <summary>
/// Initializes the singleton.
/// </summary>
private void Init()
{
InitInternal(() => IsInitialized = true);
}
/// <summary>
/// Releases any resources allocated by the singleton.
/// </summary>
private void Release()
{
ReleaseInternal(() =>
{
if (!IsApplicationQuitting)
{
s_instance = null;
}
});
}
#endregion
#region Private Types & Data
private static T s_instance;
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8e9a4c7a7122d8c419e61e67a6e8d4e0
timeCreated: 1644249666

View File

@@ -0,0 +1,54 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAsyncInitAbstractSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
using UltimateXR.Core.Threading.TaskControllers;
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// Same as <see cref="UxrAsyncInitSingleton{T}" /> but allows asynchronous initialization.
/// This can be useful where singletons require initialization through config files that are loaded asynchronously from
/// disk or through network.
/// </summary>
/// <typeparam name="T">Type the singleton is for</typeparam>
public abstract class UxrAsyncInitAbstractSingleton<T> : UxrAbstractSingleton<T> where T : UxrAsyncInitAbstractSingleton<T>
{
#region Protected Overrides UxrAbstractSingleton<T>
/// <summary>
/// Initializes the singleton asynchronously. Calls <see cref="InitAsync" /> which is required to be implemented in
/// child classes.
/// </summary>
/// <param name="initializedCallback">Callback required to run when the initialization finished.</param>
protected override void InitInternal(Action initializedCallback)
{
_initController = (UxrTaskController)InitAsync;
_initController.Completed += (o, e) => initializedCallback?.Invoke();
_initController.Start();
}
#endregion
#region Protected Methods
/// <summary>
/// Initializes the singleton asynchronously.
/// </summary>
/// <param name="ct">Allows to cancel the asynchronous process if necessary</param>
/// <returns>Task representing the initialization</returns>
protected abstract Task InitAsync(CancellationToken ct = default);
#endregion
#region Private Types & Data
private UxrTaskController _initController;
#endregion
}
}

View File

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

View File

@@ -0,0 +1,54 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAsyncInitSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
using UltimateXR.Core.Threading.TaskControllers;
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// Same as <see cref="UxrSingleton{T}" /> but allows asynchronous initialization.
/// This can be useful where singletons require initialization through config files that are loaded asynchronously from
/// disk or through network.
/// </summary>
/// <typeparam name="T">Type the singleton is for</typeparam>
public abstract class UxrAsyncInitSingleton<T> : UxrSingleton<T> where T : UxrAsyncInitSingleton<T>
{
#region Protected Overrides UxrAbstractSingleton<T>
/// <summary>
/// Initializes the singleton asynchronously. Calls <see cref="InitAsync" /> which is required to be implemented in
/// child classes.
/// </summary>
/// <param name="initializedCallback">Callback required to run when the initialization finished.</param>
protected override void InitInternal(Action initializedCallback)
{
_initController = (UxrTaskController)InitAsync;
_initController.Completed += (o, e) => initializedCallback?.Invoke();
_initController.Start();
}
#endregion
#region Protected Methods
/// <summary>
/// Initializes the singleton asynchronously.
/// </summary>
/// <param name="ct">Allows to cancel the asynchronous process if necessary</param>
/// <returns>Task representing the initialization</returns>
protected abstract Task InitAsync(CancellationToken ct = default);
#endregion
#region Private Types & Data
private UxrTaskController _initController;
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 512ee11458e34e01ad20c7f127ee1b78
timeCreated: 1611582011

View File

@@ -0,0 +1,185 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrSingleton.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.IO;
using System.Threading;
using UltimateXR.Core.Settings;
using UltimateXR.Core.Threading;
using UltimateXR.Extensions.System.IO;
using UnityEngine;
namespace UltimateXR.Core.Components.Singleton
{
/// <summary>
/// <para>
/// An improved singleton implementation over <see cref="UxrAbstractSingleton{T}" /> for non-abstract classes.
/// <see cref="UxrSingleton{T}" /> guarantees that an <see cref="Instance" /> will always be available by
/// instantiating the singleton if it wasn't found in the scene. Additionally, it can instantiate a prefab
/// if there is one available in a well-known location.
/// </para>
/// <para>
/// The steps followed by this singleton implementation to assign the instance are the:
/// </para>
/// <para>
/// <list type="number">
/// <item>
/// The singleton component is searched in the scene to see if it was pre-instantiated or is already
/// available.
/// </item>
/// <item>
/// If not found, the component tries to be instantiated in the scene using a prefab in a well known
/// Resources folder. The well known path is <see cref="UxrConstants.Paths.SingletonResources" /> in any
/// Resources folder and the prefab name is the singleton class name.
/// A prefab allows to assign initial properties to the component and also hang additional resources
/// (meshes, textures) from the GameObject if needed.
/// </item>
/// <item>
/// If not found, a new <see cref="GameObject" /> is instantiated and the singleton is added using
/// <see cref="GameObject.AddComponent{T}" />.
/// </item>
/// </list>
/// </para>
/// </summary>
/// <remarks>
/// The singleton can be a pre-existing component in a scene. If not, <see cref="Instance" /> takes care of
/// instancing it and make it the singleton.
/// This singleton can only be used in sealed classes. For use in abstract classes check
/// <see cref="UxrAbstractSingleton{T}" /> instead.
/// </remarks>
/// <typeparam name="T">
/// Type the singleton is for. This template can only be used with a hierarchy where <typeparamref name="T" /> is
/// specified at its lowers level (sealed). For use in abstract classes, check <see cref="UxrAbstractSingleton{T}" />.
/// </typeparam>
public abstract class UxrSingleton<T> : UxrAbstractSingleton<T> where T : UxrSingleton<T>
{
#region Public Types & Data
/// <inheritdoc cref="UxrAbstractSingleton{T}.Instance" />
public new static T Instance
{
get
{
if (GetInstance() is null)
{
UxrMonoDispatcher.RunOnMainThread(FindOrAddInstance);
while (GetInstance() is null && !UxrMonoDispatcher.IsCurrentThreadMain)
{
Thread.Sleep(25);
}
}
return GetInstance();
}
}
#endregion
#region Public Methods
/// <summary>
/// Dummy method forcing <see cref="Instance" /> to run the instance finding/creation process.
/// </summary>
public void Poke()
{
}
#endregion
#region Private Methods
/// <summary>
/// Tries to find a pre-existing instance in the scene and set it as the singleton instance.
/// </summary>
/// <returns></returns>
private static bool TryFindInstance()
{
return TrySetInstance(FindObjectOfType<T>());
}
/// <summary>
/// <para>
/// Tries to find the singleton instance in the scene. If it was not found, a new singleton is instantiated
/// and assigned as the singleton instance. The following steps are used:
/// </para>
/// <list type="number">
/// <item>
/// The singleton component is searched in the scene to see if it was pre-instantiated or is already
/// available.
/// </item>
/// <item>
/// If not found, the component tries to be instantiated in the scene using a prefab in a well known
/// Resources folder. The well known path is <see cref="UxrConstants.Paths.SingletonResources" /> in any
/// Resources
/// folder and the prefab name is the singleton class name.
/// A prefab can be used to assign initial properties to the component and also hang additional resources
/// (meshes, textures) from the GameObject.
/// </item>
/// <item>
/// If not found, a new <see cref="GameObject" /> is instantiated and the singleton is added using
/// <see cref="GameObject.AddComponent{T}" />.
/// </item>
/// </list>
/// </summary>
private static void FindOrAddInstance()
{
// First: Try to find instance in scene
if (TryFindInstance())
{
return;
}
// Second: Try to instantiate it from Resources singleton folder
T prefab = Resources.Load<T>(ResourcesPrefabPath);
T instance = null;
if (prefab != null)
{
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Relevant)
{
Debug.Log($"{UxrConstants.CoreModule} {typeof(T).Name} was able to load prefab from Resources folder: {ResourcesPrefabPath}");
}
instance = Instantiate(prefab);
if (instance == null)
{
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Errors)
{
Debug.LogError($"{UxrConstants.CoreModule} {typeof(T).Name}: Unable to instantiate prefab. Instance is null. Path is {ResourcesPrefabPath}", prefab);
}
}
instance.name = prefab.name;
}
// Third: Try to instantiate it by creating a GameObject and adding the component
if (instance == null)
{
instance = new GameObject(typeof(T).Name).AddComponent<T>();
}
// Try to set it as the current singleton instance
if (!TrySetInstance(instance))
{
if (UxrGlobalSettings.Instance.LogLevelCore >= UxrLogLevel.Errors)
{
Debug.LogError($"{UxrConstants.CoreModule} {typeof(T).Name} singleton failed to initialize", instance);
}
}
}
#endregion
#region Private Types & Data
private static string ResourcesPrefabPath => PathExt.Combine(UxrConstants.Paths.SingletonResources, typeof(T).Name);
#endregion
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 9a6ca3fc203c1924db6eeaa1fb9cab40
timeCreated: 1519373620
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,221 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrComponent_1.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using UltimateXR.Core.Components.Composite;
using UnityEngine;
namespace UltimateXR.Core.Components
{
/// <summary>
/// Like <see cref="UxrComponent"/> but it allows to enumerate all components of a specific type.
/// </summary>
/// <typeparam name="T">Component type</typeparam>
/// <remarks>
/// Components get registered through their Awake() call. This means that components get registered
/// the first time they are enabled. Disabled objects that have been enabled at some point are enumerated, but objects
/// that have never been enabled don't get enumerated, which means that they will not appear in
/// <see cref="AllComponents" />.
/// </remarks>
/// <seealso cref="UxrAvatarComponent{T}" />
public abstract class UxrComponent<T> : UxrComponent where T : UxrComponent<T>
{
#region Public Types & Data
/// <summary>
/// Called before registering a component.
/// </summary>
public new static event Action<T> GlobalRegistering;
/// <summary>
/// Called when a component was registered.
/// </summary>
public new static event Action<T> GlobalRegistered;
/// <summary>
/// Called before unregistering a component.
/// </summary>
public new static event Action<T> GlobalUnregistering;
/// <summary>
/// Called when a component was unregistered.
/// </summary>
public new static event Action<T> GlobalUnregistered;
/// <summary>
/// Called when a component was enabled.
/// </summary>
public new static event Action<T> GlobalEnabled;
/// <summary>
/// Called when a component was disabled.
/// </summary>
public new static event Action<T> GlobalDisabled;
/// <summary>
/// Gets all the components of this specific type, enabled or not, in all open scenes.
/// </summary>
/// <remarks>
/// Components that have never been enabled are not returned. Components are automatically registered through their
/// Awake() call, which is never called if the object has never been enabled. In this case it is recommended to resort
/// to <see cref="GameObject.GetComponentsInChildren{T}(bool)" /> or
/// <see cref="UnityEngine.Object.FindObjectsOfType{T}(bool)" />.
/// </remarks>
public new static IEnumerable<T> AllComponents => s_typeComponents;
/// <summary>
/// Gets all components of this specific type that are enabled, in all open scenes.
/// </summary>
public new static IEnumerable<T> EnabledComponents => s_typeComponents.Where(c => c.isActiveAndEnabled);
#endregion
#region Public Methods
/// <summary>
/// Sorts the internal list of components. This is useful if iterating over the components requires a certain order.
/// </summary>
/// <param name="comparison">Comparison to use for sorting</param>
public static void SortComponents(Comparison<T> comparison)
{
s_typeComponents.Sort(comparison);
}
/// <summary>
/// Destroys all components.
/// </summary>
public new static void DestroyAllComponents()
{
foreach (T component in s_typeComponents)
{
Destroy(component);
}
}
/// <summary>
/// Destroys all gameObjects the components belong to.
/// </summary>
public new static void DestroyAllGameObjects()
{
foreach (T component in s_typeComponents)
{
Destroy(component.gameObject);
}
}
#endregion
#region Unity
/// <summary>
/// Registers itself in the static list of components.
/// </summary>
protected override void Awake()
{
base.Awake();
OnRegistering();
s_typeComponents.Add((T)this);
OnRegistered();
}
/// <summary>
/// Removes itself from the static list of components.
/// </summary>
protected override void OnDestroy()
{
base.OnDestroy();
OnUnregistering();
s_typeComponents.Remove((T)this);
OnUnregistered();
}
/// <summary>
/// Triggers enabled events.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
OnEnabled();
}
/// <summary>
/// Triggers disabled events.
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
OnDisabled();
}
#endregion
#region Event Trigger Methods
/// <summary>
/// <see cref="GlobalRegistering" /> event trigger.
/// </summary>
private void OnRegistering()
{
GlobalRegistering?.Invoke(this as T);
}
/// <summary>
/// <see cref="GlobalRegistered" /> event trigger.
/// </summary>
private void OnRegistered()
{
GlobalRegistered?.Invoke(this as T);
}
/// <summary>
/// <see cref="GlobalUnregistering" /> event trigger.
/// </summary>
private void OnUnregistering()
{
GlobalUnregistering?.Invoke(this as T);
}
/// <summary>
/// <see cref="GlobalUnregistered" /> event trigger.
/// </summary>
private void OnUnregistered()
{
GlobalUnregistered?.Invoke(this as T);
}
/// <summary>
/// <see cref="GlobalEnabled" /> event trigger.
/// </summary>
private void OnEnabled()
{
GlobalEnabled?.Invoke(this as T);
}
/// <summary>
/// <see cref="GlobalDisabled" /> event trigger.
/// </summary>
private void OnDisabled()
{
GlobalDisabled?.Invoke(this as T);
}
#endregion
#region Private Types & Data
/// <summary>
/// Static list containing all registered components of this type.
/// </summary>
private static readonly List<T> s_typeComponents = new List<T>();
#endregion
}
}

View File

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

View File

@@ -0,0 +1,82 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrComponent_2.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using UltimateXR.Avatar;
using UltimateXR.Core.Components.Composite;
using UltimateXR.Extensions.Unity;
using UnityEngine;
namespace UltimateXR.Core.Components
{
/// <summary>
/// <para>
/// Like <see cref="UxrComponent{T}" /> but the component belongs to a hierarchy
/// with a parent that has a component of a certain type <typeparamref name="TP" />.
/// This allows to enumerate and keep track of only the components that hang from the hierarchy
/// under each parent component separately.
/// </para>
/// <para>
/// In the case of keeping track of all components of a same type that are in or hang from an avatar (
/// <see cref="UxrAvatar" />) there is a special component for that in <see cref="UxrAvatarComponent{T}" />.
/// </para>
/// </summary>
/// <typeparam name="TP">Parent component type</typeparam>
/// <typeparam name="TC">Component type</typeparam>
public abstract class UxrComponent<TP, TC> : UxrComponent<TC>
where TP : Component
where TC : UxrComponent<TC>
{
#region Public Types & Data
/// <summary>
/// Gets all the components, enabled of not, of this specific type that hang from the same parent.
/// </summary>
/// <remarks>
/// Components that have never been enabled are not returned. Components are automatically registered through their
/// Awake() call, which is never called if the object has never been enabled. In this case it is recommended to resort
/// to <see cref="GameObject.GetComponentsInChildren{T}(bool)" />.
/// </remarks>
public IEnumerable<TC> AllChildrenFromParent => GetParentChildren(Parent, true);
/// <summary>
/// Gets only the enabled components of this specific type that hang from the same parent.
/// </summary>
public IEnumerable<TC> EnabledChildrenFromParent => GetParentChildren(Parent);
/// <summary>
/// Parent the component belongs to.
/// </summary>
public TP Parent => gameObject.SafeGetComponentInParent<TP>();
#endregion
#region Public Methods
/// <summary>
/// Gets the children from a specific parent.
/// </summary>
/// <param name="parent">Parent to get the components from</param>
/// <param name="includeDisabled">Whether to include disabled components or not</param>
/// <returns>Components meeting the criteria</returns>
/// <remarks>
/// When using the <paramref name="includeDisabled" /> parameter, components that have never been enabled are not
/// returned. Components are automatically registered through their Awake() call, which is never called if the object
/// has never been enabled. In this case it is recommended to resort to
/// <see cref="GameObject.GetComponentsInChildren{T}(bool)" />.
/// </remarks>
public static IEnumerable<TC> GetParentChildren(TP parent, bool includeDisabled = false)
{
if (includeDisabled)
{
return AllComponents.Where(c => c is UxrComponent<TP, TC> child && child.Parent == parent);
}
return AllComponents.Where(c => c is UxrComponent<TP, TC> child && child.Parent == parent && c.isActiveAndEnabled);
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrSyncObject.StateSave.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Core.Components
{
public partial class UxrSyncObject
{
#region Protected Overrides UxrComponent
/// <inheritdoc />
protected override bool SaveStateWhenDisabled => _syncWhileDisabled;
/// <inheritdoc />
protected override bool SerializeActiveAndEnabledState => _syncActiveAndEnabled;
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 115582f99ade41d98a39ff08c14120ff
timeCreated: 1715540449

View File

@@ -0,0 +1,56 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrSyncObject.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core.StateSave;
using UltimateXR.Core.Unique;
using UnityEngine;
namespace UltimateXR.Core.Components
{
/// <summary>
/// Minimal <see cref="UxrComponent" /> component that can be used to identify GameObjects that don't have any other
/// <see cref="UxrComponent" />. Additionally, it can control which Transform to sync, if any.
/// This can be useful in multiplayer environments to reference objects. For example, an avatar might be parented to a
/// moving platform and this operation needs to be executed in other client PCs.
/// If there is no reference to this platform (it might be the result of performing a raycast and not because a script
/// has a reference to it, for instance), there needs to be a way to get the same GameObject in the other PCS.
/// Since <see cref="UxrComponent" /> has a way to identify and obtain components (<see cref="UxrComponent.UniqueId" />
/// and <see cref="UxrUniqueIdImplementer.TryGetComponentById" />), a simple way to send references through the network
/// is by using a <see cref="UxrSyncObject" /> component on the GameObject.
/// </summary>
public partial class UxrSyncObject : UxrComponent
{
#region Inspector Properties/Serialized Fields
[SerializeField] private bool _syncTransform;
[SerializeField] private UxrTransformSpace _transformSpace = UxrTransformSpace.World;
[SerializeField] private bool _syncActiveAndEnabled;
[SerializeField] private bool _syncWhileDisabled;
#endregion
#region Public Types & Data
/// <summary>
/// Gets whether the transform should be synchronized.
/// </summary>
public bool SyncTransform => _syncTransform;
#endregion
#region Protected Overrides UxrComponent
/// <inheritdoc />
protected override UxrTransformSpace TransformStateSaveSpace => _transformSpace;
/// <inheritdoc />
protected override bool RequiresTransformSerialization(UxrStateSaveLevel level)
{
return SyncTransform;
}
#endregion
}
}

View File

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