initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,267 @@
#if UNITY_2020_2_OR_NEWER
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.XR;
using UnityEditor;
namespace MockHMD.Editor.MultiCamera
{
public class AddCameraWindow : EditorWindow
{
private List<MockCamera> camerasToRemove = new List<MockCamera>();
private AdditionalMockCameras additionalMockCameras = new AdditionalMockCameras();
private Vector2 camerasScrollPos;
private static NativeApi.MockCameraProperties cameraProperties = new NativeApi.MockCameraProperties{position = new NativeApi.float3(), rotation = new NativeApi.float4()};
private static List<XRDisplaySubsystem> s_displaySubsystems = new List<XRDisplaySubsystem>();
private int m_CameraIds = 0;
private bool isPlaying = false;
XRDisplaySubsystem GetXRDisplaySubsystem()
{
XRDisplaySubsystem ret = null;
SubsystemManager.GetInstances<XRDisplaySubsystem>(s_displaySubsystems);
if (s_displaySubsystems.Count > 0)
{
ret = s_displaySubsystems[0];
}
return ret;
}
[MenuItem ("Window/XR/Mock HMD/Additional Cameras")]
public static void ShowWindow ()
{
EditorWindow w = EditorWindow.GetWindow(typeof(AddCameraWindow));
w.titleContent = new GUIContent("Mock HMD Add Camera");
}
void OnEnable()
{
if (EditorPrefs.HasKey("MOCK Cameras"))
{
string data = EditorPrefs.GetString("MOCK Cameras");
JsonUtility.FromJsonOverwrite(data, additionalMockCameras);
foreach (var mockCam in additionalMockCameras.extraCameras)
{
mockCam.id = -1;
}
}
EditorApplication.playModeStateChanged += SetCamerasOnPlayStateChanged;
}
void OnDisable()
{
EditorApplication.playModeStateChanged -= SetCamerasOnPlayStateChanged;
string data = JsonUtility.ToJson(additionalMockCameras);
EditorPrefs.SetString("MOCK Cameras", data);
}
void SetCamerasOnPlayStateChanged(PlayModeStateChange state)
{
switch(state)
{
case PlayModeStateChange.EnteredEditMode:
break;
case PlayModeStateChange.ExitingEditMode:
break;
case PlayModeStateChange.EnteredPlayMode:
foreach (var mockCam in additionalMockCameras.extraCameras)
{
if (mockCam.isActive)
{
if (mockCam.id < 0)
{
mockCam.id = m_CameraIds;
m_CameraIds++;
}
if (!NativeApi.HasCameraWithId(mockCam.id))
AddCamera(mockCam.id);
}
}
isPlaying = true;
break;
case PlayModeStateChange.ExitingPlayMode:
isPlaying = false;
foreach (var mockCam in additionalMockCameras.extraCameras)
{
if (mockCam.isActive)
{
if (NativeApi.HasCameraWithId(mockCam.id))
RemoveCamera(mockCam.id);
mockCam.id = -1;
}
}
break;
}
}
void UpdateAllCameras()
{
if (isPlaying)
{
foreach (var mockCam in additionalMockCameras.extraCameras)
{
if (mockCam.isActive)
{
if (mockCam.id < 0)
{
mockCam.id = m_CameraIds;
m_CameraIds++;
}
if (!NativeApi.HasCameraWithId(mockCam.id))
AddCamera(mockCam.id);
UpdateCamera(mockCam.id, mockCam);
}
else
{
if (NativeApi.HasCameraWithId(mockCam.id))
RemoveCamera(mockCam.id);
}
}
}
}
void OnGUI()
{
var displaySubsystem = GetXRDisplaySubsystem();
EditorGUILayout.BeginVertical();
EditorGUILayout.Space();
if (GUILayout.Button("Add Camera"))
{
var newCam = new MockCamera();
newCam.id = -1;
additionalMockCameras.extraCameras.Add(newCam);
}
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space();
int camIndex = 0;
camerasScrollPos = EditorGUILayout.BeginScrollView(camerasScrollPos, GUILayout.Width(EditorGUIUtility.currentViewWidth));
foreach (var mockCam in additionalMockCameras.extraCameras)
{
EditorGUILayout.LabelField($"Mock Camera {camIndex}", EditorStyles.largeLabel);
EditorGUILayout.Space();
camIndex++;
mockCam.position = EditorGUILayout.Vector3Field("Position", mockCam.position);
mockCam.rotation.eulerAngles = EditorGUILayout.Vector3Field("Rotation", mockCam.rotation.eulerAngles);
mockCam.fov = EditorGUILayout.FloatField("Field of View", mockCam.fov);
mockCam.near = EditorGUILayout.FloatField("Near", mockCam.near);
mockCam.far = EditorGUILayout.FloatField("Far", mockCam.far);
mockCam.textureWidth = EditorGUILayout.IntField("Texture Width", mockCam.textureWidth);
mockCam.textureHeight = EditorGUILayout.IntField("Texture Height", mockCam.textureHeight);
mockCam.stereoRenderingMode = (MockRenderingMode)EditorGUILayout.EnumPopup("Rendering Mode", mockCam.stereoRenderingMode);
if (mockCam.stereoRenderingMode != MockRenderingMode.None)
{
mockCam.eyeSeparation = EditorGUILayout.FloatField("Eye Separation", mockCam.eyeSeparation);
mockCam.eyeSeparation = Math.Max(Math.Min(5.0f, mockCam.eyeSeparation), 0.01f);
}
mockCam.enableLeftOcclusion = EditorGUILayout.Toggle("Left Occlusion: ", mockCam.enableLeftOcclusion);
mockCam.leftAbberation = EditorGUILayout.Vector2Field("Left Abberation: ", mockCam.leftAbberation);
EditorGUILayout.Space();
mockCam.enableRightOcclusion = EditorGUILayout.Toggle("Right Occlusion: ", mockCam.enableRightOcclusion);
mockCam.rightAbberation = EditorGUILayout.Vector2Field("Right Abberation: ", mockCam.rightAbberation);
bool preIsActive = mockCam.isActive;
mockCam.isActive = EditorApplication.isPlayingOrWillChangePlaymode ? EditorGUILayout.Toggle("Active", mockCam.isActive) : false;
if (GUILayout.Button("Remove Camera"))
{
camerasToRemove.Add(mockCam);
mockCam.isActive = false;
}
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
UpdateAllCameras();
foreach (var mockCam in camerasToRemove)
{
additionalMockCameras.extraCameras.Remove(mockCam);
}
}
private void AddCamera(int id)
{
if (NativeApi.HasCameraWithId(id))
{
Debug.LogWarning($"Attmept to add a camera with id {id} when one already exists!");
return;
}
if (!NativeApi.AddCameraWithId(id))
{
Debug.LogError($"Attempt to add camera with id {id} failed!");
}
}
private void UpdateCamera(int id, MockCamera mockCam)
{
if (NativeApi.HasCameraWithId(id))
{
cameraProperties.position.x = mockCam.position.x;
cameraProperties.position.y = mockCam.position.y;
cameraProperties.position.z = mockCam.position.z;
cameraProperties.rotation.x = mockCam.rotation.x;
cameraProperties.rotation.y = mockCam.rotation.y;
cameraProperties.rotation.z = mockCam.rotation.z;
cameraProperties.rotation.w = mockCam.rotation.w;
cameraProperties.fov = mockCam.fov;
cameraProperties.near = mockCam.near;
cameraProperties.far = mockCam.far;
cameraProperties.textureWidth = mockCam.textureWidth;
cameraProperties.textureHeight = mockCam.textureHeight;
cameraProperties.renderingMode = (int)mockCam.stereoRenderingMode;
cameraProperties.eyeSeparation = mockCam.eyeSeparation;
cameraProperties.leftAbberation.x = mockCam.leftAbberation.x;
cameraProperties.leftAbberation.y = mockCam.leftAbberation.y;
cameraProperties.leftAbberation.z = 0;
cameraProperties.rightAbberation.x = mockCam.rightAbberation.x;
cameraProperties.rightAbberation.y = mockCam.rightAbberation.y;
cameraProperties.rightAbberation.z = 0;
cameraProperties.enableLeftOcclusion = mockCam.enableLeftOcclusion ? 1 : 0;
cameraProperties.enableRightOcclusion = mockCam.enableRightOcclusion ? 1 : 0;
NativeApi.UpdateCameraWithId(id, cameraProperties);
}
}
private void RemoveCamera(int id)
{
if (!NativeApi.RemoveCameraWithId(id))
{
Debug.LogWarning($"Could not remove camera with id {id}");
}
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9ac39955019e92f40ab924eeaaaaaf95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,62 @@
#if UNITY_2020_2_OR_NEWER
using System;
using System.Collections.Generic;
using UnityEngine;
namespace MockHMD.Editor.MultiCamera
{
public enum MockRenderingMode
{
None,
MultiPass,
SinglePassInstance,
}
[System.Serializable]
public class MockCamera
{
[SerializeField]
public int id;
[SerializeField]
public Vector3 position;
[SerializeField]
public Quaternion rotation;
[SerializeField]
public float fov = 60.0f;
[SerializeField]
public float near = 0.3f;
[SerializeField]
public float far = 1000.0f;
[SerializeField]
public int textureWidth = 100;
[SerializeField]
public int textureHeight = 100;
[SerializeField]
public MockRenderingMode stereoRenderingMode = MockRenderingMode.None;
[SerializeField]
public float eyeSeparation = 0.2f;
[SerializeField]
public Vector2 leftAbberation;
[SerializeField]
public Vector2 rightAbberation;
[SerializeField]
public bool enableLeftOcclusion;
[SerializeField]
public bool enableRightOcclusion;
[SerializeField]
public bool isActive;
}
[System.Serializable]
public class AdditionalMockCameras
{
[SerializeField]
public List<MockCamera> extraCameras = new List<MockCamera>();
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 349542c7fcef6d549b7e101555458365
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,61 @@
#if UNITY_2020_2_OR_NEWER
using System;
using System.Runtime.InteropServices;
using UnityEngine;
namespace MockHMD.Editor.MultiCamera
{
public static class NativeApi
{
[StructLayout(LayoutKind.Sequential)]
public struct float3
{
public float x;
public float y;
public float z;
}
[StructLayout(LayoutKind.Sequential)]
public struct float4
{
public float x;
public float y;
public float z;
public float w;
}
[StructLayout(LayoutKind.Sequential)]
public struct MockCameraProperties
{
public float3 position;
public float4 rotation;
public float fov;
public float near;
public float far;
public int textureWidth;
public int textureHeight;
public int renderingMode;
public float eyeSeparation;
public float3 leftAbberation;
public float3 rightAbberation;
public int enableLeftOcclusion;
public int enableRightOcclusion;
}
[DllImport("Packages/com.unity.xr.mock-hmd/Runtime/Windows/x64/UnityMockHMD.dll", CharSet = CharSet.Auto)]
public static extern bool HasCameraWithId(int id);
[DllImport("Packages/com.unity.xr.mock-hmd/Runtime/Windows/x64/UnityMockHMD.dll", CharSet = CharSet.Auto)]
public static extern bool AddCameraWithId(int id);
[DllImport("Packages/com.unity.xr.mock-hmd/Runtime/Windows/x64/UnityMockHMD.dll", CharSet = CharSet.Auto)]
public static extern bool UpdateCameraWithId(int id, MockCameraProperties properties);
[DllImport("Packages/com.unity.xr.mock-hmd/Runtime/Windows/x64/UnityMockHMD.dll", CharSet = CharSet.Auto)]
public static extern bool RemoveCameraWithId(int id);
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f34674229f0c6964fa4b72d99761a76d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,175 @@
#if UNITY_2020_2_OR_NEWER
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.XR;
using UnityEditor;
namespace MockHMD.Editor.MultiCamera
{
public class RenderPassTextureWindow : EditorWindow
{
Vector2 renderTextureScrollPos;
int textureImageHeight = 200;
int textureImageWidth = 200;
int textureImageSpace = 20;
int textureImageLeftPadding = 25;
private static List<XRDisplaySubsystem> s_displaySubsystems = new List<XRDisplaySubsystem>();
XRDisplaySubsystem.XRRenderPass s_renderPass = new XRDisplaySubsystem.XRRenderPass();
XRDisplaySubsystem.XRRenderParameter s_renderParameter= new XRDisplaySubsystem.XRRenderParameter();
[MenuItem ("Window/XR/Mock HMD/Render Texture Viewer")]
public static void ShowWindow ()
{
EditorWindow w = EditorWindow.GetWindow(typeof(RenderPassTextureWindow));
w.titleContent = new GUIContent("Render Texture Viewer");
}
XRDisplaySubsystem GetXRDisplaySubsystem()
{
XRDisplaySubsystem ret = null;
SubsystemManager.GetInstances<XRDisplaySubsystem>(s_displaySubsystems);
if (s_displaySubsystems.Count > 0)
{
ret = s_displaySubsystems[0];
}
return ret;
}
private void Update()
{
if (EditorApplication.isPlaying)
{
Repaint();
}
}
void DisplayRenderTextures(XRDisplaySubsystem displaySubsystem)
{
RenderTexture rt = displaySubsystem.GetRenderTextureForRenderPass(s_renderPass.renderPassIndex);
if (rt == null)
return;
int rpc = s_renderPass.GetRenderParameterCount();
RenderTexture target = new RenderTexture(rt.width, rt.height, rt.depth);
Graphics.CopyTexture(rt, 0, target, 0);
EditorGUILayout.BeginHorizontal();
Rect r = EditorGUILayout.GetControlRect(false, textureImageHeight,
GUILayout.MaxWidth(textureImageWidth + textureImageLeftPadding),
GUILayout.Width(textureImageWidth),
GUILayout.MaxHeight(textureImageHeight + textureImageSpace));
EditorGUI.DrawPreviewTexture(r, target);
if (rpc > 1)
{
Graphics.CopyTexture(rt, 1, target, 0);
r = EditorGUILayout.GetControlRect(false, textureImageHeight,
GUILayout.MaxWidth(textureImageWidth + textureImageLeftPadding),
GUILayout.Width(textureImageWidth),
GUILayout.MaxHeight(textureImageHeight + textureImageSpace));
EditorGUI.DrawPreviewTexture(r, target);
}
target.DiscardContents();
target.Release();
EditorGUILayout.EndHorizontal();
}
void DisplayRenderPassData()
{
EditorGUILayout.BeginHorizontal();
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.Space();
EditorGUILayout.LabelField($"Render Pass : {s_renderPass.renderPassIndex}");
EditorGUILayout.LabelField($"Should Fill Depth : {s_renderPass.shouldFillOutDepth}");
EditorGUILayout.LabelField($"Cull Index: {s_renderPass.cullingPassIndex}");
}
int rpc = s_renderPass.GetRenderParameterCount();
for (int rpmi = 0; rpmi < rpc; rpmi++)
{
try
{
s_renderPass.GetRenderParameter(UnityEngine.Camera.main, rpmi, out s_renderParameter);
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.Space();
EditorGUILayout.LabelField($"Render Parameter: {rpmi}");
var planes = s_renderParameter.projection.decomposeProjection;
using (new EditorGUI.DisabledScope(true))
{
EditorGUILayout.RectField("Projection Planes", new Rect(planes.left, planes.top, planes.right, planes.bottom));
}
}
}
catch (Exception)
{
}
}
EditorGUILayout.EndHorizontal();
}
void OnGUI()
{
EditorGUILayout.BeginVertical();
if (EditorApplication.isPlaying || EditorApplication.isPaused)
{
var displaySubsystem = GetXRDisplaySubsystem();
if (displaySubsystem == null)
return;
#if !UNITY_2020_2_OR_NEWER
if (displaySubsystem.disableLegacyRenderer)
return;
#endif
int renderPassCount = displaySubsystem.GetRenderPassCount();
EditorGUILayout.LabelField("Render Pass Textures:");
renderTextureScrollPos = EditorGUILayout.BeginScrollView(renderTextureScrollPos, GUILayout.Width(EditorGUIUtility.currentViewWidth));
for (int rpi = 0; rpi < renderPassCount; rpi++)
{
displaySubsystem.GetRenderPass(rpi, out s_renderPass);
EditorGUILayout.Space();
DisplayRenderPassData();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space();
DisplayRenderTextures(displaySubsystem);
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
}
EditorGUILayout.EndScrollView();
}
else
{
EditorGUILayout.LabelField("Must be running in Play mode to see render textures.");
}
EditorGUILayout.EndVertical();
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08619e971c0c7d54cb6e8918730ef68e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: