#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; using UnityEngine; namespace Unity.XR.PXR { /// /// Manages communication of changes between an application and the UnityPXR_ lib for all /// objects. /// /// /// PXR_ 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 PXR_LayerProvider via . /// public class PXR_LayerProvider : 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 UnityPXR_ 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 PXR_LayerProvider. /// Initializes and registers all the default, built-in layer handlers. /// /// /// The PXR_LayerProvider is created and disposed by the . /// You do not need to create an instance of PXR_LayerProvider yourself. Layer handlers /// should only use the static methods and properties of this class /// public PXR_LayerProvider() => InitializeAndRegisterBuiltInHandlers(); /// /// Calls the methods in its invocation list when the PXR_LayerProvider has started and registered it's built-in layer handlers. /// /// /// You can use this event to wait for the PXR_LayerProvider 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 PXR_LayerProvider has stopped and is disposed. /// public static event Action Stopped; /// /// Reports whether the PXR_LayerProvider has already been created and started. /// public static bool isStarted { get; set; } static Dictionary LayerHandlers = new Dictionary(); static readonly ProfilerMarker s_PXR_LayerProviderCreate = new ProfilerMarker("PXR_LayerProvider.Create"); static readonly ProfilerMarker s_PXR_LayerProviderRemove = new ProfilerMarker("PXR_LayerProvider.Remove"); static readonly ProfilerMarker s_PXR_LayerProviderModify = new ProfilerMarker("PXR_LayerProvider.Modify"); static readonly ProfilerMarker s_PXR_LayerProviderActive = new ProfilerMarker("PXR_LayerProvider.Active"); static readonly ProfilerMarker s_PXR_LayerProviderUpdate = new ProfilerMarker("PXR_LayerProvider.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 PXR_LayerProvider 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_PXR_LayerProviderRemove.Begin(); handler?.RemoveLayer(removed); s_PXR_LayerProviderRemove.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_PXR_LayerProviderCreate.Begin(); handler?.CreateLayer(created); s_PXR_LayerProviderCreate.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_PXR_LayerProviderModify.Begin(); handler?.ModifyLayer(modified); s_PXR_LayerProviderModify.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_PXR_LayerProviderActive.Begin(); handler?.SetActiveLayer(active); s_PXR_LayerProviderActive.End(); } } } foreach (var handler in LayerHandlers.Values) { s_PXR_LayerProviderUpdate.Begin(); handler?.OnUpdate(); s_PXR_LayerProviderUpdate.End(); } } /// /// Used for cleanup and to call Dispose() on registered layer handlers. /// /// This is called by the PXR_Loader 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 PXR_DefaultLayer(); var quadLayerHandler = new PXR_QuadLayer(); //var projectionLayerHandler = new PXR_ProjectionLayer(); var cylinderLayerHandler = new PXR_CylinderLayer(); var cubeLayerHandler = new PXR_CubeLayer() ; ILayerHandler equirectLayerHandler = new PXR_Equirect2Layer() ; // 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