version 2.0.0
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using VIVE.OpenXR.CompositionLayer;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
public class CompositionLayerManager : MonoBehaviour
|
||||
{
|
||||
private uint maxLayerCount = 0;
|
||||
|
||||
private static CompositionLayerManager instance = null;
|
||||
private List<CompositionLayer> compositionLayers = new List<CompositionLayer>();
|
||||
private List<CompositionLayer> compositionLayersToBeSubscribed = new List<CompositionLayer>();
|
||||
private List<CompositionLayer> compositionLayersToBeUnsubscribed = new List<CompositionLayer>();
|
||||
|
||||
private bool isOnBeforeRenderSubscribed = false;
|
||||
private ViveCompositionLayer compositionLayerFeature = null;
|
||||
|
||||
private const string LOG_TAG = "VIVE_CompositionLayerManager";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
#region public parameter access functions
|
||||
public static CompositionLayerManager GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
GameObject CompositionLayerManagerGO = new GameObject("MultiLayerManager", typeof(CompositionLayerManager));
|
||||
instance = CompositionLayerManagerGO.GetComponent<CompositionLayerManager>();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static bool CompositionLayerManagerExists()
|
||||
{
|
||||
return (instance != null);
|
||||
}
|
||||
|
||||
public int MaxLayerCount()
|
||||
{
|
||||
return (int)maxLayerCount;
|
||||
}
|
||||
|
||||
public int RemainingLayerCount()
|
||||
{
|
||||
int count = (int)maxLayerCount - compositionLayers.Count;
|
||||
if (count < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public int CurrentLayerCount()
|
||||
{
|
||||
return compositionLayers.Count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Monobehaviour Lifecycle
|
||||
void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
else if (instance != this)
|
||||
{
|
||||
Destroy(instance);
|
||||
instance = this;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UpdateMaxLayerCount();
|
||||
}
|
||||
|
||||
public delegate void CompositionLayerManagerOnBeforeRender();
|
||||
public event CompositionLayerManagerOnBeforeRender CompositionLayerManagerOnBeforeRenderDelegate = null;
|
||||
|
||||
private void OnBeforeRender()
|
||||
{
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
if (compositionLayerFeature != null)
|
||||
{
|
||||
if (compositionLayerFeature.XrSessionEnding)
|
||||
{
|
||||
DEBUG("XrSession is ending, stop all layers");
|
||||
foreach (CompositionLayer layer in compositionLayers) //All active layers
|
||||
{
|
||||
if (!compositionLayersToBeUnsubscribed.Contains(layer) && !compositionLayersToBeSubscribed.Contains(layer))
|
||||
{
|
||||
//Add currently active layers that are not scheduled for termination to the "To be subscribed" list
|
||||
compositionLayersToBeSubscribed.Add(layer);
|
||||
}
|
||||
|
||||
layer.TerminateLayer();
|
||||
}
|
||||
compositionLayers.Clear();
|
||||
|
||||
foreach (CompositionLayer layer in compositionLayersToBeUnsubscribed) //All layers to be terminated
|
||||
{
|
||||
layer.TerminateLayer();
|
||||
}
|
||||
compositionLayersToBeUnsubscribed.Clear();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("compositionLayerFeature not found");
|
||||
}
|
||||
|
||||
bool CompositionLayerStatusUpdateNeeded = false;
|
||||
|
||||
//Process Sub and Unsub list in bulk at once per frame
|
||||
if (compositionLayersToBeUnsubscribed.Count > 0)
|
||||
{
|
||||
foreach (CompositionLayer layerToBeRemoved in compositionLayersToBeUnsubscribed)
|
||||
{
|
||||
DEBUG("CompositionLayersToBeUnsubscribed: Processing");
|
||||
if (compositionLayers.Contains(layerToBeRemoved) && !compositionLayersToBeSubscribed.Contains(layerToBeRemoved))
|
||||
{
|
||||
layerToBeRemoved.TerminateLayer();
|
||||
compositionLayers.Remove(layerToBeRemoved);
|
||||
}
|
||||
}
|
||||
compositionLayersToBeUnsubscribed.Clear();
|
||||
CompositionLayerStatusUpdateNeeded = true;
|
||||
}
|
||||
|
||||
if (compositionLayersToBeSubscribed.Count > 0)
|
||||
{
|
||||
DEBUG("CompositionLayersToBeSubscribed: Processing");
|
||||
foreach (CompositionLayer layerToBeAdded in compositionLayersToBeSubscribed)
|
||||
{
|
||||
if (!compositionLayers.Contains(layerToBeAdded))
|
||||
{
|
||||
compositionLayers.Add(layerToBeAdded);
|
||||
DEBUG("Add new layer");
|
||||
}
|
||||
else if (layerToBeAdded.isRenderPriorityChanged)
|
||||
{
|
||||
DEBUG("Layer RenderPriority changed");
|
||||
}
|
||||
}
|
||||
compositionLayersToBeSubscribed.Clear();
|
||||
CompositionLayerStatusUpdateNeeded = true;
|
||||
}
|
||||
|
||||
if (CompositionLayerStatusUpdateNeeded)
|
||||
{
|
||||
DEBUG("CompositionLayerStatusUpdateNeeded");
|
||||
UpdateLayerStatus();
|
||||
CompositionLayerStatusUpdateNeeded = false;
|
||||
}
|
||||
|
||||
CompositionLayerManagerOnBeforeRenderDelegate?.Invoke();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!isOnBeforeRenderSubscribed)
|
||||
{
|
||||
Application.onBeforeRender += OnBeforeRender;
|
||||
isOnBeforeRenderSubscribed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (isOnBeforeRenderSubscribed)
|
||||
{
|
||||
Application.onBeforeRender -= OnBeforeRender;
|
||||
isOnBeforeRenderSubscribed = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (isOnBeforeRenderSubscribed)
|
||||
{
|
||||
Application.onBeforeRender -= OnBeforeRender;
|
||||
isOnBeforeRenderSubscribed = false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void SubscribeToLayerManager(CompositionLayer layerToBeAdded)
|
||||
{
|
||||
if (compositionLayersToBeSubscribed == null)
|
||||
{
|
||||
DEBUG("SubscribeToLayerManager: Layer List not found. Creating a new one.");
|
||||
compositionLayersToBeSubscribed = new List<CompositionLayer>();
|
||||
}
|
||||
|
||||
if (!compositionLayersToBeSubscribed.Contains(layerToBeAdded))
|
||||
{
|
||||
DEBUG("SubscribeToLayerManager: Add layer");
|
||||
compositionLayersToBeSubscribed.Add(layerToBeAdded);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnsubscribeFromLayerManager(CompositionLayer layerToBeRemoved, bool isImmediate)
|
||||
{
|
||||
if (compositionLayersToBeUnsubscribed == null)
|
||||
{
|
||||
DEBUG("UnsubscribeFromLayerManager: Layer List not found. Creating a new one.");
|
||||
compositionLayersToBeUnsubscribed = new List<CompositionLayer>();
|
||||
}
|
||||
|
||||
if (!compositionLayersToBeUnsubscribed.Contains(layerToBeRemoved) && !isImmediate)
|
||||
{
|
||||
DEBUG("UnsubscribeFromLayerManager: Remove layer");
|
||||
compositionLayersToBeUnsubscribed.Add(layerToBeRemoved);
|
||||
}
|
||||
else if (isImmediate)
|
||||
{
|
||||
layerToBeRemoved.TerminateLayer();
|
||||
|
||||
if (compositionLayersToBeUnsubscribed.Contains(layerToBeRemoved))
|
||||
{
|
||||
compositionLayersToBeUnsubscribed.Remove(layerToBeRemoved);
|
||||
}
|
||||
|
||||
if (compositionLayersToBeSubscribed.Contains(layerToBeRemoved))
|
||||
{
|
||||
compositionLayersToBeSubscribed.Remove(layerToBeRemoved);
|
||||
}
|
||||
|
||||
if (compositionLayers.Contains(layerToBeRemoved))
|
||||
{
|
||||
compositionLayers.Remove(layerToBeRemoved);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLayerStatus()
|
||||
{
|
||||
SortCompositionLayers();
|
||||
RenderCompositionLayers();
|
||||
}
|
||||
|
||||
private void SortCompositionLayers()
|
||||
{
|
||||
if (compositionLayers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CompositionLayerRenderPriorityComparer renderPriorityComparer = new CompositionLayerRenderPriorityComparer();
|
||||
compositionLayers.Sort(renderPriorityComparer);
|
||||
}
|
||||
|
||||
private void RenderCompositionLayers()
|
||||
{
|
||||
UpdateMaxLayerCount();
|
||||
|
||||
for (int layerIndex=0; layerIndex < compositionLayers.Count; layerIndex++)
|
||||
{
|
||||
if (layerIndex < maxLayerCount) //Render as normal layers
|
||||
{
|
||||
if (compositionLayers[layerIndex].RenderAsLayer()) //Successfully initialized
|
||||
{
|
||||
DEBUG("RenderCompositionLayers: Layer " + compositionLayers[layerIndex].name + " Initialized successfully, Priority: " + compositionLayers[layerIndex].GetRenderPriority() + " layerIndex: " + layerIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("RenderCompositionLayers: Layer Initialization failed." + " layerIndex: " + layerIndex);
|
||||
}
|
||||
}
|
||||
else //Fallback if enabled
|
||||
{
|
||||
compositionLayers[layerIndex].RenderInGame();
|
||||
DEBUG("RenderCompositionLayers: Layer " + compositionLayers[layerIndex].name + " Rendering in game, Priority: " + compositionLayers[layerIndex].GetRenderPriority() + " layerIndex: " + layerIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMaxLayerCount()
|
||||
{
|
||||
XrSystemProperties xrSystemProperties = new XrSystemProperties();
|
||||
XrResult result;
|
||||
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
if (compositionLayerFeature != null)
|
||||
{
|
||||
if ((result = compositionLayerFeature.GetSystemProperties(ref xrSystemProperties)) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
maxLayerCount = xrSystemProperties.graphicsProperties.maxLayerCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("Failed to get max layer count: " + result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("compositionLayerFeature not found");
|
||||
maxLayerCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class CompositionLayerRenderPriorityComparer : IComparer<CompositionLayer>
|
||||
{
|
||||
public int Compare(CompositionLayer layerX, CompositionLayer layerY)
|
||||
{
|
||||
//Rule1: Higher Render Priority -> Front of the list
|
||||
//Rule2: Same Render Priority -> Do not move layer
|
||||
if (layerX.GetRenderPriority() > layerY.GetRenderPriority())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (layerX.GetRenderPriority() < layerY.GetRenderPriority())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user