#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