120 lines
3.9 KiB
C#
120 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
|
|
namespace VRC.SDK3.ClientSim
|
|
{
|
|
public class ClientSimStackedVRCameraSystem : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private ClientSimStackedCamera[] cameraStack;
|
|
|
|
private bool _isCameraStackingEnabled;
|
|
private Camera _mainSceneCamera;
|
|
private bool _isInitialized;
|
|
private bool _isReady;
|
|
private List<Camera> _cameras;
|
|
private ClientSimMenu _clientSimMenu;
|
|
private IClientSimEventDispatcher _eventDispatcher;
|
|
|
|
public IReadOnlyList<Camera> Cameras => _cameras;
|
|
|
|
// all layers handled by this system - note that this does not change whether the system is active or not,
|
|
// meaning it is valid to call this at any time, which `OnCameraSettingsChanged` may need to do
|
|
public LayerMask RequestedStackLayers => cameraStack.Aggregate(0, (mask, cam) => mask | cam.RenderLayer);
|
|
|
|
public void Initialize(Camera playerCamera, ClientSimMenu menu, IClientSimEventDispatcher eventDispatcher)
|
|
{
|
|
_mainSceneCamera = playerCamera;
|
|
_clientSimMenu = menu;
|
|
_eventDispatcher = eventDispatcher;
|
|
}
|
|
|
|
public void Ready()
|
|
{
|
|
_isReady = true;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if(!_isReady) return;
|
|
if (!_isInitialized) { InitializeStackedSystem(); }
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
if (_mainSceneCamera != null)
|
|
{
|
|
if (_isCameraStackingEnabled)
|
|
DestroyCameraStack();
|
|
}
|
|
}
|
|
|
|
private void InitializeStackedSystem()
|
|
{
|
|
_cameras = new List<Camera>();
|
|
if (_mainSceneCamera != null)
|
|
{
|
|
CreateCameraStack();
|
|
_isInitialized = true;
|
|
_eventDispatcher.SendEvent(new ClientSimStackedCameraReadyEvent());
|
|
}
|
|
}
|
|
|
|
private void CreateCameraStack()
|
|
{
|
|
for (int i = 0; i < cameraStack.Length; i++)
|
|
{
|
|
AddCamera(i);
|
|
}
|
|
_isCameraStackingEnabled = true;
|
|
}
|
|
|
|
private void DestroyCameraStack()
|
|
{
|
|
for (int i = 0; i < _cameras.Count; i++)
|
|
{
|
|
DestroyCamera(i);
|
|
}
|
|
_isCameraStackingEnabled = false;
|
|
}
|
|
|
|
private void AddCamera(int index)
|
|
{
|
|
var cameraObj = new GameObject();
|
|
cameraObj.transform.parent = _mainSceneCamera.transform;
|
|
Camera cam = cameraObj.AddComponent<Camera>();
|
|
XRDevice.DisableAutoXRCameraTracking(cam, true);
|
|
|
|
cam.CopyFrom(_mainSceneCamera); // Start by copying all the settings from the main camera
|
|
#if VRC_VR_STEAM // We only want this on SteamVR.
|
|
cameraObj.AddComponent<SteamVRCantedProjectionCullingFix>();
|
|
#endif
|
|
_cameras.Add(cam);
|
|
|
|
cameraObj.tag = "Untagged";
|
|
cameraObj.name = $"StackedCamera : {cameraStack[index].CameraName}";
|
|
cam.clearFlags = CameraClearFlags.Depth;
|
|
cam.depth = 100 - index;
|
|
cam.cullingMask = cameraStack[index].RenderLayer;
|
|
cam.useOcclusionCulling = cameraStack[index].UseOcclusionCulling;
|
|
|
|
//Remove this cameras layers from the base camera
|
|
_mainSceneCamera.cullingMask = _mainSceneCamera.cullingMask ^ cameraStack[index].RenderLayer;
|
|
|
|
// Set the ClientSim UI canvas to use this camera
|
|
_clientSimMenu.SetCanvasCamera(cam);
|
|
}
|
|
|
|
private void DestroyCamera(int index)
|
|
{
|
|
Camera cam = _cameras[index];
|
|
_cameras.RemoveAt(index);
|
|
|
|
//Restore Layers from this camera to the main camera
|
|
_mainSceneCamera.cullingMask = _mainSceneCamera.cullingMask | cameraStack[index].RenderLayer;
|
|
Destroy(cam.gameObject);
|
|
}
|
|
}
|
|
} |