#if XR_COMPOSITION_LAYERS using System; using System.Collections.Generic; using System.Reflection.Emit; using Unity.Profiling; using Unity.XR.CompositionLayers.Extensions; using Unity.XR.CompositionLayers.Layers; using Unity.XR.CompositionLayers.Provider; using Unity.XR.CompositionLayers.Services; namespace UnityEngine.XR.OpenXR.CompositionLayers { /// /// Manages communication of changes between an application and the UnityOpenXR lib for all /// objects. /// /// /// OpenXR providers or extensions that create custom composition layer types or that override how the built-in /// layer types are handled, must implement the interface and register instances of /// these implementations with the OpenXRLayerProvider via . /// public class OpenXRLayerProvider : ILayerProvider, IDisposable { /// /// An interface used by the to communicate layer data changes to /// registered layer handlers. /// /// /// ILayerHandler instances must register themselves via /// /// to specify the type to handle. /// If more than one object registers itself as a handler for a specific /// type, the last registered handler is used. /// /// The class provides a partial, base implementation of this interface that you can /// use to create custom layer handlers. /// public interface ILayerHandler { /// /// Called by the during the Unity Update loop. /// All implementations must call every frame /// to add their native layer structs to the endFrameInfo struct inside the UnityOpenXR lib. /// public void OnUpdate(); /// /// Called by the when a new /// object of the type registered to this ILayerHandler instance has been created. /// /// Container for the instance id and CompositionLayer component of the composition layer /// that was just created. public void CreateLayer(CompositionLayerManager.LayerInfo layerInfo); /// /// Called by the when a object /// of the type registered to this ILayerHandler instance has been destroyed or disabled. /// /// The instance id of the CompositionLayer component that was removed. public void RemoveLayer(int id); /// /// Called by the when a object /// or any attached extension components have had a member modified. /// /// Container for the instance id and CompositionLayer component of the composition layer /// that was modified. public void ModifyLayer(CompositionLayerManager.LayerInfo layerInfo); /// /// Called every frame by the for all currently active objects /// of the type registered to this ILayerHandler instance. /// /// Container for the instance id and CompositionLayer component of the composition layer /// being set to active. public void SetActiveLayer(CompositionLayerManager.LayerInfo layerInfo); } /// /// Initializes and returns an instance of OpenXRLayerProvider. /// Initializes and registers all the default, built-in layer handlers. /// /// /// The OpenXRLayerProvider is created and disposed by the . /// You do not need to create an instance of OpenXRLayerProvider yourself. Layer handlers /// should only use the static methods and properties of this class /// public OpenXRLayerProvider() => InitializeAndRegisterBuiltInHandlers(); /// /// Calls the methods in its invocation list when the OpenXRLayerProvider has started and registered it's built-in layer handlers. /// /// /// You can use this event to wait for the OpenXRLayerProvider to finish registering its built-in layer handlers /// so that you can override them with your own custom layer handlers. /// public static event Action Started; /// /// Calls the methods in its invocation list when the OpenXRLayerProvider has stopped and is disposed. /// public static event Action Stopped; /// /// Reports whether the OpenXRLayerProvider has already been created and started. /// public static bool isStarted { get; set; } static Dictionary LayerHandlers = new Dictionary(); static readonly ProfilerMarker s_OpenXRLayerProviderCreate = new ProfilerMarker("OpenXRLayerProvider.Create"); static readonly ProfilerMarker s_OpenXRLayerProviderRemove = new ProfilerMarker("OpenXRLayerProvider.Remove"); static readonly ProfilerMarker s_OpenXRLayerProviderModify = new ProfilerMarker("OpenXRLayerProvider.Modify"); static readonly ProfilerMarker s_OpenXRLayerProviderActive = new ProfilerMarker("OpenXRLayerProvider.Active"); static readonly ProfilerMarker s_OpenXRLayerProviderUpdate = new ProfilerMarker("OpenXRLayerProvider.Update"); /// /// Registers a concrete object as the handler for all layers of a specific /// subclass. /// /// /// If more than one object registers itself as a handler for a specific /// type, the last registered handler is used. /// /// The OpenXRLayerProvider invokes the registered layer handler's methods /// when any object of the associated type is updated in some way. /// /// The subclass to handle. /// The concrete ILayerHandler instance> to register. public static void RegisterLayerHandler(Type layerDataType, ILayerHandler handler) { if (handler == null) { LayerHandlers.Remove(layerDataType); return; } LayerHandlers[layerDataType] = handler; } /// /// Sets the layer provider state on first assignment to the . /// /// The list of all currently known instances, regardless of active state. public void SetInitialState(List layers) { UpdateLayers(layers, null, null, null); } /// /// Called by the to tell the instance of about /// the current state of layers it is managing. /// /// /// The list of layers that were just created. Any layer in /// this list may be in the list if it is activated in the same frame. /// Any layer in this list should not be in or . /// This list is ephemeral and cleared after each call. /// /// The list of layers that are no longer being managed. Any layer in /// this list should not be in the , , or /// lists. /// This list is ephemeral and cleared after each call. /// /// The list of layers that have been recently modified. Any layer in /// this list may also be in the list. Any layer in this list should not /// be in or . /// This list is ephemeral and cleared after each call. /// /// The list of layers currently active within the scene. /// Layers in this list may also be in the or lists /// if they became active in the same frame. public void UpdateLayers(List createdLayers, List removedLayers, List modifiedLayers, List activeLayers) { if (removedLayers != null && removedLayers.Count != 0) { foreach (var handler in LayerHandlers.Values) { foreach (var removed in removedLayers) { s_OpenXRLayerProviderRemove.Begin(); handler?.RemoveLayer(removed); s_OpenXRLayerProviderRemove.End(); } } } if (createdLayers != null && createdLayers.Count != 0) { foreach (var created in createdLayers) { if (created.Layer == null) continue; var layerDataType = created.Layer.LayerData.GetType(); if (LayerHandlers.TryGetValue(layerDataType, out ILayerHandler handler)) { s_OpenXRLayerProviderCreate.Begin(); handler?.CreateLayer(created); s_OpenXRLayerProviderCreate.End(); } } } if (modifiedLayers != null && modifiedLayers.Count != 0) { foreach (var modified in modifiedLayers) { if (modified.Layer == null) continue; var layerDataType = modified.Layer.LayerData.GetType(); if (LayerHandlers.TryGetValue(layerDataType, out ILayerHandler handler)) { s_OpenXRLayerProviderModify.Begin(); handler?.ModifyLayer(modified); s_OpenXRLayerProviderModify.End(); } } } if (activeLayers != null && activeLayers.Count != 0) { foreach (var active in activeLayers) { if (active.Layer == null) continue; var layerDataType = active.Layer.LayerData.GetType(); if (LayerHandlers.TryGetValue(layerDataType, out ILayerHandler handler)) { s_OpenXRLayerProviderActive.Begin(); handler?.SetActiveLayer(active); s_OpenXRLayerProviderActive.End(); } } } foreach (var handler in LayerHandlers.Values) { s_OpenXRLayerProviderUpdate.Begin(); handler?.OnUpdate(); s_OpenXRLayerProviderUpdate.End(); } } /// /// Used for cleanup and to call Dispose() on registered layer handlers. /// /// This is called by the OpenXRLoader class when StopInternal() is invoked. public void Dispose() { foreach (var handler in LayerHandlers.Values) { if (handler is IDisposable) { ((IDisposable)handler)?.Dispose(); } } LayerHandlers.Clear(); isStarted = false; Stopped?.Invoke(); } public void CleanupState() { } public void LateUpdate() { } void InitializeAndRegisterBuiltInHandlers() { var defaultLayerHandler = new OpenXRDefaultLayer(); var quadLayerHandler = new OpenXRQuadLayer(); var projectionLayerHandler = new OpenXRProjectionLayer(); var cylinderLayerHandler = OpenXRCylinderLayer.ExtensionEnabled ? new OpenXRCylinderLayer() : null; var cubeLayerHandler = OpenXRCubeLayer.ExtensionEnabled ? new OpenXRCubeLayer() : null; ILayerHandler equirectLayerHandler = OpenXREquirect2Layer.ExtensionEnabled ? new OpenXREquirect2Layer() : OpenXREquirectLayer.ExtensionEnabled ? new OpenXREquirectLayer() : null; RegisterLayerHandler(typeof(DefaultLayerData), defaultLayerHandler); RegisterLayerHandler(typeof(QuadLayerData), quadLayerHandler); RegisterLayerHandler(typeof(CylinderLayerData), cylinderLayerHandler); RegisterLayerHandler(typeof(ProjectionLayerData), projectionLayerHandler); RegisterLayerHandler(typeof(ProjectionLayerRigData), projectionLayerHandler); RegisterLayerHandler(typeof(CubeProjectionLayerData), cubeLayerHandler); RegisterLayerHandler(typeof(EquirectMeshLayerData), equirectLayerHandler); isStarted = true; Started?.Invoke(); } } } #endif