This commit is contained in:
2025-11-13 17:40:28 +08:00
parent 962ab49609
commit 10156da245
5503 changed files with 805282 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d1f88856b31e5b048b260670c0dd2ab2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 687edb8814fe64d438f49fadb4fe7849
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Android:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 6948a18f1c6415b42a41bb1ffd98095c
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Android:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 50f8077c12618da40a431db72f014562
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.Interaction.Toolkit;
public class PXRSample_SpatialAnchor : MonoBehaviour
{
[HideInInspector]
public ulong anchorHandle;
[SerializeField]
private Text anchorID;
[SerializeField]
private GameObject savedIcon;
[SerializeField]
private GameObject uiCanvas;
[SerializeField] private Button btnPersist;
[SerializeField] private Button btnDestroyAnchor;
[SerializeField] private Button btnDeleteAnchor;
private void Awake()
{
//uiCanvas.SetActive(false);
uiCanvas.SetActive(true);
uiCanvas.GetComponent<Canvas>().worldCamera = Camera.main;
btnPersist.onClick.AddListener(OnBtnPressedPersist);
btnDestroyAnchor.onClick.AddListener(OnBtnPressedDestroy);
btnDeleteAnchor.onClick.AddListener(OnBtnPressedUnPersist);
}
protected void OnEnable()
{
}
protected void OnDisable()
{
}
private void Start()
{
}
private void Update()
{
if (uiCanvas.activeSelf)
{
uiCanvas.transform.LookAt(new Vector3(uiCanvas.transform.position.x * 2 - Camera.main.transform.position.x, uiCanvas.transform.position.y * 2 - Camera.main.transform.position.y, uiCanvas.transform.position.z * 2 - Camera.main.transform.position.z), Vector3.up);
}
}
private void LateUpdate()
{
var result = PXR_MixedReality.LocateAnchor(anchorHandle, out var position, out var rotation);
if (result == PxrResult.SUCCESS)
{
transform.position = position;
transform.rotation = rotation;
}
else
{
PXRSample_SpatialAnchorManager.Instance.SetLogInfo("LocateSpatialAnchor:" + result.ToString());
}
}
private async void OnBtnPressedPersist()
{
var result = await PXR_MixedReality.PersistSpatialAnchorAsync(anchorHandle);
PXRSample_SpatialAnchorManager.Instance.SetLogInfo("PersistSpatialAnchorAsync:" + result.ToString());
if (result == PxrResult.SUCCESS)
{
ShowSaveIcon();
}
}
private void OnBtnPressedDestroy()
{
PXRSample_SpatialAnchorManager.Instance.DestroySpatialAnchor(anchorHandle);
}
private async void OnBtnPressedUnPersist()
{
var result = await PXR_MixedReality.UnPersistSpatialAnchorAsync(anchorHandle);
PXRSample_SpatialAnchorManager.Instance.SetLogInfo("UnPersistSpatialAnchorAsync:" + result.ToString());
if (result == PxrResult.SUCCESS)
{
OnBtnPressedDestroy();
}
}
public void SetAnchorHandle(ulong handle)
{
anchorHandle = handle;
anchorID.text = "ID: " + anchorHandle;
}
public void ShowSaveIcon()
{
savedIcon.SetActive(true);
}
}

View File

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

View File

@@ -0,0 +1,198 @@
using System.Collections.Generic;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;
public class PXRSample_SpatialAnchorManager : MonoBehaviour
{
private static PXRSample_SpatialAnchorManager instance = null;
public static PXRSample_SpatialAnchorManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<PXRSample_SpatialAnchorManager>();
}
return instance;
}
}
public GameObject anchorPrefab;
private bool isCreateAnchorMode = false;
public Dictionary<ulong, PXRSample_SpatialAnchor> anchorList = new Dictionary<ulong, PXRSample_SpatialAnchor>();
public Dictionary<ulong, ulong> persistTaskList = new Dictionary<ulong, ulong>();
public Dictionary<ulong, ulong> unPersistTaskList = new Dictionary<ulong, ulong>();
private InputDevice rightController;
public GameObject anchorPreview;
[SerializeField] private GameObject menuPanel;
[SerializeField] private Button btnCreateAnchor;
[SerializeField] private Button btnLoadAnchors;
private bool btnAClick = false;
private bool aLock = false;
private bool btnAState = false;
private bool gripButton = false;
public Text tipsText;
private int maxLogCount = 5;
private Queue<string> logQueue = new Queue<string>();
void Start()
{
PXR_Manager.EnableVideoSeeThrough = true;
StartSpatialAnchorProvider();
btnCreateAnchor.onClick.AddListener(OnBtnPressedCreateAnchor);
btnLoadAnchors.onClick.AddListener(OnBtnPressedLoadAllAnchors);
btnCreateAnchor.gameObject.SetActive(true);
btnLoadAnchors.gameObject.SetActive(true);
rightController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
}
private async void StartSpatialAnchorProvider()
{
var result = await PXR_MixedReality.StartSenseDataProvider(PxrSenseDataProviderType.SpatialAnchor);
SetLogInfo("StartSenseDataProvider:" + result);
}
void OnEnable()
{
PXR_Manager.SpatialAnchorDataUpdated += SpatialAnchorDataUpdated;
}
void OnDisable()
{
PXR_Manager.SpatialAnchorDataUpdated -= SpatialAnchorDataUpdated;
}
// Update is called once per frame
void Update()
{
ProcessKeyEvent();
menuPanel.SetActive(gripButton);
if (isCreateAnchorMode && btnAClick)
{
CreateSpatialAnchor(anchorPreview.transform);
}
}
private void ProcessKeyEvent()
{
rightController.TryGetFeatureValue(CommonUsages.primaryButton, out btnAState);
if (btnAState && !aLock)
{
btnAClick = true;
aLock = true;
}
else
{
btnAClick = false;
}
if (!btnAState)
{
btnAClick = false;
aLock = false;
}
InputDevices.GetDeviceAtXRNode(XRNode.LeftHand).TryGetFeatureValue(CommonUsages.gripButton, out gripButton);
}
private void SpatialAnchorDataUpdated()
{
SetLogInfo("SpatialAnchorDataUpdated:");
OnBtnPressedLoadAllAnchors();
}
private void OnBtnPressedCreateAnchor()
{
isCreateAnchorMode = !isCreateAnchorMode;
if (isCreateAnchorMode)
{
btnCreateAnchor.transform.Find("Text").GetComponent<Text>().text = "CancelCreate";
anchorPreview.SetActive(true);
}
else
{
btnCreateAnchor.transform.Find("Text").GetComponent<Text>().text = "CreateAnchor";
anchorPreview.SetActive(false);
}
}
private async void OnBtnPressedLoadAllAnchors()
{
var result = await PXR_MixedReality.QuerySpatialAnchorAsync();
SetLogInfo("LoadSpatialAnchorAsync:" + result.result.ToString());
if (result.result == PxrResult.SUCCESS)
{
foreach (var key in result.anchorHandleList)
{
if (!anchorList.ContainsKey(key))
{
GameObject anchorObject = Instantiate(anchorPrefab);
PXRSample_SpatialAnchor anchor = anchorObject.GetComponent<PXRSample_SpatialAnchor>();
anchor.SetAnchorHandle(key);
PXR_MixedReality.LocateAnchor(key, out var position, out var orientation);
anchor.transform.position = position;
anchor.transform.rotation = orientation;
anchorList.Add(key, anchor);
anchorList[key].ShowSaveIcon();
}
}
}
}
private async void CreateSpatialAnchor(Transform transform)
{
var result = await PXR_MixedReality.CreateSpatialAnchorAsync(transform.position, transform.rotation);
SetLogInfo("CreateSpatialAnchorAsync:" + result.ToString());
if (result.result == PxrResult.SUCCESS)
{
GameObject anchorObject = Instantiate(anchorPrefab);
PXRSample_SpatialAnchor anchor = anchorObject.GetComponent<PXRSample_SpatialAnchor>();
if (anchor == null)
{
anchor = anchorObject.AddComponent<PXRSample_SpatialAnchor>();
}
anchor.SetAnchorHandle(result.anchorHandle);
anchorList.Add(result.anchorHandle, anchor);
var result1 = PXR_MixedReality.GetAnchorUuid(result.anchorHandle, out var uuid);
SetLogInfo("GetUuid:" + result1.ToString() + " " + (result.uuid.Equals(uuid)) + "Uuid:" + uuid);
}
}
public void DestroySpatialAnchor(ulong anchorHandle)
{
var result = PXR_MixedReality.DestroyAnchor(anchorHandle);
SetLogInfo("DestroySpatialAnchor:" + result.ToString());
if (result == PxrResult.SUCCESS)
{
if (anchorList.ContainsKey(anchorHandle))
{
Destroy(anchorList[anchorHandle].gameObject);
anchorList.Remove(anchorHandle);
}
}
}
public void SetLogInfo(string log)
{
if (logQueue.Count >= maxLogCount)
{
logQueue.Dequeue();
}
logQueue.Enqueue(log);
tipsText.text = string.Join("\n", logQueue.ToArray());
}
}

View File

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

View File

@@ -0,0 +1,185 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.XR.PXR;
using UnityEngine.UI;
using System;
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
public class PXR_BodyTrackingBlock : MonoBehaviour
{
public Transform skeletonJoints;
public bool showCube = true;
public float zDistance = 0;
private bool supportedBT = false;
private bool updateBT = true;
private BodyTrackingGetDataInfo bdi = new BodyTrackingGetDataInfo();
private BodyTrackingData bd = new BodyTrackingData();
private Transform[] boneMapping = new Transform[(int)BodyTrackerRole.ROLE_NUM];
BodyTrackingStatus bs = new BodyTrackingStatus();
bool istracking = false;
// Start is called before the first frame update
void Start()
{
skeletonJoints.transform.localPosition += new Vector3(0, 0, zDistance);
InitializeSkeletonJoints();
StartBodyTracking();
}
// Update is called once per frame
void Update()
{
#if UNITY_ANDROID
// Update bodytracking pose.
if (updateBT)
{
#if PICO_OPENXR_SDK
BodyTrackingFeature.GetBodyTrackingState(ref istracking, ref bs);
#else
PXR_MotionTracking.GetBodyTrackingState(ref istracking, ref bs);
#endif
// If not calibrated, invoked system motion tracker app for calibration.
if (bs.stateCode != BodyTrackingStatusCode.BT_VALID)
{
return;
}
// Get the position and orientation data of each body node.
int ret = -1;
#if PICO_OPENXR_SDK
ret = BodyTrackingFeature.GetBodyTrackingData(ref bdi, ref bd);
#else
ret = PXR_MotionTracking.GetBodyTrackingData(ref bdi, ref bd);
#endif
// if the return is successful
if (ret == 0)
{
for (int i = 0; i < (int)BodyTrackerRole.ROLE_NUM; i++)
{
var bone = boneMapping[i];
if (bone != null)
{
bone.transform.localPosition = new Vector3((float)bd.roleDatas[i].localPose.PosX, (float)bd.roleDatas[i].localPose.PosY,
(float)bd.roleDatas[i].localPose.PosZ);
bone.transform.localRotation = new Quaternion((float)bd.roleDatas[i].localPose.RotQx, (float)bd.roleDatas[i].localPose.RotQy,
(float)bd.roleDatas[i].localPose.RotQz, (float)bd.roleDatas[i].localPose.RotQw);
}
}
}
}
#endif
}
public void StartBodyTracking()
{
// Query whether the current device supports human body tracking.
#if PICO_OPENXR_SDK
supportedBT = BodyTrackingFeature.IsBodyTrackingSupported();
#else
PXR_MotionTracking.GetBodyTrackingSupported(ref supportedBT);
#endif
if (!supportedBT)
{
return;
}
BodyTrackingBoneLength bones = new BodyTrackingBoneLength();
// Start BodyTracking
#if PICO_OPENXR_SDK
BodyTrackingFeature.StartBodyTracking(BodyJointSet.BODY_JOINT_SET_BODY_FULL_START, bones);
BodyTrackingFeature.GetBodyTrackingState(ref istracking, ref bs);
#else
PXR_MotionTracking.StartBodyTracking(BodyJointSet.BODY_JOINT_SET_BODY_FULL_START, bones);
PXR_MotionTracking.GetBodyTrackingState(ref istracking, ref bs);
#endif
// If not calibrated, invoked system motion tracker app for calibration.
if (bs.stateCode != BodyTrackingStatusCode.BT_VALID)
{
if (bs.message == BodyTrackingMessage.BT_MESSAGE_TRACKER_NOT_CALIBRATED || bs.message == BodyTrackingMessage.BT_MESSAGE_UNKNOWN)
{
#if PICO_OPENXR_SDK
BodyTrackingFeature.StartMotionTrackerCalibApp();
#else
PXR_MotionTracking.StartMotionTrackerCalibApp();
#endif
}
}
skeletonJoints.gameObject.SetActive(true);
updateBT = true;
}
private void OnDestroy()
{
#if PICO_OPENXR_SDK
int ret = BodyTrackingFeature.StopBodyTracking();
#else
int ret = PXR_MotionTracking.StopBodyTracking();
#endif
updateBT = false;
}
public void InitializeSkeletonJoints()
{
Queue<Transform> nodes = new Queue<Transform>();
nodes.Enqueue(skeletonJoints);
while (nodes.Count > 0)
{
Transform next = nodes.Dequeue();
for (int i = 0; i < next.childCount; ++i)
{
nodes.Enqueue(next.GetChild(i));
}
ProcessJoint(next);
}
}
void ProcessJoint(Transform joint)
{
int index = GetJointIndex(joint.name);
if (index >= 0 && index < (int)BodyTrackerRole.ROLE_NUM)
{
boneMapping[index] = joint;
Transform cubeT = joint.Find("Cube");
if (cubeT)
{
cubeT.gameObject.SetActive(showCube);
}
}
else
{
Debug.LogWarning($"{joint.name} was not found.");
}
}
// Returns the integer value corresponding to the JointIndices enum value
// passed in as a string.
int GetJointIndex(string jointName)
{
BodyTrackerRole val;
if (Enum.TryParse(jointName, out val))
{
return (int)val;
}
return -1;
}
}

View File

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

View File

@@ -0,0 +1,257 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.XR.PXR;
using UnityEngine.UI;
using System;
using static UnityEngine.UI.Dropdown;
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
public class PXR_BodyTrackingDebugBlock : MonoBehaviour
{
public Transform skeletonJoints;
public bool showCube = true;
public float zDistance = 0;
public Dropdown dropdown;
public Text changeJointTittle;
private bool supportedBT = false;
private bool updateBT = true;
private Transform changeJointT;
private BodyTrackingGetDataInfo bdi = new BodyTrackingGetDataInfo();
private BodyTrackingData bd = new BodyTrackingData();
private Transform[] boneMapping = new Transform[(int)BodyTrackerRole.ROLE_NUM];
private Transform[] targetMapping = new Transform[(int)BodyTrackerRole.ROLE_NUM];
BodyTrackingStatus bs = new BodyTrackingStatus();
bool istracking = false;
// Start is called before the first frame update
void Start()
{
dropdown.ClearOptions();
skeletonJoints.transform.localPosition += new Vector3(0, 0, zDistance);
InitializeSkeletonJoints();
StartBodyTracking();
dropdown.RefreshShownValue();
dropdown.onValueChanged.AddListener(delegate
{
DropdownValueChanged(dropdown);
});
}
// Update is called once per frame
void Update()
{
#if UNITY_ANDROID
// Update bodytracking pose.
if (updateBT)
{
#if PICO_OPENXR_SDK
BodyTrackingFeature.GetBodyTrackingState(ref istracking, ref bs);
#else
PXR_MotionTracking.GetBodyTrackingState(ref istracking, ref bs);
#endif
// If not calibrated, invoked system motion tracker app for calibration.
if (bs.stateCode!=BodyTrackingStatusCode.BT_VALID)
{
return;
}
// Get the position and orientation data of each body node.
int ret = -1;
#if PICO_OPENXR_SDK
ret = BodyTrackingFeature.GetBodyTrackingData(ref bdi, ref bd);
#else
ret = PXR_MotionTracking.GetBodyTrackingData(ref bdi, ref bd);
#endif
// if the return is successful
if (ret == 0)
{
for (int i = 0; i < (int)BodyTrackerRole.ROLE_NUM; i++)
{
var bone = boneMapping[i];
if (bone != null)
{
bone.transform.localPosition = new Vector3((float)bd.roleDatas[i].localPose.PosX, (float)bd.roleDatas[i].localPose.PosY, (float)bd.roleDatas[i].localPose.PosZ);
bone.transform.localRotation = new Quaternion((float)bd.roleDatas[i].localPose.RotQx, (float)bd.roleDatas[i].localPose.RotQy, (float)bd.roleDatas[i].localPose.RotQz, (float)bd.roleDatas[i].localPose.RotQw);
}
}
}
}
#endif
}
public void StartBodyTracking()
{
// Query whether the current device supports human body tracking.
#if PICO_OPENXR_SDK
supportedBT= BodyTrackingFeature.IsBodyTrackingSupported();
#else
PXR_MotionTracking.GetBodyTrackingSupported(ref supportedBT);
#endif
if (!supportedBT)
{
return;
}
BodyTrackingBoneLength bones = new BodyTrackingBoneLength();
// Start BodyTracking
#if PICO_OPENXR_SDK
BodyTrackingFeature.StartBodyTracking(BodyJointSet.BODY_JOINT_SET_BODY_FULL_START, bones);
BodyTrackingFeature.GetBodyTrackingState(ref istracking, ref bs);
#else
PXR_MotionTracking.StartBodyTracking(BodyJointSet.BODY_JOINT_SET_BODY_FULL_START, bones);
PXR_MotionTracking.GetBodyTrackingState(ref istracking, ref bs);
#endif
// If not calibrated, invoked system motion tracker app for calibration.
if (bs.stateCode!=BodyTrackingStatusCode.BT_VALID)
{
if (bs.message==BodyTrackingMessage.BT_MESSAGE_TRACKER_NOT_CALIBRATED||bs.message==BodyTrackingMessage.BT_MESSAGE_UNKNOWN)
{
#if PICO_OPENXR_SDK
BodyTrackingFeature.StartMotionTrackerCalibApp();
#else
PXR_MotionTracking.StartMotionTrackerCalibApp();
#endif
}
}
skeletonJoints.gameObject.SetActive(true);
updateBT = true;
}
private void OnDestroy()
{
#if PICO_OPENXR_SDK
int ret = BodyTrackingFeature.StopBodyTracking();
#else
int ret = PXR_MotionTracking.StopBodyTracking();
#endif
updateBT = false;
}
public void InitializeSkeletonJoints()
{
Queue<Transform> nodes = new Queue<Transform>();
nodes.Enqueue(skeletonJoints);
while (nodes.Count > 0)
{
Transform next = nodes.Dequeue();
for (int i = 0; i < next.childCount; ++i)
{
nodes.Enqueue(next.GetChild(i));
}
ProcessJoint(next);
}
}
void ProcessJoint(Transform joint)
{
int index = GetJointIndex(joint.name);
if (index >= 0 && index < (int)BodyTrackerRole.ROLE_NUM)
{
boneMapping[index] = joint;
Transform cubeT = joint.Find("Cube");
if (cubeT)
{
cubeT.gameObject.SetActive(showCube);
}
OptionData optionData = new OptionData();
optionData.text = joint.name;
dropdown.options.Add(optionData);
if (index == 0)
{
changeJointT = cubeT;
var cubeRenderer = changeJointT.GetComponent<Renderer>();
cubeRenderer.material.SetColor("_Color", Color.green);
if (changeJointTittle)
{
changeJointTittle.text = "Joint Rotation : " + joint.name;
}
}
}
else
{
Debug.LogWarning($"{joint.name} was not found.");
}
}
// Returns the integer value corresponding to the JointIndices enum value
// passed in as a string.
int GetJointIndex(string jointName)
{
BodyTrackerRole val;
if (Enum.TryParse(jointName, out val))
{
return (int)val;
}
return -1;
}
void DropdownValueChanged(Dropdown change)
{
if (changeJointTittle)
{
changeJointTittle.text = "Joint Rotation : " + change.options[change.value].text;
}
foreach (var b in boneMapping)
{
changeJointT = b.Find("Cube");
var cubeRenderer = changeJointT.GetComponent<Renderer>();
cubeRenderer.material.SetColor("_Color", Color.white);
}
var bone = boneMapping[change.value];
if (bone)
{
changeJointT = bone.Find("Cube");
var cubeRenderer = changeJointT.GetComponent<Renderer>();
cubeRenderer.material.SetColor("_Color", Color.green);
}
}
public void SetRotationX(float x)
{
if (changeJointT)
{
changeJointT.localRotation = Quaternion.AngleAxis(x, Vector3.right);
}
}
public void SetRotationY(float y)
{
if (changeJointT)
{
changeJointT.localRotation = Quaternion.AngleAxis(y, Vector3.up);
}
}
public void SetRotationZ(float z)
{
if (changeJointT)
{
changeJointT.localRotation = Quaternion.AngleAxis(z, Vector3.forward);
}
}
}

View File

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

View File

@@ -0,0 +1,196 @@
using System.Collections;
using System.Collections.Generic;
using Unity.XR.PXR;
using UnityEngine;
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
public class PXR_CameraEffectBlock : MonoBehaviour
{
public Texture2D lutTex;
private int row = 0;
private int col = 0;
private float brightness = 0;
private float contrast = 0;
private float saturation = 0;
private PassthroughStyle passthroughStyle = new()
{
enableColorMap = true,
enableEdgeColor = true,
TextureOpacityFactor = 1.0f
};
private float r = 0;
private float g = 0;
private float b = 0;
private float a = 0;
private Color[] values;
// Start is called before the first frame update
void Start()
{
#if PICO_OPENXR_SDK
PassthroughFeature.EnableVideoSeeThrough = true;
values = new Color[PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
#else
PXR_Manager.EnableVideoSeeThrough = true;
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
#endif
}
// Update is called once per frame
void Update()
{
}
public void SetColortemp(float x)
{
#if PICO_OPENXR_SDK
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
PXR_MixedReality.SetVideoSeeThroughEffect(PxrLayerEffect.Colortemp, x, 0);
#endif
}
public void SetBrightness(float x)
{
#if PICO_OPENXR_SDK
brightness = x;
PassthroughFeature.SetBrightnessContrastSaturation(ref passthroughStyle, brightness, contrast, saturation);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
PXR_MixedReality.SetVideoSeeThroughEffect(PxrLayerEffect.Brightness, x, 0);
#endif
}
public void SetSaturation(float x)
{
#if PICO_OPENXR_SDK
saturation = x;
PassthroughFeature.SetBrightnessContrastSaturation(ref passthroughStyle, brightness, contrast, saturation);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
PXR_MixedReality.SetVideoSeeThroughEffect(PxrLayerEffect.Saturation, x, 0);
#endif
}
public void SetContrast(float x)
{
#if PICO_OPENXR_SDK
contrast = x;
PassthroughFeature.SetBrightnessContrastSaturation(ref passthroughStyle, brightness, contrast, saturation);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
PXR_MixedReality.SetVideoSeeThroughEffect(PxrLayerEffect.Contrast, x, 0);
#endif
}
public void SetLut()
{
if (lutTex)
{
#if PICO_OPENXR_SDK
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(true);
PXR_MixedReality.SetVideoSeeThroughLut(lutTex, 8, 8);
#endif
}
}
public void ClearAll()
{
#if PICO_OPENXR_SDK
passthroughStyle = new()
{
enableColorMap = true,
enableEdgeColor = true,
TextureOpacityFactor = 1.0f
};
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
#else
PXR_MixedReality.EnableVideoSeeThroughEffect(false);
#endif
}
#if PICO_OPENXR_SDK
public void MonoToMono()
{
var monOvalues = new int[PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
for (int i = 0; i < PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; ++i)
{
monOvalues[i] = i;
}
PassthroughFeature.SetColorMapbyMonoToMono(ref passthroughStyle, monOvalues);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
}
public void SetEdgeColorToR(float x)
{
r = x;
SetEdgeColorRGBA();
}
public void SetEdgeColorToG(float x)
{
g = x;
SetEdgeColorRGBA();
}
public void SetEdgeColorToB(float x)
{
b = x;
SetEdgeColorRGBA();
}
public void SetEdgeColorToA(float x)
{
a = x;
SetEdgeColorRGBA();
}
public void SetEdgeColorRGBA()
{
passthroughStyle.EdgeColor = new Color(r, g, b, a);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
}
public void SetColorMapR()
{
var values = new Color[PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
for (int i = 0; i < PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; ++i)
{
float colorValue = i / 255.0f;
values[i] = new Color(colorValue, 0.0f, 0.0f, 1.0f);
}
PassthroughFeature.SetColorMapbyMonoToRgba(ref passthroughStyle, values);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
}
public void SetColorMapG()
{
var values = new Color[PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
for (int i = 0; i < PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; ++i)
{
float colorValue = i / 255.0f;
values[i] = new Color(0.0f, colorValue, 0.0f, 1.0f);
}
PassthroughFeature.SetColorMapbyMonoToRgba(ref passthroughStyle, values);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
}
public void SetColorMapB()
{
var values = new Color[PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
for (int i = 0; i < PassthroughFeature.XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; ++i)
{
float colorValue = i / 255.0f;
values[i] = new Color(0.0f, 0.0f, colorValue, 1.0f);
}
PassthroughFeature.SetColorMapbyMonoToRgba(ref passthroughStyle, values);
PassthroughFeature.SetPassthroughStyle(passthroughStyle);
}
#endif
}

View File

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

View File

@@ -0,0 +1,103 @@
using System.Collections.Generic;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.Rendering;
public class PXR_ObjectTrackingBlock : MonoBehaviour
{
private Transform objectTrackers;
private bool updateOT = true;
private int objectTrackersMaxNum = 3;
int DeviceCount = 1;
List<long> trackerIds = new List<long>();
// Start is called before the first frame update
void Start()
{
objectTrackers = transform;
for (int i = 0; i < objectTrackersMaxNum; i++)
{
GameObject ga = GameObject.CreatePrimitive(PrimitiveType.Cube);
ga.transform.parent = objectTrackers;
ga.transform.localScale = Vector3.one * 0f;
#if UNITY_6000_0_OR_NEWER
if (GraphicsSettings.defaultRenderPipeline != null)
#else
if (GraphicsSettings.renderPipelineAsset != null)
#endif
{
Material material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
Renderer renderer = ga.GetComponent<Renderer>();
if (renderer != null)
{
renderer.sharedMaterial = material;
}
}
}
int res = -1;
#if PICO_OPENXR_SDK
#else
PXR_MotionTracking.RequestMotionTrackerCompleteAction += RequestMotionTrackerComplete;
res = PXR_MotionTracking.CheckMotionTrackerNumber(MotionTrackerNum.TWO);
#endif
if (res == 0)
{
objectTrackers.gameObject.SetActive(true);
}
}
private void RequestMotionTrackerComplete(RequestMotionTrackerCompleteEventData obj)
{
DeviceCount = (int)obj.trackerCount;
for (int i = 0; i < DeviceCount; i++)
{
trackerIds.Add(obj.trackerIds[i]);
}
updateOT = true;
}
// Update is called once per frame
void Update()
{
#if UNITY_ANDROID
for (int i = 0; i < objectTrackersMaxNum; i++)
{
var child = objectTrackers.GetChild(i);
if (child)
{
child.localScale = Vector3.zero;
}
}
// Update motiontrackers pose.
if (updateOT )
{
MotionTrackerLocation location = new MotionTrackerLocation();
for (int i = 0; i < trackerIds.Count; i++)
{
bool isValidPose = false;
int result = -1;
#if PICO_OPENXR_SDK
#else
result = PXR_MotionTracking.GetMotionTrackerLocation(trackerIds[i], ref location, ref isValidPose);
#endif
// if the return is successful
if (result == 0)
{
var child = objectTrackers.GetChild(i);
if (child)
{
child.localPosition = location.pose.Position.ToVector3();
child.localRotation = location.pose.Orientation.ToQuat();
child.localScale = Vector3.one * 0.1f;
}
}
}
}
#endif
}
}

View File

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

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SliderText : MonoBehaviour
{
public Text text;
private Slider m_Slider;//Slider<65><72><EFBFBD><EFBFBD>
// Start is called before the first frame update
void Start()
{
m_Slider = GetComponent<Slider>();
m_Slider.onValueChanged.AddListener(delegate {ValueChangeCheck(); });
}
private void ValueChangeCheck()
{
text.text = m_Slider.value.ToString();
}
// Update is called once per frame
void Update()
{
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bec33959f7da2ab48afb4551f620ee26
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
#if XR_COMPOSITION_LAYERS
using System.Collections.Generic;
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Layers;
using Unity.XR.CompositionLayers.Services;
using UnityEngine;
namespace Unity.XR.PXR
{
internal class PXR_CubeLayer : PXR_CustomLayerHandler<XrCompositionLayerCubeKHR>
{
protected override unsafe bool CreateSwapchain(CompositionLayerManager.LayerInfo layerInfo, out SwapchainCreateInfo swapchainCreateInfo)
{
TexturesExtension texture = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texture == null || texture.enabled == false || texture.LeftTexture == null)
{
swapchainCreateInfo = default;
return false;
}
swapchainCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = PXR_LayerUtility.GetDefaultColorFormat(),
SampleCount = 1,
Width = (uint)(texture.LeftTexture.width),
Height = (uint)(texture.LeftTexture.height),
FaceCount = 6,
ArraySize = 1,
MipCount = (uint)texture.LeftTexture.mipmapCount,
};
return true;
}
protected override unsafe bool CreateNativeLayer(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput, out XrCompositionLayerCubeKHR nativeLayer)
{
var data = layerInfo.Layer.LayerData as CubeProjectionLayerData;
var transform = layerInfo.Layer.GetComponent<Transform>();
nativeLayer = new XrCompositionLayerCubeKHR()
{
Type = (uint)XrStructureType.XR_TYPE_COMPOSITION_LAYER_CUBE_KHR,
Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer),
LayerFlags = data.BlendType == BlendType.Premultiply ? XrCompositionLayerFlags.SourceAlpha : XrCompositionLayerFlags.SourceAlpha | XrCompositionLayerFlags.UnPremultipliedAlpha,
Space = PXR_LayerUtility.GetCurrentAppSpace(),
EyeVisibility = 0,
Swapchain = swapchainOutput.handle,
ImageArrayIndex = 0,
Orientation = new XrQuaternionf(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation)
};
return true;
}
protected override bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerCubeKHR nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false || texturesExtension.LeftTexture == null)
return false;
var transform = layerInfo.Layer.GetComponent<Transform>();
nativeLayer.Space = PXR_LayerUtility.GetCurrentAppSpace();
nativeLayer.Orientation = new XrQuaternionf(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
return true;
}
protected override bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerCubeKHR nativeLayer)
{
nativeLayer.Space = PXR_LayerUtility.GetCurrentAppSpace();
return base.ActiveNativeLayer(layerInfo, ref nativeLayer);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,491 @@
#if XR_COMPOSITION_LAYERS
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Services;
using UnityEngine;
#if UNITY_VIDEO
using UnityEngine.Video;
#endif
namespace Unity.XR.PXR
{
/// <summary>
/// Provides a base implementation for the <see cref="PXR_LayerProvider.ILayerHandler"/> interface.
/// You can implement the required methods of this abstract class to create a concrete layer handler.
/// </summary>
/// <remarks>
/// The <see cref="PXR_LayerProvider.ILayerHandler"/> methods that this class implements handle adding
/// and removing composition layers from native arrays, swap chain creation dispatching and other tasks
/// required by the Unity side of the API.
///
/// The abstract methods that you must implement handle the custom aspects of your layer. These methods include:
///
/// * <see cref="CreateSwapchain(CompositionLayerManager.LayerInfo, out SwapchainCreateInfo)"/>
/// * <see cref="CreateNativeLayer(CompositionLayerManager.LayerInfo, PXR_CustomLayerHandler{T}.SwapchainCreatedOutput, out T)"/>
/// * <see cref="ModifyNativeLayer(CompositionLayerManager.LayerInfo, ref T)"/>
///
/// You are not required to implement a custom layer handler based on this abstract class, but doing so should be
/// easier than implementing the <see cref="PXR_LayerProvider.ILayerHandler"/> interface in its entirety.
///
/// You must register your concrete layer handler object with
/// <see cref="PXR_LayerProvider.RegisterLayerHandler(Type, PXR_LayerProvider.ILayerHandler)"/>.
/// </remarks>
/// <typeparam name="T">The native PXR_ structure of the composition layer to handle.</typeparam>
public abstract class PXR_CustomLayerHandler<T> : PXR_LayerProvider.ILayerHandler, IDisposable where T : struct
{
/// <summary>
/// Container for swapchain related information that may be needed during the creation of the native PXR_ composition layer struct.
/// </summary>
protected struct SwapchainCreateInfo
{
/// <summary>
/// Native structure for the swapchain creation info.
/// </summary>
public XrSwapchainCreateInfo nativeStruct;
/// <summary>
/// Tells if swapchain is using an external surface.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool isExternalSurface;
/// <summary>
/// Tells if swapchain should be stereo.
/// </summary>
public bool isStereo;
/// <summary>
/// Initializes and returns an instance of SwapchainCreateInfo with the provided parameters.
/// </summary>
/// <param name="xrSwapchainCreateInfo">Native structure for the swapchain creation info.</param>
/// <param name="isExternalSurface">Tells if swapchain is using an external surface.</param>
/// <param name="isStereo">Tells if swapchain should be stereo.</param>
public SwapchainCreateInfo(XrSwapchainCreateInfo xrSwapchainCreateInfo, bool isExternalSurface = false, bool isStereo = false)
{
this.nativeStruct = xrSwapchainCreateInfo;
this.isExternalSurface = isExternalSurface;
this.isStereo = isStereo;
}
/// <summary>
/// Implicit conversion with just a native XrSwapchainCreateInfo struct.
/// </summary>
/// <param name="createInfo">The native struct to convert.</param>
public static implicit operator SwapchainCreateInfo(XrSwapchainCreateInfo createInfo) => new SwapchainCreateInfo(createInfo);
}
/// <summary>
/// Container for swapchain related information that may be needed during the creation of the native PXR_ composition layer struct.
/// </summary>
protected struct SwapchainCreatedOutput
{
/// <summary>
/// The handle of the created swapchain.
/// Can be used to initialize the swapchain member of a native PXR_ composition layer struct.
/// </summary>
public ulong handle;
/// <summary>
/// The second handle of the created stereo swapchain.
/// Can be used to initialize the swapchain member of a native PXR_ composition layer struct.
/// </summary>
public ulong secondStereoHandle;
}
/// <summary>
/// Container for grouping render information for each compostion layer.
/// </summary>
class LayerRenderInfo
{
public Texture RenderTexture;
public Texture Texture;
#if UNITY_VIDEO
public VideoPlayer videoPlayer;
#endif
public MeshCollider meshCollider;
}
/// <summary>
/// Initializes and returns an instance of this <c>PXR_CustomLayerHandler&lt;T&gt;</c> while also setting the singleton instance member.
/// </summary>
protected PXR_CustomLayerHandler() => Instance = this;
/// <summary>
/// Singleton instance of this specific handler.
/// </summary>
protected static PXR_CustomLayerHandler<T> Instance;
/// <summary>
/// Deinitializes this instance of c>PXR_CustomLayerHandler&lt;T&gt;</c>.
/// </summary>
~PXR_CustomLayerHandler() => Dispose(false);
/// <summary>
/// Override this method to create the <see cref="XrSwapchainCreateInfo"/> struct that is passed to PXR_
/// to create a swapchain.
/// </summary>
/// <remarks>
/// To add extensions when constructing the <see cref="XrSwapchainCreateInfo"/> struct, initialize
/// the <c>Next</c> pointer with
/// <see cref="PXR_LayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>.
/// </remarks>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was just created.</param>
/// <param name="swapchainCreateInfo"> An <c>XrSwapchainCreateInfo</c> object created and initialized by the concrete implementation of this method.</returns>
/// <returns> A bool indicating success or failure.</returns>
protected abstract bool CreateSwapchain(CompositionLayerManager.LayerInfo layerInfo, out SwapchainCreateInfo swapchainCreateInfo);
/// <summary>
/// Override this method to create the native composition layer struct of type T that is passed to PXR_.
/// A swapchain info struct is provided so your layer handler has access to any needed swapchain information.
/// </summary>
/// <remarks>
/// To add extensions when constructing the <see cref="XrSwapchainCreateInfo"/> struct, initialize
/// the <c>Next</c> pointer with <see cref="PXR_LayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>.
///
/// If your struct needs any XrSpace relative info you can use <see cref="PXR_LayerUtility.GetCurrentAppSpace"/>
/// to get the current app space.
/// </remarks>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was just created.</param>
/// <param name="swapchainOutput"> Information regarding the swapchain that was created for this layer,
/// such as the associated swapchain handle.</param>
/// <param name="nativeLayer"> An object of type T that is created and initialized by the concrete implementation of this method.</returns>
/// <returns> A bool indicating success or failure.</returns>
protected abstract bool CreateNativeLayer(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput, out T nativeLayer);
/// <summary>
/// Override this method to modify a native composition layer struct in response to changes on the associated
/// <see cref="Unity.XR.CompositionLayers.Layers.LayerData"/> object or any extension components on the
/// <see cref="Unity.XR.CompositionLayers.CompositionLayer"/> GameObject.
/// </summary>
/// <remarks>
/// You must reinitialize the Next pointer with <see cref="PXR_LayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>
/// to get any potential updates from extension components.
/// </remarks>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition
/// layer that was modified.</param>
/// <param name="nativeLayer"> A reference to the native PXR_ structure of the composition layer that was modified.
/// The concrete implementation of this method should update the values of the structure as appropriate.</param>
/// <returns> A bool indicating success or failure.</returns>
protected abstract bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref T nativeLayer);
/// <summary>
/// Mapping of instance ids and native layer structs to help determine what layers are currently set to be active.
/// </summary>
protected Dictionary<int, T> m_nativeLayers = new Dictionary<int, T>();
/// <summary>
/// Thread safe queue used to dispatch callbacks that may come from other threads such as the swapchain creation
/// on the graphics thread.
/// </summary>
protected ConcurrentQueue<Action> actionsForMainThread = new ConcurrentQueue<Action>();
Dictionary<int, LayerRenderInfo> m_renderInfos = new Dictionary<int, LayerRenderInfo>();
Dictionary<int, CompositionLayerManager.LayerInfo> m_layerInfos = new Dictionary<int, CompositionLayerManager.LayerInfo>();
NativeArray<T> m_ActiveNativeLayers;
NativeArray<int> m_ActiveNativeLayerOrders;
int m_ActiveNativeLayerCount;
/// <summary>
/// Implements the <see cref="PXR_LayerProvider.ILayerHandler"/> method that is called by the
/// <see cref="PXR_LayerProvider"/> during the Unity update loop.
/// </summary>
/// <remarks>
/// This implementation carries out two tasks. It dequeues actions for the main thread like dispatch when
/// the swapchain has been
/// created and it adds all the active layers to the <c>endFrameInfo</c> struct in the native UnityPXR_ lib.
/// </remarks>
public virtual void OnUpdate()
{
while (actionsForMainThread.Count > 0)
{
if (actionsForMainThread.TryDequeue(out Action action))
action();
}
unsafe
{
if (m_ActiveNativeLayerCount > 0)
PXR_LayerUtility.AddActiveLayersToEndFrame(m_ActiveNativeLayers.GetUnsafePtr(), m_ActiveNativeLayerOrders.GetUnsafePtr(), m_ActiveNativeLayerCount, UnsafeUtility.SizeOf<T>());
}
m_ActiveNativeLayerCount = 0;
}
/// <summary>
/// Implements the <see cref="PXR_LayerProvider.ILayerHandler"/> method that is called by the
/// <see cref="PXR_LayerProvider"/> when a new layer has been created.
/// This implementation triggers the creation of a swapchain before the actual native layer struct is created.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// being created.</param>
public void CreateLayer(CompositionLayerManager.LayerInfo layerInfo)
{
CreateSwapchainAsync(layerInfo);
}
/// <summary>
/// Implements the <see cref="PXR_LayerProvider.ILayerHandler"/> method that is called by the
/// <see cref="PXR_LayerProvider"/> when a layer or attached extension has been modified.
/// This implementation asks the subclass for any changes that must be made to the layer via
/// <see cref="ModifyNativeLayer(CompositionLayerManager.LayerInfo, ref T)"/>
/// by sending a reference to the native layer struct.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was modified.</param>
public virtual void ModifyLayer(CompositionLayerManager.LayerInfo layerInfo)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (!m_nativeLayers.TryGetValue(layerInfo.Id, out var nativeLayer))
{
if (texturesExtension != null && texturesExtension.TextureAdded)
{
texturesExtension.TextureAdded = false;
CreateLayer(layerInfo);
}
return;
}
var success = ModifyNativeLayer(layerInfo, ref nativeLayer);
if (success)
m_nativeLayers[layerInfo.Id] = nativeLayer;
}
/// <summary>
/// Implements the <see cref="PXR_LayerProvider.ILayerHandler"/> method that is called by the
/// <see cref="PXR_LayerProvider"/> when a layer is destroyed or disabled.
/// </summary>
/// <param name="removedLayerId"> The instance id of the CompositionLayer component that was removed.</param>
public virtual void RemoveLayer(int removedLayerId)
{
PXR_LayerUtility.ReleaseSwapchain(removedLayerId);
m_nativeLayers.Remove(removedLayerId);
m_layerInfos.Remove(removedLayerId);
m_renderInfos.Remove(removedLayerId);
}
/// <summary>
/// Implements the <see cref="PXR_LayerProvider.ILayerHandler"/> method that is called by the
/// <see cref="PXR_LayerProvider"/> when a layer is considered to be currently active.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// being set to active.</param>
public virtual void SetActiveLayer(CompositionLayerManager.LayerInfo layerInfo)
{
if (!m_nativeLayers.TryGetValue(layerInfo.Id, out var nativeLayer))
return;
var success = ActiveNativeLayer(layerInfo, ref nativeLayer);
if (!success)
return;
m_nativeLayers[layerInfo.Id] = nativeLayer;
ResizeNativeArrays();
m_ActiveNativeLayers[m_ActiveNativeLayerCount] = m_nativeLayers[layerInfo.Id];
m_ActiveNativeLayerOrders[m_ActiveNativeLayerCount] = layerInfo.Layer.Order;
++m_ActiveNativeLayerCount;
}
/// <summary>
/// Implements method from <see cref="IDisposable"/> that is called by the <see cref="PXR_LayerProvider"/>
/// when this custom layer handler instance is disposed.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Clears all maps and disposes any created native arrays.
/// </summary>
/// <param name="disposing">Determines if this method was called from the Dispose() method or the finalizer.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
m_layerInfos.Clear();
m_nativeLayers.Clear();
m_renderInfos.Clear();
}
if (m_ActiveNativeLayers.IsCreated)
m_ActiveNativeLayers.Dispose();
if (m_ActiveNativeLayerOrders.IsCreated)
m_ActiveNativeLayerOrders.Dispose();
}
/// <summary>
/// Calls <see cref="CreateSwapchain(CompositionLayerManager.LayerInfo, out SwapchainCreateInfo)"/> to create a
/// <see cref="SwapchainCreateInfo"/> struct that is then passed to the
/// UnityPXR_ lib to actually create the swapchain on the graphics thread.
/// The static <see cref="OnCreatedSwapchainCallback(int, ulong)"/> method is passed as a callback and invoked when
/// the swapchain has been created.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was just created.</param>
protected virtual void CreateSwapchainAsync(CompositionLayerManager.LayerInfo layerInfo)
{
m_layerInfos[layerInfo.Id] = layerInfo;
var success = CreateSwapchain(layerInfo, out var swapChainInfo);
if (!success)
return;
if (swapChainInfo.isStereo)
PXR_LayerUtility.CreateStereoSwapchain(layerInfo.Id, swapChainInfo.nativeStruct, OnCreatedStereoSwapchainCallback);
else
PXR_LayerUtility.CreateSwapchain(layerInfo.Id, swapChainInfo.nativeStruct, swapChainInfo.isExternalSurface, OnCreatedSwapchainCallback);
}
/// <summary>
/// This method is dispatched to the main thread inside <see cref="OnCreatedSwapchainCallback(int, ulong)"/>
/// and asks this subclass to create the native layer struct by invoking
/// <see cref="CreateNativeLayer(CompositionLayerManager.LayerInfo, SwapchainCreatedOutput, out T)"/>.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was just created.</param>
/// <param name="swapchainOutput"> Information regarding the swapchain that was created for this layer, such as
/// the associated swapchain handle.</param>
protected virtual void OnCreatedSwapchain(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput)
{
var success = CreateNativeLayer(layerInfo, swapchainOutput, out var nativeLayer);
if (success){
m_nativeLayers[layerInfo.Id] = nativeLayer;
}
}
/// <summary>
/// Ensures that the native arrays are of the same size as the m_nativeLayers map.
/// </summary>
protected virtual void ResizeNativeArrays()
{
if (!m_ActiveNativeLayers.IsCreated && !m_ActiveNativeLayerOrders.IsCreated)
{
m_ActiveNativeLayers = new NativeArray<T>(m_nativeLayers.Count, Allocator.Persistent);
m_ActiveNativeLayerOrders = new NativeArray<int>(m_nativeLayers.Count, Allocator.Persistent);
return;
}
UnityEngine.Assertions.Assert.AreEqual(m_ActiveNativeLayers.Length, m_ActiveNativeLayerOrders.Length);
if (m_ActiveNativeLayers.Length < m_nativeLayers.Count)
{
var newLayerArray = new NativeArray<T>(m_nativeLayers.Count, Allocator.Persistent);
NativeArray<T>.Copy(m_ActiveNativeLayers, newLayerArray, m_ActiveNativeLayers.Length);
m_ActiveNativeLayers.Dispose();
m_ActiveNativeLayers = newLayerArray;
var newOrderArray = new NativeArray<int>(m_nativeLayers.Count, Allocator.Persistent);
NativeArray<int>.Copy(m_ActiveNativeLayerOrders, newOrderArray, m_ActiveNativeLayerOrders.Length);
m_ActiveNativeLayerOrders.Dispose();
m_ActiveNativeLayerOrders = newOrderArray;
}
}
/// <summary>
/// Override this method to modify a native composition layer struct in response to when it is active.
/// An active compositon layer will invoke this every frame.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition
/// layer that is active.</param>
/// <param name="nativeLayer"> A reference to the native PXR_ structure of the composition layer that is active.</param>
/// <returns>Bool indicating success or failure. A failure case will result in the native composition layer struct not being added into the final XrFrameEndInfo struct.</returns>
protected virtual bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref T nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.LeftTexture == null || texturesExtension.sourceTexture == TexturesExtension.SourceTextureEnum.AndroidSurface)
return true;
if (m_renderInfos.TryGetValue(layerInfo.Id, out var container))
{
PXR_LayerUtility.WriteToRenderTexture(layerInfo.Id, container.Texture, container.RenderTexture, nativeLayer.GetType() == typeof(XrCompositionLayerCubeKHR));
bool isNewTexture = container.Texture != texturesExtension.LeftTexture;
if (isNewTexture)
{
// If we have a new texture with different dimensions then we need to release the current swapchain and create another.
// This is an async procedure that also creates a new native layer object.
if (container.Texture.width != texturesExtension.LeftTexture.width || container.Texture.height != texturesExtension.LeftTexture.height)
{
RemoveLayer(layerInfo.Id);
CreateSwapchainAsync(layerInfo);
return false;
}
else
container.Texture = texturesExtension.LeftTexture;
#if UNITY_VIDEO
container.videoPlayer = layerInfo.Layer.GetComponent<VideoPlayer>();
#endif
container.meshCollider = layerInfo.Layer.GetComponent<MeshCollider>();
}
bool isVideo = false;
#if UNITY_VIDEO
isVideo = container.videoPlayer != null && container.videoPlayer.enabled;
#endif
bool isUI = container.meshCollider != null && container.meshCollider.enabled;
#if UNITY_EDITOR
// Layers with a video or ui component in editor may have multiple native render textures associated with the layer id so we must find them.
if (isVideo || isUI){
PXR_LayerUtility.FindAndWriteToRenderTexture(layerInfo, container.Texture, out container.RenderTexture, nativeLayer.GetType() == typeof(XrCompositionLayerCubeKHR));
}
else if (isNewTexture){
PXR_LayerUtility.WriteToRenderTexture(layerInfo.Id, container.Texture, container.RenderTexture, nativeLayer.GetType() == typeof(XrCompositionLayerCubeKHR));
}
#else
// We only need to write continuously to the native render texture if our texture is changing.
if (isVideo || isUI || isNewTexture)
PXR_LayerUtility.WriteToRenderTexture(layerInfo.Id, container.Texture, container.RenderTexture, nativeLayer.GetType() == typeof(XrCompositionLayerCubeKHR));
#endif
}
else
{
bool isRenderTextureWritten = PXR_LayerUtility.FindAndWriteToRenderTexture(layerInfo, texturesExtension.LeftTexture, out Texture renderTexture, nativeLayer.GetType() == typeof(XrCompositionLayerCubeKHR));
if (isRenderTextureWritten)
{
var layerRenderInfo = new LayerRenderInfo()
{ Texture = texturesExtension.LeftTexture, RenderTexture = renderTexture,
#if UNITY_VIDEO
videoPlayer = layerInfo.Layer.GetComponent<VideoPlayer>(),
#endif
meshCollider = layerInfo.Layer.GetComponent<MeshCollider>() };
m_renderInfos.Add(layerInfo.Id, layerRenderInfo);
};
}
return true;
}
[AOT.MonoPInvokeCallback(typeof(PXR_LayerUtility.SwapchainCallbackDelegate))]
static void OnCreatedSwapchainCallback(int layerId, ulong swapchainHandle)
{
if (Instance == null)
return;
Instance.actionsForMainThread.Enqueue(() => { Instance.OnCreatedSwapchain(Instance.m_layerInfos[layerId], new SwapchainCreatedOutput { handle = swapchainHandle });});
}
[AOT.MonoPInvokeCallback(typeof(PXR_LayerUtility.StereoSwapchainCallbackDelegate))]
static void OnCreatedStereoSwapchainCallback(int layerId, ulong swapchainHandleLeft, ulong swapchainHandleRight)
{
if (Instance == null)
return;
Instance.actionsForMainThread.Enqueue(() => { Instance.OnCreatedSwapchain(Instance.m_layerInfos[layerId], new SwapchainCreatedOutput { handle = swapchainHandleLeft, secondStereoHandle = swapchainHandleRight}); });
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,314 @@
#if XR_COMPOSITION_LAYERS
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Layers;
using Unity.XR.CompositionLayers.Services;
using UnityEngine;
namespace Unity.XR.PXR
{
internal class PXR_CylinderLayer : PXR_CustomLayerHandler<XrCompositionLayerCylinderKHR>
{
float savedDelta;
bool layerDataChanged = false;
struct CylinderLayerSize
{
public float radius;
public float centralAngle;
public float aspectRatio;
public static implicit operator CylinderLayerSize(Vector3 v) => new CylinderLayerSize
{
radius = v.x,
centralAngle = v.y,
aspectRatio = v.z
};
}
protected override bool CreateSwapchain(CompositionLayerManager.LayerInfo layer, out SwapchainCreateInfo swapchainCreateInfo)
{
if (layer.Layer == null)
{
swapchainCreateInfo = default;
return false;
}
unsafe
{
var texturesExtension = layer.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
{
swapchainCreateInfo = default;
return false;
}
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture == null)
goto default;
var xrCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = PXR_LayerUtility.GetDefaultColorFormat(),
SampleCount = 1,
Width = (uint)texturesExtension.LeftTexture.width,
Height = (uint)texturesExtension.LeftTexture.height,
FaceCount = 1,
ArraySize = 1,
MipCount = (uint)texturesExtension.LeftTexture.mipmapCount,
};
swapchainCreateInfo = new SwapchainCreateInfo(xrCreateInfo, isExternalSurface: false);
return true;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
#if UNITY_ANDROID
var xrCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = 0,
SampleCount = 0,
Width = (uint)texturesExtension.Resolution.x,
Height = (uint)texturesExtension.Resolution.y,
FaceCount = 0,
ArraySize = 0,
MipCount = 0,
};
swapchainCreateInfo = new SwapchainCreateInfo(xrCreateInfo, isExternalSurface: true);
return true;
#else
goto default;
#endif
}
default:
swapchainCreateInfo = default;
return false;
}
}
}
protected override bool CreateNativeLayer(CompositionLayerManager.LayerInfo layer, SwapchainCreatedOutput swapchainOutput, out XrCompositionLayerCylinderKHR nativeLayer)
{
unsafe
{
var data = layer.Layer.LayerData as CylinderLayerData;
var transform = layer.Layer.GetComponent<Transform>();
var texturesExtension = layer.Layer.GetComponent<TexturesExtension>();
int subImageWidth = 0;
int subImageHeight = 0;
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture != null)
{
subImageWidth = texturesExtension.LeftTexture.width;
subImageHeight = texturesExtension.LeftTexture.height;
}
break;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
subImageWidth = (int)texturesExtension.Resolution.x;
subImageHeight = (int)texturesExtension.Resolution.y;
break;
}
}
CylinderLayerSize scaledSize = data.GetScaledSize(transform.lossyScale);
if (texturesExtension.CropToAspect)
{
scaledSize = FixAspectRatio(data, scaledSize, subImageWidth, subImageHeight);
}
nativeLayer = new XrCompositionLayerCylinderKHR()
{
Type = (uint)XrStructureType.XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Layer),
LayerFlags = data.BlendType == BlendType.Premultiply ? XrCompositionLayerFlags.SourceAlpha : XrCompositionLayerFlags.SourceAlpha | XrCompositionLayerFlags.UnPremultipliedAlpha,
Space = PXR_LayerUtility.GetCurrentAppSpace(),
EyeVisibility = 0,
SubImage = new XrSwapchainSubImage()
{
Swapchain = swapchainOutput.handle,
ImageRect = new XrRect2Di()
{
Offset = new XrOffset2Di() { X = 0, Y = 0 },
Extent = new XrExtent2Di()
{
Width = subImageWidth,
Height = subImageHeight
}
},
ImageArrayIndex = 0
},
Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation),
Radius = data.ApplyTransformScale ? scaledSize.radius : data.Radius,
CentralAngle = data.ApplyTransformScale ? scaledSize.centralAngle : data.CentralAngle,
AspectRatio = data.ApplyTransformScale ? scaledSize.aspectRatio : data.AspectRatio,
};
layerDataChanged = true;
return true;
}
}
protected override bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerCylinderKHR nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
return false;
var data = layerInfo.Layer.LayerData as CylinderLayerData;
GetSubImageDimensions(out int subImageWidth, out int subImageHeight, texturesExtension);
nativeLayer.SubImage.ImageRect.Extent = new XrExtent2Di()
{
Width = subImageWidth,
Height = subImageHeight
};
var transform = layerInfo.Layer.GetComponent<Transform>();
CylinderLayerSize scaledSize = data.GetScaledSize(transform.lossyScale);
if (texturesExtension.CropToAspect)
{
scaledSize = FixAspectRatio(data, scaledSize, subImageWidth, subImageHeight);
}
nativeLayer.Radius = data.ApplyTransformScale ? scaledSize.radius : data.Radius;
nativeLayer.CentralAngle = data.ApplyTransformScale ? scaledSize.centralAngle : data.CentralAngle;
nativeLayer.AspectRatio = data.ApplyTransformScale ? scaledSize.aspectRatio : data.AspectRatio;
unsafe
{
nativeLayer.Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer);
}
layerDataChanged = true;
return true;
}
protected override bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerCylinderKHR nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
return false;
var transform = layerInfo.Layer.GetComponent<Transform>();
// Special treatment for cylinder type based on destination rects.
if (texturesExtension != null && texturesExtension.CustomRects)
{
var cylinderLayer = layerInfo.Layer.LayerData as CylinderLayerData;
float rotationDelta = (texturesExtension.LeftEyeDestinationRect.x + (0.5f * texturesExtension.LeftEyeDestinationRect.width) - 0.5f) * cylinderLayer.CentralAngle / (float)System.Math.PI * 180.0f;
if (rotationDelta != savedDelta)
{
Quaternion savedDeltaQuaternion = Quaternion.AngleAxis(savedDelta, Vector3.up);
Quaternion deltaQuaternion = Quaternion.AngleAxis(rotationDelta, Vector3.up);
Quaternion difference = deltaQuaternion * Quaternion.Inverse(savedDeltaQuaternion);
savedDelta = rotationDelta;
transform.rotation *= difference;
}
}
nativeLayer.Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
nativeLayer.Space = PXR_LayerUtility.GetCurrentAppSpace();
if (texturesExtension.CustomRects && layerDataChanged)
{
GetSubImageDimensions(out int subImageWidth, out int subImageHeight, texturesExtension);
nativeLayer.SubImage.ImageRect = new XrRect2Di()
{
Offset = new XrOffset2Di()
{
X = (int)(subImageWidth * texturesExtension.LeftEyeSourceRect.x),
Y = (int)(subImageHeight * texturesExtension.LeftEyeSourceRect.y)
},
Extent = new XrExtent2Di()
{
Width = (int)(subImageWidth * texturesExtension.LeftEyeSourceRect.width),
Height = (int)(subImageHeight * texturesExtension.LeftEyeSourceRect.height)
}
};
var currentPosition = PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position;
float cylinderHeight = nativeLayer.Radius * nativeLayer.CentralAngle / nativeLayer.AspectRatio;
float transformedY = currentPosition.y + (((texturesExtension.LeftEyeDestinationRect.y + (0.5f * texturesExtension.LeftEyeDestinationRect.height) - 0.5f)) * (-1.0f * cylinderHeight));
nativeLayer.Pose = new XrPosef(new Vector3(currentPosition.x, transformedY, currentPosition.z), PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
nativeLayer.CentralAngle = nativeLayer.CentralAngle * texturesExtension.LeftEyeDestinationRect.width;
nativeLayer.AspectRatio = nativeLayer.AspectRatio * texturesExtension.LeftEyeDestinationRect.width / texturesExtension.LeftEyeDestinationRect.height;
layerDataChanged = false;
}
return base.ActiveNativeLayer(layerInfo, ref nativeLayer);
}
static CylinderLayerSize FixAspectRatio(CylinderLayerData data, CylinderLayerSize scaledSize, int texWidth, int texHeight)
{
// because we're cropping and trying to maintain the same other parameters, we don't
// need to consider data.MaintainAspectRatio here. That's mostly an editor concern, anyway.
float texRatio = (float)texWidth / (float)texHeight;
if (scaledSize.aspectRatio > texRatio)
{
// too wide
float width = scaledSize.radius * scaledSize.centralAngle;
float height = width / scaledSize.aspectRatio;
scaledSize.centralAngle = height * texRatio / scaledSize.radius;
scaledSize.aspectRatio = texRatio;
}
else if (scaledSize.aspectRatio < texRatio)
{
// too narrow
scaledSize.aspectRatio = texRatio;
}
return scaledSize;
}
static void GetSubImageDimensions(out int width, out int height, TexturesExtension texturesExtension)
{
width = 0;
height = 0;
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture != null)
{
width = texturesExtension.LeftTexture.width;
height = texturesExtension.LeftTexture.height;
}
break;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
width = (int)texturesExtension.Resolution.x;
height = (int)texturesExtension.Resolution.y;
break;
}
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,40 @@
#if XR_COMPOSITION_LAYERS
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Layers;
using Unity.XR.CompositionLayers.Services;
namespace Unity.XR.PXR
{
internal class PXR_DefaultLayer : PXR_LayerProvider.ILayerHandler
{
unsafe void SetDefaultLayerAttributes(CompositionLayerManager.LayerInfo layerInfo)
{
var extensions = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer);
PXR_LayerUtility.SetDefaultSceneLayerExtensions(extensions);
var flags = layerInfo.Layer.LayerData.BlendType == BlendType.Premultiply ? XrCompositionLayerFlags.SourceAlpha : XrCompositionLayerFlags.SourceAlpha | XrCompositionLayerFlags.UnPremultipliedAlpha;
PXR_LayerUtility.SetDefaultLayerFlags(flags);
}
public void CreateLayer(CompositionLayerManager.LayerInfo layerInfo) => SetDefaultLayerAttributes(layerInfo);
public void ModifyLayer(CompositionLayerManager.LayerInfo layerInfo) => SetDefaultLayerAttributes(layerInfo);
public void OnUpdate()
{
return;
}
public void RemoveLayer(int id)
{
return;
}
public void SetActiveLayer(CompositionLayerManager.LayerInfo layerInfo)
{
return;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,120 @@
#if XR_COMPOSITION_LAYERS
using System;
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Layers;
using Unity.XR.CompositionLayers.Services;
using UnityEngine;
namespace Unity.XR.PXR
{
internal class PXR_Equirect2Layer : PXR_CustomLayerHandler<XrCompositionLayerEquirect2KHR>
{
protected override unsafe bool CreateSwapchain(CompositionLayerManager.LayerInfo layerInfo, out SwapchainCreateInfo swapchainCreateInfo)
{
TexturesExtension texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false || texturesExtension.LeftTexture == null)
{
swapchainCreateInfo = default;
return false;
}
swapchainCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = PXR_LayerUtility.GetDefaultColorFormat(),
SampleCount = 1,
Width = (uint)(texturesExtension.LeftTexture.width),
Height = (uint)(texturesExtension.LeftTexture.height),
FaceCount = 1,
ArraySize = 1,
MipCount = (uint)texturesExtension.LeftTexture.mipmapCount,
};
return true;
}
protected override unsafe bool CreateNativeLayer(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput, out XrCompositionLayerEquirect2KHR nativeLayer)
{
TexturesExtension texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false || texturesExtension.LeftTexture == null)
{
nativeLayer = default;
return false;
}
var transform = layerInfo.Layer.GetComponent<Transform>();
var data = layerInfo.Layer.LayerData as EquirectMeshLayerData;
Vector2 scaleCalculated = CalculateScale(data.CentralHorizontalAngle, data.UpperVerticalAngle, data.LowerVerticalAngle);
nativeLayer = new XrCompositionLayerEquirect2KHR()
{
Type = (uint)XrStructureType.XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR,
Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer),
LayerFlags = data.BlendType == BlendType.Premultiply ? XrCompositionLayerFlags.SourceAlpha : XrCompositionLayerFlags.SourceAlpha | XrCompositionLayerFlags.UnPremultipliedAlpha,
Space = PXR_LayerUtility.GetCurrentAppSpace(),
EyeVisibility = 0,
SubImage = new XrSwapchainSubImage()
{
Swapchain = swapchainOutput.handle,
ImageRect = new XrRect2Di()
{
Offset = new XrOffset2Di() { X = 0, Y = 0 },
Extent = new XrExtent2Di()
{
Width = texturesExtension.LeftTexture.width,
Height = texturesExtension.LeftTexture.height
}
},
ImageArrayIndex = 0
},
Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation),
Radius = data.Radius,
CentralHorizontalAngle = data.CentralHorizontalAngle,
UpperVerticalAngle = data.UpperVerticalAngle,
LowerVerticalAngle = -data.LowerVerticalAngle
};
return true;
}
protected override unsafe bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerEquirect2KHR nativeLayer)
{
TexturesExtension texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false || texturesExtension.LeftTexture == null)
return false;
var transform = layerInfo.Layer.GetComponent<Transform>();
var data = layerInfo.Layer.LayerData as EquirectMeshLayerData;
Vector2 scaleCalculated = CalculateScale(data.CentralHorizontalAngle, data.UpperVerticalAngle, data.LowerVerticalAngle);
nativeLayer.SubImage.ImageRect.Extent = new XrExtent2Di()
{
Width = texturesExtension.LeftTexture.width,
Height = texturesExtension.LeftTexture.height
};
nativeLayer.Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
nativeLayer.Radius = data.Radius;
nativeLayer.CentralHorizontalAngle = data.CentralHorizontalAngle;
nativeLayer.UpperVerticalAngle = data.UpperVerticalAngle;
nativeLayer.LowerVerticalAngle = -data.LowerVerticalAngle;
nativeLayer.Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer);
return true;
}
protected override bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerEquirect2KHR nativeLayer)
{
nativeLayer.Space = PXR_LayerUtility.GetCurrentAppSpace();
return base.ActiveNativeLayer(layerInfo, ref nativeLayer);
}
Vector2 CalculateScale(float centralHorizontalAngle, float upperVerticalAngle, float lowerVerticalAngle)
{
return new Vector2((2.0f * (float)Math.PI) / centralHorizontalAngle, (float)Math.PI / (upperVerticalAngle - lowerVerticalAngle));
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,300 @@
#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
{
/// <summary>
/// Manages communication of changes between an application and the UnityPXR_ lib for all
/// <see cref="Unity.XR.CompositionLayers.Layers.LayerData"/> objects.
/// </summary>
/// <remarks>
/// PXR_ providers or extensions that create custom composition layer types or that override how the built-in
/// layer types are handled, must implement the <see cref="ILayerProvider"/> interface and register instances of
/// these implementations with the <c>PXR_LayerProvider</c> via <see cref="RegisterLayerHandler(Type, PXR_LayerProvider.ILayerHandler)"/>.
/// </remarks>
public class PXR_LayerProvider : ILayerProvider, IDisposable
{
/// <summary>
/// An interface used by the <see cref="PXR_LayerProvider"/> to communicate layer data changes to
/// registered layer handlers.
/// </summary>
/// <remarks>
/// <c>ILayerHandler</c> instances must register themselves via
/// <see cref="PXR_LayerProvider.RegisterLayerHandler(Type, PXR_LayerProvider.ILayerHandler)"/>
/// to specify the <see cref="LayerData"/> type to handle.
/// If more than one object registers itself as a handler for a specific <see cref="LayerData"/>
/// type, the last registered handler is used.
///
/// The <see cref="PXR_CustomLayerHandler{T}"/> class provides a partial, base implementation of this interface that you can
/// use to create custom layer handlers.
/// </remarks>
public interface ILayerHandler
{
/// <summary>
/// Called by the <see cref="PXR_LayerProvider"/> during the Unity Update loop.
/// All implementations must call <see cref="PXR_LayerUtility.AddActiveLayersToEndFrame(void*,void*,int,int)"/> every frame
/// to add their native layer structs to the <c>endFrameInfo</c> struct inside the UnityPXR_ lib.
/// </summary>
public void OnUpdate();
/// <summary>
/// Called by the <see cref="PXR_LayerProvider"/> when a new <see cref="LayerData"/>
/// object of the type registered to this <c>ILayerHandler</c> instance has been created.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was just created.</param>
public void CreateLayer(CompositionLayerManager.LayerInfo layerInfo);
/// <summary>
/// Called by the <see cref="PXR_LayerProvider"/> when a <see cref="LayerData"/> object
/// of the type registered to this <c>ILayerHandler</c> instance has been destroyed or disabled.
/// </summary>
/// <param name="removedLayerId"> The instance id of the CompositionLayer component that was removed.</param>
public void RemoveLayer(int id);
/// <summary>
/// Called by the <see cref="PXR_LayerProvider"/> when a <see cref="LayerData"/> object
/// or any attached extension components have had a member modified.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// that was modified.</param>
public void ModifyLayer(CompositionLayerManager.LayerInfo layerInfo);
/// <summary>
/// Called every frame by the <see cref="PXR_LayerProvider"/> for all currently active <see cref="LayerData"/> objects
/// of the type registered to this <c>ILayerHandler</c> instance.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
/// being set to active.</param>
public void SetActiveLayer(CompositionLayerManager.LayerInfo layerInfo);
}
/// <summary>
/// Initializes and returns an instance of <c>PXR_LayerProvider</c>.
/// Initializes and registers all the default, built-in layer handlers.
/// </summary>
/// <remarks>
/// The <c>PXR_LayerProvider</c> is created and disposed by the <see cref="Management.XRLoader"/>.
/// You do not need to create an instance of <c>PXR_LayerProvider</c> yourself. Layer handlers
/// should only use the static methods and properties of this class
/// </remarks>
public PXR_LayerProvider() => InitializeAndRegisterBuiltInHandlers();
/// <summary>
/// Calls the methods in its invocation list when the <c>PXR_LayerProvider</c> has started and registered it's built-in layer handlers.
/// </summary>
/// <remarks>
/// You can use this event to wait for the <c>PXR_LayerProvider</c> to finish registering its built-in layer handlers
/// so that you can override them with your own custom layer handlers.
/// </remarks>
public static event Action Started;
/// <summary>
/// Calls the methods in its invocation list when the <c>PXR_LayerProvider</c> has stopped and is disposed.
/// </summary>
public static event Action Stopped;
/// <summary>
/// Reports whether the <c>PXR_LayerProvider</c> has already been created and started.
/// </summary>
public static bool isStarted { get; set; }
static Dictionary<Type, ILayerHandler> LayerHandlers = new Dictionary<Type, ILayerHandler>();
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");
/// <summary>
/// Registers a concrete <see cref="ILayerHandler"/> object as the handler for all layers of a specific
/// <see cref="LayerData"/> subclass.
/// </summary>
/// <remarks>
/// If more than one object registers itself as a handler for a specific <see cref="LayerData"/>
/// type, the last registered handler is used.
///
/// The <c>PXR_LayerProvider</c> invokes the registered layer handler's <see cref="ILayerHandler"/> methods
/// when any object of the associated <see cref="LayerData"/> type is updated in some way.
/// </remarks>
/// <param name="layerDataType">The <see cref="LayerData"/> subclass to handle.</param>
/// <param name="handler">The concrete <c>ILayerHandler</c> instance> to register.</param>
public static void RegisterLayerHandler(Type layerDataType, ILayerHandler handler)
{
if (handler == null)
{
LayerHandlers.Remove(layerDataType);
return;
}
LayerHandlers[layerDataType] = handler;
}
/// <summary>
/// Sets the layer provider state on first assignment to the <see cref="CompositionLayerManager" />.
/// </summary>
/// <param name="layers">The list of all currently known <see cref="CompositionLayer"/> instances, regardless of active state.</param>
public void SetInitialState(List<CompositionLayerManager.LayerInfo> layers)
{
UpdateLayers(layers, null, null, null);
}
/// <summary>
/// Called by the <see cref="CompositionLayerManager" /> to tell the instance of <see cref="ILayerProvider" /> about
/// the current state of layers it is managing.
/// </summary>
///
/// <param name="createdLayers">The list of layers that were just created. Any layer in
/// this list may be in the <paramref name="activeLayers" /> list if it is activated in the same frame.
/// Any layer in this list should not be in <paramref name="modifiedLayers" /> or <paramref name="removedLayers" />.
/// This list is ephemeral and cleared after each call.</param>
///
/// <param name="removedLayers">The list of layers that are no longer being managed. Any layer in
/// this list should not be in the <paramref name="createdLayers" />, <paramref name="modifiedLayers" />, or
/// <paramref name="activeLayers" /> lists.
/// This list is ephemeral and cleared after each call.</param>
///
/// <param name="modifiedLayers">The list of layers that have been recently modified. Any layer in
/// this list may also be in the <paramref name="activeLayers" /> list. Any layer in this list should not
/// be in <paramref name="createdLayers" /> or <paramref name="removedLayers" />.
/// This list is ephemeral and cleared after each call.</param>
///
/// <param name="activeLayers">The list of layers currently active within the scene.
/// Layers in this list may also be in the <paramref name="createdLayers" /> or <paramref name="modifiedLayers" /> lists
/// if they became active in the same frame.</param>
public void UpdateLayers(List<CompositionLayerManager.LayerInfo> createdLayers, List<int> removedLayers, List<CompositionLayerManager.LayerInfo> modifiedLayers, List<CompositionLayerManager.LayerInfo> 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();
}
}
/// <summary>
/// Used for cleanup and to call Dispose() on registered layer handlers.
/// </summary>
/// <remarks>This is called by the PXR_Loader class when StopInternal() is invoked.</remarks>
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

View File

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

View File

@@ -0,0 +1,420 @@
#if XR_COMPOSITION_LAYERS
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Services;
using UnityEngine;
using UnityEngine.Rendering;
using static Unity.XR.CompositionLayers.CompositionLayersRuntimeSettings;
namespace Unity.XR.PXR
{
/// <summary>
/// A general-purpose helper class for composition layer support.
/// </summary>
public static class PXR_LayerUtility
{
internal unsafe delegate void LayerCallbackDelegate(int layerId, XrCompositionLayerBaseHeader* layer);
private static Material textureM;
private static Material cubeM;
static Dictionary<UInt32, Texture> _textureMap = new Dictionary<UInt32, Texture>();
static Dictionary<ValueTuple<int, int>, Texture> _textureCache = new Dictionary<ValueTuple<int, int>, Texture>();
/// <summary>
/// Calls the methods in its invocation list when a swapchain is created on the graphics thread inside the UnityPXR_ lib.
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
/// <param name="swapchainHandle">The handle to the native swapchain that was just created.</param>
public unsafe delegate void SwapchainCallbackDelegate(int layerId, ulong swapchainHandle);
/// <summary>
/// Calls the methods in its invocation list when a stereo swapchain is created on the graphics thread inside the UnityPXR_ lib.
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
/// <param name="swapchainHandleLeft">The handle to one of the stereo swapchains that was just created.</param>
/// <param name="swapchainHandleRight">The handle to one of the stereo swapchains that was just created.</param>
public unsafe delegate void StereoSwapchainCallbackDelegate(int layerId, ulong swapchainHandleLeft, ulong swapchainHandleRight);
/// <summary>
/// Helper method used to gather the extension components attached to a CompositionLayer GameObject.
/// This method chains the native extension struct pointers of those extension components to initialize an PXR_ native object's Next pointer struct chain.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer.</param>
/// <param name="extensionTarget"> Represents what part of the composition layer to retrieve extensions for.</param>
/// <returns>A pointer to the head of an array of native extension objects that will be associated with a composition layer.</returns>
public static unsafe void* GetExtensionsChain(CompositionLayerManager.LayerInfo layerInfo, CompositionLayerExtension.ExtensionTarget extensionTarget)
{
void* extensionsChainHead = null;
void* extensionsChain = null;
foreach (var extension in layerInfo.Layer.Extensions)
{
// Skip extension if not enabled or not the intended target.
if (!extension.enabled || extension.Target != extensionTarget)
continue;
var extensionNativeStructPtr = extension.GetNativeStructPtr();
// Skip extension if no native pointer is provided.
if (extensionNativeStructPtr == null)
continue;
// Initialize pointer chain if head has not been set.
if (extensionsChainHead == null)
{
extensionsChainHead = extensionNativeStructPtr;
extensionsChain = extensionsChainHead;
}
// Chain pointer if head has been initialized.
else
{
((XrBaseInStructure*)extensionsChain)->Next = extensionNativeStructPtr;
extensionsChain = extensionNativeStructPtr;
}
}
return extensionsChainHead;
}
/// <summary>
/// Helper method used get the current app space for any native composition layer structs that may require an associated XrSpace.
/// </summary>
/// <returns>A handle to the current app space.</returns>
/// <remarks>Normally used when creating native composition layers.</remarks>
//public static ulong GetCurrentAppSpace() => Features.PXR_Feature.Internal_GetAppSpace(out ulong appSpaceId) ? appSpaceId : 0; // TODO
public static ulong GetCurrentAppSpace() => 0;
/// <summary>
/// Helper method used get the XR session handle for any native composition layer structs that may require an associated XrSession.
/// </summary>
/// <returns>A handle to the current xr session.</returns>
//public static ulong GetXRSession() => Features.PXR_Feature.Internal_GetXRSession(out ulong xrSessionHandle) ? xrSessionHandle : 0; // TODO
public static ulong GetXRSession() => 0;
/// <summary>
/// Create the <see cref="XrSwapchainCreateInfo"/> struct that is passed to PXR_ SDK to create a swapchain.
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
/// <param name="createInfo">The struct used to create the swapchain.</param>
/// <param name="isExternalSurface"> Optional parameter that can be used when an external surface will be used, like when using the Android Surface feature.</param>
/// <param name="callback"> Optional parameter that can be used if your composition layer needs to know the handle after swapchain creation.</param>
public static void CreateSwapchain(int layerId, XrSwapchainCreateInfo createInfo, bool isExternalSurface = false, SwapchainCallbackDelegate callback = null)
{
Pxr_CompositorLayersCreateSwapchain(layerId, createInfo, isExternalSurface, callback);
}
/// <summary>
/// Create the <see cref="XrSwapchainCreateInfo"/> struct that is passed to PXR_ SDK to create a swapchain for stereo projection, like Projection layer type.
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
/// <param name="createInfo">The struct used to create the swapchain.</param>
/// <param name="callback"> Optional parameter that can be used if your composition layer needs to know the handles after swapchain creation.</param>
public static void CreateStereoSwapchain(int layerId, XrSwapchainCreateInfo createInfo, StereoSwapchainCallbackDelegate callback = null)
{
Pxr_CompositorLayersCreateStereoSwapchain(layerId, createInfo, callback);
}
/// <summary>
/// Release swapchain according to the id provided.
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
public static void ReleaseSwapchain(int layerId)
{
Pxr_CompositorLayersReleaseSwapchain(layerId);
}
/// <summary>
/// Return swapchain supported color format.
/// </summary>
/// <returns>The color format the swapchains will be using.</returns>
public static Int64 GetDefaultColorFormat()
{
if (GraphicsDeviceType.Vulkan == SystemInfo.graphicsDeviceType)
{
return (long)PXR_CompositionLayer.ColorForamt.VK_FORMAT_R8G8B8A8_SRGB;
}
else
{
return (long)PXR_CompositionLayer.ColorForamt.GL_SRGB8_ALPHA8;
}
}
/// <summary>
/// Finds the render texture of the give texture id.
/// </summary>
/// <param name="texId">The id of the render texture to find.</param>
/// <returns>The render texture with the provided id or null if no render textrue with that id was found.</returns>
public static Texture FindRenderTexture(int id, UInt32 texId)
{
// texId will be 0 if swapchain has no images.
if (texId == 0)
return null;
if (!_textureMap.TryGetValue(texId, out var renderTexture))
{
var objs = Resources.FindObjectsOfTypeAll<RenderTexture>();
var name = $"XR Texture [{texId}]";
// for (int i = 0; i < objs.Length; i++)
// {
// Debug.Log($"FindRenderTexture 2 objs[i]={objs[i].name}");
// }
bool found = false;
foreach (var rt in objs)
{
if (rt.name == name)
{
renderTexture = rt;
_textureMap[texId] = rt;
found = true;
break;
}
}
}
return renderTexture;
}
/// <summary>
/// Finds the render texture of the layer id.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer.</param>
/// <returns>The render texture with the provided id or null if no render textrue with that id was found.</returns>
public static Texture FindRenderTexture(CompositionLayerManager.LayerInfo layerInfo)
{
UInt32 texId = Pxr_CompositorLayersCreateOrGetRenderTextureId(layerInfo.Id);
return FindRenderTexture(layerInfo.Id, texId);
}
public static Texture CreateExternalTexture(int id, int width, int height, bool isCube)
{
int imageIndex = 0;
PXR_Plugin.Render.UPxr_GetLayerNextImageIndexByRender(id, ref imageIndex);
var cacheKey = ValueTuple.Create(id, imageIndex);
if (_textureCache.TryGetValue(cacheKey, out var cachedTexture))
{
return cachedTexture;
}
IntPtr ptr = IntPtr.Zero;
PXR_Plugin.Render.UPxr_GetLayerImagePtr(id, (EyeType)0, imageIndex, ref ptr);
if (IntPtr.Zero == ptr)
{
Debug.LogError($"WriteToRenderTexture id={id}, _textureMap, imageIndex={imageIndex}, IntPtr.Zero == ptr");
return null;
}
Texture nativeTexture;
if (isCube)
{
nativeTexture = Cubemap.CreateExternalTexture(width, TextureFormat.RGBA32, false, ptr);
}
else
{
nativeTexture = Texture2D.CreateExternalTexture(width, height, TextureFormat.RGBA32, false, true, ptr);
}
if (nativeTexture == null)
{
Debug.LogError($"WriteToRenderTexture id={id}, _textureMap, imageIndex={imageIndex}, nativeTexture == null");
}
if (nativeTexture != null)
{
nativeTexture.name = $"{id}+{imageIndex}";
_textureCache[cacheKey] = nativeTexture;
}
Debug.Log($"WriteToRenderTexture id={id}, imageIndex={imageIndex}, cacheKey={cacheKey}, ptr={ptr}");
return nativeTexture;
}
/// <summary>
/// Handles transfering texture data to a render texture.
/// </summary>
/// <param name="texture">The source texture that will be written into the provided render texture.</param>
/// <param name="renderTexture">The render texture that will be written to.</param>
public static void WriteToRenderTexture(int id, Texture sourceTextures, Texture nativeTexture, bool isCube)
{
if (sourceTextures == null)
{
Debug.LogError($"WriteToRenderTexture sourceTextures == null!");
return;
}
nativeTexture = CreateExternalTexture(id, sourceTextures.width, sourceTextures.height, isCube);
if (nativeTexture == null)
{
Debug.LogError($"WriteToRenderTexture 11 id={id} nativeTexture == null");
return;
}
int eyeCount = 1;
for (int i = 0; i < eyeCount; i++)
{
if (isCube && null == sourceTextures as Cubemap)
{
Debug.LogError($"WriteToRenderTexture 11 id={id} isCube && null == sourceTextures as Cubemap");
return;
}
int faceCount = isCube ? 6:1;
for (int f = 0; f < faceCount; f++)
{
if (QualitySettings.activeColorSpace == ColorSpace.Gamma && sourceTextures != null)
{
Graphics.CopyTexture(sourceTextures, f, 0, nativeTexture, f, 0);
}
else
{
RenderTextureDescriptor rtDes = new RenderTextureDescriptor((int)sourceTextures.width, (int)sourceTextures.height, RenderTextureFormat.ARGB32, 0);
rtDes.msaaSamples = 1;
rtDes.useMipMap = true;
rtDes.autoGenerateMips = false;
rtDes.sRGB = true;
RenderTexture renderTexture = RenderTexture.GetTemporary(rtDes);
if (!renderTexture.IsCreated())
{
renderTexture.Create();
}
renderTexture.DiscardContents();
if (isCube)
{
if (cubeM == null)
{
Debug.Log($"WriteToRenderTexture id={id}, cubeM , f={f}, cubeM == null");
cubeM = new Material(Shader.Find("PXR_SDK/PXR_CubemapBlit"));
}
cubeM.SetInt("_d", f);
Graphics.Blit(sourceTextures, renderTexture, cubeM);
}
else
{
if (textureM == null)
{
Debug.Log($"WriteToRenderTexture id={id}, textureM, textureM == null");
textureM = new Material(Shader.Find("PXR_SDK/PXR_Texture2DBlit"));
}
textureM.mainTexture = renderTexture;
textureM.SetPass(0);
//textureM.SetInt("_premultiply", isPremultipliedAlpha ? 1 : 0);
Graphics.Blit(sourceTextures, renderTexture);
}
Graphics.CopyTexture(renderTexture, 0, 0, nativeTexture, f, 0);
RenderTexture.ReleaseTemporary(renderTexture);
}
}
}
}
/// <summary>
/// Query the correct XR Textures for rendering and blit the layer textures.
/// </summary>
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer.</param>
/// <param name="texture">The source texture that will be written into the provided render texture.</param>
/// <param name="renderTexture">The render texture that will be searched for and written to.
/// Will be null if no render texture can be found for the provided layerInfo object.</param>
/// <returns>True if a render texture was found and written to, false if the provided texture is null or if no render texture was found for the provided layerInfo object.</returns>
public static bool FindAndWriteToRenderTexture(CompositionLayerManager.LayerInfo layerInfo, Texture texture, out Texture renderTexture, bool isCube)
{
if (texture == null)
{
Debug.Log($"FindAndWriteToRenderTexture texture == null");
renderTexture = null;
return false;
}
renderTexture = FindRenderTexture(layerInfo);
WriteToRenderTexture(layerInfo.Id, texture, renderTexture, isCube);
return renderTexture != null;
}
/// <summary>
/// Add native layer structs to the <c>endFrameInfo</c> struct inside the UnityPXR_ lib - for custom layer type support
/// </summary>
/// <param name="layers">Pointer to the native array of currently active composition layers.</param>
/// <param name="orders">Pointer to the native array of order values for the currently active composition layers.</param>
/// <param name="count">Indicates the size of the layers and orders arrays.</param>
/// <param name="layerByteSize">Indicates the size in bytes of a single element of the given array of composition layers.</param>
/// <remarks>Layers sent must all be of the same type.Demonstrated in the PXR_CustomLayerHandler class.</remarks>
public static unsafe void AddActiveLayersToEndFrame(void* layers, void* orders, int count, int layerByteSize)
{
IntPtr ptrLayers = new IntPtr(layers);
IntPtr ptrOrders = new IntPtr(orders);
Pxr_CompositorLayersAddActiveLayers(layers, orders, count, layerByteSize);
}
/// <summary>
/// Return the Surface object for Android External Surface support (Android only).
/// </summary>
/// <param name="layerId">The instance id of the composition layer object.</param>
/// <returns>Pointer to the android surface object.</returns>
public static System.IntPtr GetLayerAndroidSurfaceObject(int layerId)
{
IntPtr surfaceObject = IntPtr.Zero;
if (Pxr_CompositorLayersGetLayerAndroidSurfaceObject(layerId, ref surfaceObject))
{
return surfaceObject;
}
return IntPtr.Zero;
}
/// <summary>
/// Sends an array of extensions to be attached to the native default compostion layer.
/// </summary>
/// <param name="extensions">Pointer to the array of extensions to attach to the default compostion layer.</param>
/// <remarks>Currently only called by the PXR_DefautLayer class.</remarks>
public static unsafe void SetDefaultSceneLayerExtensions(void* extensions)
{
// IntPtr ptr = new IntPtr(extensions);
// ext_composition_layers_SetDefaultSceneLayerExtensions(extensions);
}
/// <summary>
/// Sends what flags are to be added to the native default compostion layer.
/// </summary>
/// <param name="flags">Flags to be added to the native default compostion layer.</param>
/// <remarks>Currently only called by the PXR_DefautLayer class.</remarks>
public static unsafe void SetDefaultLayerFlags(XrCompositionLayerFlags flags)
{
// ext_composition_layers_SetDefaultSceneLayerFlags(flags);
}
const string LibraryName = "PxrPlatform";
[DllImport(LibraryName)]
internal static extern UInt32 Pxr_CompositorLayersCreateOrGetRenderTextureId(int id); // Down
[DllImport(LibraryName)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool Pxr_CompositorLayersCreateOrGetStereoRenderTextureIds(int id, out UInt32 leftId, out UInt32 rightId); // Down
[DllImport(LibraryName)]
internal static extern void Pxr_CompositorLayersCreateSwapchain(int id, XrSwapchainCreateInfo createInfo, [MarshalAs(UnmanagedType.I1)]bool isExternalSurface = false, SwapchainCallbackDelegate callback = null); // Down
[DllImport(LibraryName)]
internal static extern void Pxr_CompositorLayersCreateStereoSwapchain(int id, XrSwapchainCreateInfo createInfo, StereoSwapchainCallbackDelegate callback = null); // Down
[DllImport(LibraryName)]
internal static extern void Pxr_CompositorLayersReleaseSwapchain(int id); // Down
[DllImport(LibraryName)]
internal static extern unsafe void Pxr_CompositorLayersAddActiveLayers(void* layers, void* orders, int count, int size); // Down
[DllImport(LibraryName)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool Pxr_CompositorLayersGetLayerAndroidSurfaceObject(int layerId, ref IntPtr surfaceObject); // Down
[DllImport(LibraryName)]
internal static extern unsafe void ext_composition_layers_SetDefaultSceneLayerExtensions(void* extensions);
[DllImport(LibraryName)]
internal static extern void ext_composition_layers_SetDefaultSceneLayerFlags(XrCompositionLayerFlags flags);
}
}
#endif

View File

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

View File

@@ -0,0 +1,300 @@
#if XR_COMPOSITION_LAYERS
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;
using Unity.XR.CompositionLayers.Layers;
using Unity.XR.CompositionLayers.Services;
using Unity.XR.PXR;
using UnityEngine;
namespace Unity.XR.PXR
{
//Default PXR_ Composition Layer - Quad Layer support
internal class PXR_QuadLayer : PXR_CustomLayerHandler<XrCompositionLayerQuad>
{
protected override bool CreateSwapchain(CompositionLayerManager.LayerInfo layer, out SwapchainCreateInfo swapchainCreateInfo)
{
unsafe
{
var texturesExtension = layer.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
{
swapchainCreateInfo = default;
return false;
}
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture == null)
goto default;
var xrCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = PXR_LayerUtility.GetDefaultColorFormat(),
SampleCount = 1,
Width = (uint)texturesExtension.LeftTexture.width,
Height = (uint)texturesExtension.LeftTexture.height,
FaceCount = 1,
ArraySize = 1,
MipCount = (uint)texturesExtension.LeftTexture.mipmapCount,
};
swapchainCreateInfo = new SwapchainCreateInfo(xrCreateInfo, isExternalSurface: false);
return true;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
#if UNITY_ANDROID
var xrCreateInfo = new XrSwapchainCreateInfo()
{
Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Swapchain),
CreateFlags = 0,
UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
Format = 0,
SampleCount = 0,
Width = (uint)texturesExtension.Resolution.x,
Height = (uint)texturesExtension.Resolution.y,
FaceCount = 0,
ArraySize = 0,
MipCount = 0,
};
swapchainCreateInfo = new SwapchainCreateInfo(xrCreateInfo, isExternalSurface: true);
return true;
#else
goto default;
#endif
}
default:
swapchainCreateInfo = default;
return false;
}
}
}
protected override bool CreateNativeLayer(CompositionLayerManager.LayerInfo layer, SwapchainCreatedOutput swapchainOutput, out XrCompositionLayerQuad nativeLayer)
{
unsafe
{
var texturesExtension = layer.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
{
nativeLayer = default;
return false;
}
var data = layer.Layer.LayerData as QuadLayerData;
var transform = layer.Layer.GetComponent<Transform>();
int subImageWidth = 0;
int subImageHeight = 0;
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture != null)
{
subImageWidth = texturesExtension.LeftTexture.width;
subImageHeight = texturesExtension.LeftTexture.height;
}
break;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
subImageWidth = (int)texturesExtension.Resolution.x;
subImageHeight = (int)texturesExtension.Resolution.y;
break;
}
}
var correctedSize = texturesExtension.CropToAspect ?
FixAspectRatio(data, transform, subImageWidth, subImageHeight) :
data.GetScaledSize(transform.lossyScale);
nativeLayer = new XrCompositionLayerQuad()
{
Type = (uint)XrStructureType.XR_TYPE_COMPOSITION_LAYER_QUAD,
Next = PXR_LayerUtility.GetExtensionsChain(layer, CompositionLayerExtension.ExtensionTarget.Layer),
LayerFlags = data.BlendType == BlendType.Premultiply ? XrCompositionLayerFlags.SourceAlpha : XrCompositionLayerFlags.SourceAlpha | XrCompositionLayerFlags.UnPremultipliedAlpha,
Space = PXR_LayerUtility.GetCurrentAppSpace(),
EyeVisibility = 0,
SubImage = new XrSwapchainSubImage()
{
Swapchain = swapchainOutput.handle,
ImageRect = new XrRect2Di()
{
Offset = new XrOffset2Di() { X = 0, Y = 0 },
Extent = new XrExtent2Di()
{
Width = subImageWidth,
Height = subImageHeight
}
},
ImageArrayIndex = 0
},
Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation),
Size = new XrExtent2Df()
{
width = correctedSize.x,
height = correctedSize.y
}
};
return true;
}
}
protected override bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerQuad nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
return false;
var data = layerInfo.Layer.LayerData as QuadLayerData;
var transform = layerInfo.Layer.GetComponent<Transform>();
nativeLayer.Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
int subImageWidth = 0;
int subImageHeight = 0;
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture != null)
{
subImageWidth = texturesExtension.LeftTexture.width;
subImageHeight = texturesExtension.LeftTexture.height;
}
break;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
subImageWidth = (int)texturesExtension.Resolution.x;
subImageHeight = (int)texturesExtension.Resolution.y;
break;
}
}
nativeLayer.SubImage.ImageRect.Extent = new XrExtent2Di()
{
Width = subImageWidth,
Height = subImageHeight
};
var correctedSize = texturesExtension.CropToAspect ?
FixAspectRatio(data, transform, subImageWidth, subImageHeight) :
data.GetScaledSize(transform.lossyScale);
nativeLayer.Size = new XrExtent2Df()
{
width = correctedSize.x,
height = correctedSize.y
};
unsafe
{
nativeLayer.Next = PXR_LayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer);
}
return true;
}
protected override bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerQuad nativeLayer)
{
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
if (texturesExtension == null || texturesExtension.enabled == false)
return false;
var data = layerInfo.Layer.LayerData as QuadLayerData;
var transform = layerInfo.Layer.GetComponent<Transform>();
nativeLayer.Pose = new XrPosef(PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position, PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
nativeLayer.Space = PXR_LayerUtility.GetCurrentAppSpace();
if (texturesExtension.CustomRects)
{
int subImageWidth = 0;
int subImageHeight = 0;
switch (texturesExtension.sourceTexture)
{
case TexturesExtension.SourceTextureEnum.LocalTexture:
{
if (texturesExtension.LeftTexture != null)
{
subImageWidth = texturesExtension.LeftTexture.width;
subImageHeight = texturesExtension.LeftTexture.height;
}
break;
}
case TexturesExtension.SourceTextureEnum.AndroidSurface:
{
subImageWidth = (int)texturesExtension.Resolution.x;
subImageHeight = (int)texturesExtension.Resolution.y;
break;
}
}
nativeLayer.SubImage.ImageRect = new XrRect2Di()
{
Offset = new XrOffset2Di()
{
X = (int)(subImageWidth * texturesExtension.LeftEyeSourceRect.x),
Y = (int)(subImageHeight * texturesExtension.LeftEyeSourceRect.y)
},
Extent = new XrExtent2Di()
{
Width = (int)(subImageWidth * texturesExtension.LeftEyeSourceRect.width),
Height = (int)(subImageHeight * texturesExtension.LeftEyeSourceRect.height)
}
};
var currentPosition = PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).position;
var correctedSize = texturesExtension.CropToAspect ?
FixAspectRatio(data, transform, subImageWidth, subImageHeight) :
data.GetScaledSize(transform.lossyScale);
float transformedX = currentPosition.x + (((texturesExtension.LeftEyeDestinationRect.x + (0.5f * texturesExtension.LeftEyeDestinationRect.width) - 0.5f)) * correctedSize.x);
float transformedY = currentPosition.y + (((texturesExtension.LeftEyeDestinationRect.y + (0.5f * texturesExtension.LeftEyeDestinationRect.height) - 0.5f)) * (-1.0f * correctedSize.y));
nativeLayer.Pose = new XrPosef(new Vector3(transformedX, transformedY, currentPosition.z), PXR_Utility.ComputePoseToWorldSpace(transform, CompositionLayerManager.mainCameraCache).rotation);
nativeLayer.Size = new XrExtent2Df()
{
width = correctedSize.x * texturesExtension.LeftEyeDestinationRect.width,
height = correctedSize.y * texturesExtension.LeftEyeDestinationRect.height
};
}
return base.ActiveNativeLayer(layerInfo, ref nativeLayer);
}
static Vector2 FixAspectRatio(QuadLayerData data, Transform transform, int texWidth, int texHeight)
{
var requestedSize = data.GetScaledSize(transform.lossyScale);
float reqSizeRatio = (float)requestedSize.x / (float)requestedSize.y;
float texRatio = (float)texWidth / (float)texHeight;
if (reqSizeRatio > texRatio)
{
// too wide
requestedSize.x = requestedSize.y * texRatio;
}
else if (reqSizeRatio < texRatio)
{
// too narrow
requestedSize.y = requestedSize.x / texRatio;
}
return requestedSize;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,65 @@
using System.Runtime.InteropServices;
using UnityEngine;
namespace Unity.XR.PXR
{
/// <summary>
/// PXR_ Utility Class contains helper methods that any script can use.
/// </summary>
public static class PXR_Utility
{
/// <summary>
/// Computes the inverse of the given pose.
/// </summary>
private static Pose Inverse(Pose p)
{
Pose ret;
ret.rotation = Quaternion.Inverse(p.rotation);
ret.position = ret.rotation * -p.position;
return ret;
}
/// <summary>
/// Recalculate object position and rotation from tracking-space to world-space, for use cases like teleporting.
/// </summary>
/// <param name="t">original transform of the object in the scene, typically obtained by gameObject.transform</param>
/// <param name="camera">camera the calculation is based on, normally it is the main camera</param>
/// <returns>the recalculated pose <see cref="UnityEngine.Pose"/> in world-space.</returns>
public static Pose ComputePoseToWorldSpace(Transform t, Camera camera)
{
if (camera == null)
return default;
Transform cameraTransform = camera.transform;
Pose headPose = new Pose(cameraTransform.localPosition, cameraTransform.localRotation);
Pose camPose = new Pose(cameraTransform.position, cameraTransform.rotation);
Pose transformPose = new Pose(t.position, t.rotation);
Pose headSpacePose = transformPose.GetTransformedBy(Inverse(camPose));
return headSpacePose.GetTransformedBy(headPose);
}
/// <summary>
/// Returns if the current session is in the focused state.
/// See <a href="https://registry.khronos.org/PXR_/specs/1.0/html/xrspec.html#session-states">XR_SESSION_STATE_FOCUSED.</a> for reference.
/// </summary>
public static bool IsSessionFocused => Internal_IsSessionFocused();
/// <summary>
/// Returns the change of user presence, such as when the user has taken off or put on an XR headset.
/// If the system does not support user presence sensing, runtime assumes that the user is always present and IsUserPresent always returns True.
/// If the system supports the sensing of user presence, returns true when detected the presence of a user and returns false when detected the absence of a user.
/// See <a href="https://registry.khronos.org/PXR_/specs/1.0/html/xrspec.html#XR_EXT_user_presence">XR_EXT_user_presence.</a> for reference.
/// </summary>
public static bool IsUserPresent => Internal_GetUserPresence();
private const string LibraryName = "PxrPlatform";
[DllImport(LibraryName, EntryPoint = "NativeConfig_IsSessionFocused")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool Internal_IsSessionFocused();
[DllImport(LibraryName, EntryPoint = "NativeConfig_GetUserPresence")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool Internal_GetUserPresence();
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ebb628dede9d3e54ab6eb81df63d0495
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db96a9bfa8f934f8f8ca1cc2c403131c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public interface IPXR_PanelManager
{
public void Init();
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22ec8844704ed4d4b87cb33d0962fcc4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c33f4710ca73400aa4ead29cfe05d8c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,125 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.XR;
using System;
// using UnityEngine.InputSystem.XR;
using UnityEngine.XR.Interaction.Toolkit;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_DeviceManager : MonoBehaviour
{
public static PXR_DeviceManager Instance { get; private set; }
private InputDevice rightHandDevice;
private InputDevice leftHandDevice;
private XRController rightHandController;
private XRController leftHandController;
public Transform RightHand => rightHandController.transform;
public Transform LeftHand => leftHandController.transform;
public Action OnAButtonPress;
public Action OnBButtonPress;
public Action OnXButtonPress;
public Action OnYButtonPress;
public Action OnAButtonRelease;
public Action OnBButtonRelease;
public Action OnXButtonRelease;
public Action OnYButtonRelease;
public Action OnLeftGripButtonPress;
public Action OnLeftTriggerButtonPress;
public Action OnRightGripButtonPress;
public Action OnRightTriggerButtonPress;
public Action OnLeftGripButtonRelease;
public Action OnLeftTriggerButtonRelease;
public Action OnRightGripButtonRelease;
public Action OnRightTriggerButtonRelease;
private bool previousRightPrimaryButtonPress;
private bool previousLeftPrimaryButtonPress;
private bool previousRightSecondaryButtonPress;
private bool previousLeftSecondaryButtonPress;
private bool previousRightGripButtonPress;
private bool previousLeftGripButtonPress;
private bool previousRightTriggerButtonPress;
private bool previousLeftTriggerButtonPress;
private void Awake()
{
if (Instance != null)
{
Debug.LogError($"The singleton has multiple instances");
}
else
{
Destroy(Instance);
}
Instance = this;
}
void Start()
{
leftHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
XRController[] xrControllers = FindObjectsOfType<XRController>();
foreach (XRController controller in xrControllers){
if (controller.controllerNode == XRNode.LeftHand){
leftHandController = controller;
}
if (controller.controllerNode == XRNode.RightHand){
rightHandController = controller;
}
}
}
public void ToggleRightController(bool state){
rightHandController.modelParent.gameObject.SetActive(state);
}
private void ButtonHandler(bool currentState,ref bool previousState,in Action OnPressed,in Action OnReleased)
{
if (currentState && !previousState)
{
OnPressed?.Invoke();
}
if (!currentState && previousState)
{
OnReleased?.Invoke();
}
previousState = currentState;
}
void Update()
{
rightHandDevice.TryGetFeatureValue(CommonUsages.primaryButton, out bool isRightPrimaryButtonPress);
ButtonHandler(isRightPrimaryButtonPress,ref previousRightPrimaryButtonPress, OnAButtonPress, OnAButtonRelease);
rightHandDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out bool isRightSecondaryButtonPress);
ButtonHandler(isRightSecondaryButtonPress,ref previousRightSecondaryButtonPress, OnBButtonPress, OnBButtonRelease);
rightHandDevice.TryGetFeatureValue(CommonUsages.gripButton, out bool isRightGripButtonPress);
ButtonHandler(isRightGripButtonPress,ref previousRightGripButtonPress, OnRightGripButtonPress, OnRightGripButtonRelease);
rightHandDevice.TryGetFeatureValue(CommonUsages.triggerButton, out bool isRightTriggerButtonPress);
ButtonHandler(isRightTriggerButtonPress,ref previousRightTriggerButtonPress, OnRightTriggerButtonPress, OnRightTriggerButtonRelease);
leftHandDevice.TryGetFeatureValue(CommonUsages.primaryButton, out bool isLeftPrimaryButtonPress);
ButtonHandler(isLeftPrimaryButtonPress,ref previousLeftPrimaryButtonPress, OnXButtonPress, OnXButtonRelease);
leftHandDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out bool isLeftSecondaryButtonPress);
ButtonHandler(isLeftSecondaryButtonPress,ref previousLeftSecondaryButtonPress, OnYButtonPress, OnYButtonRelease);
leftHandDevice.TryGetFeatureValue(CommonUsages.gripButton, out bool isLeftGripButtonPress);
ButtonHandler(isLeftGripButtonPress,ref previousLeftGripButtonPress, OnLeftGripButtonPress, OnLeftGripButtonRelease);
leftHandDevice.TryGetFeatureValue(CommonUsages.triggerButton, out bool isLeftTriggerButtonPress);
ButtonHandler(isLeftTriggerButtonPress,ref previousLeftTriggerButtonPress, OnLeftTriggerButtonPress, OnLeftTriggerButtonRelease);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,42 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEditor;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_PicoDebuggerManager : MonoBehaviour
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void OnBeforeSceneLoadRuntimeMethod()
{
var config = Resources.Load<PXR_PicoDebuggerSO>("PXR_PicoDebuggerSO");
if(config.isOpen){
AddPrefab();
}
}
private static void AddPrefab()
{
GameObject prefab = Resources.Load<GameObject>("PXR_PICODebugger");
if (prefab != null)
{
Instantiate(prefab, Vector3.zero, Quaternion.identity);
}
else
{
Debug.LogError("Prefab not found in Resources folder.");
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1ab97bca604e54c99a2273f6e8533286
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,100 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
[CreateAssetMenu(fileName = "MainConfig", menuName = "ScriptableObjects / PXR_PicoDebuggerSO", order = 1)]
public class PXR_PicoDebuggerSO : ScriptableObject
{
private static PXR_PicoDebuggerSO _instance;
public static PXR_PicoDebuggerSO Instance
{
get
{
if (_instance == null)
{
GetAsset(out PXR_PicoDebuggerSO picoDebuggerSO, "PXR_PicoDebuggerSO");
_instance = picoDebuggerSO;
}
return _instance;
}
}
[Header("default")]
public bool isOpen;
public LauncherButton debuggerLauncherButton;
public StartPosiion startPosition;
[Header("console")]
[Range(500,1000)]public int maxInfoCount;
[Header("tools")]
public LauncherButton rulerClearButton;
internal static void GetAsset<T>(out T asset, string name) where T : PXR_PicoDebuggerSO
{
asset = null;
#if UNITY_EDITOR
string path = GetPath(name);
asset = AssetDatabase.LoadAssetAtPath(path, typeof(T)) as T;
if (asset == null )
{
asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, path);
}
#else
asset = Resources.Load<T>(name);
#endif
}
#if UNITY_EDITOR
internal static string GetPath(string name)
{
string resourcesPath = Path.Combine(Application.dataPath, "Resources");
if (!Directory.Exists(resourcesPath))
{
Directory.CreateDirectory(resourcesPath);
}
string assetPath = Path.GetRelativePath(Application.dataPath, Path.GetFullPath(Path.Combine(resourcesPath, $"{name}.asset")));
// Unity's AssetDatabase path requires a slash before "Assets"
return "Assets/" + assetPath.Replace('\\', '/');
}
public void AddToPreloadedAssets()
{
var preloadedAssets = PlayerSettings.GetPreloadedAssets().ToList();
if (!preloadedAssets.Contains(this))
{
preloadedAssets.Add(this);
PlayerSettings.SetPreloadedAssets(preloadedAssets.ToArray());
}
}
#endif
#if UNITY_EDITOR
public static PXR_PicoDebuggerSO GetSerializedObject(string path)
{
var config = AssetDatabase.LoadAssetAtPath<PXR_PicoDebuggerSO>(path);
if (config == null)
{
Debug.LogError("Failed to load PXR_PicoDebuggerSO at path: " + path);
}
return config;
}
#endif
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b0b5ff6f3ba0942d79f41538d7d76c76
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_CloseButton : MonoBehaviour, IPointerDownHandler
{
public UnityEvent onButtonCLick;
// Called when the button is selected
public void OnPointerDown(PointerEventData args)
{
onButtonCLick?.Invoke();
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,105 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_DefaultButton : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler
{
bool isButtonPress = false;
bool isButtonHover = false;
private float hoverSpeed = 0.8f;
[SerializeField] private Color defaultColor;
[SerializeField] private Color hoverColor;
[SerializeField] private GameObject panelGO;
[SerializeField] private GameObject[] panelList;
[SerializeField] private PXR_DefaultButton[] buttonList;
[SerializeField] private MeshRenderer bg;
[SerializeField] private MeshRenderer border;
[SerializeField] private Sprite sprite;
private float borderAlpha;
private void Start()
{
Reset();
}
private void OnValidate()
{
transform.GetChild(0).GetComponent<Image>().sprite = sprite;
}
// Called when the button is selected
public void OnPointerDown(PointerEventData eventData)
{
if (!isButtonPress)
{
border.material.color = hoverColor;
bg.material.color = defaultColor;
isButtonHover = false;
isButtonPress = true;
OpenPanel();
}
}
private void Update()
{
if (isButtonHover)
{
bg.material.color = Color.Lerp(bg.material.color, hoverColor, hoverSpeed * Time.deltaTime);
var borderColor = Color.Lerp(border.material.color, hoverColor, hoverSpeed * Time.deltaTime);
borderAlpha += hoverSpeed * Time.deltaTime;
borderColor.a = borderAlpha;
border.material.color = borderColor;
}
}
private void OpenPanel(){
for (var i = 0; i < panelList.Length; i++)
{
panelList[i].SetActive(false);
}
for (var i = 0; i<buttonList.Length; i++){
buttonList[i].Reset();
}
panelGO.SetActive(true);
if(panelGO.TryGetComponent(out IPXR_PanelManager manager)){
manager.Init();
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (!isButtonPress)
{
border.material.color = new Color(0, 0, 0, 0);
borderAlpha = 0f;
isButtonHover = true;
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (!isButtonPress)
{
isButtonHover = false;
border.material.color = new Color(0, 0, 0, 0);
bg.material.color = defaultColor;
}
}
public void Reset()
{
bg.material.color = defaultColor;
border.material.color = new Color(0, 0, 0, 0);
isButtonPress = false;
isButtonHover = false;
panelGO.SetActive(false);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,73 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_DragButton : MonoBehaviour, IBeginDragHandler, IDragHandler,IEndDragHandler
{
private Image image;
private Transform _camera;
public PXR_UIController uiController;
private Vector3 origin; // Center of a sphere
private float radius = 5f; // Radius of a sphere
public Transform container;
[SerializeField]private Color defaultColor;
[SerializeField]private Color hoverColor;
private void Start()
{
_camera = Camera.main.transform;
image = GetComponent<Image>();
}
private void UpdateTransformPosition(PointerEventData eventData)
{
// Gets the position and direction of the controller
Vector3 controllerPosition = eventData.pointerCurrentRaycast.worldPosition;
// Calculate the point at which the ray intersects the sphere
Vector3 sphereCenterToController = controllerPosition - origin;
Vector3 intersectionPoint = origin + sphereCenterToController.normalized * radius;
Vector3 intersectionDirection = (intersectionPoint - origin).normalized;
float angle = Vector3.Angle(intersectionDirection, Vector3.up);
if (angle < 45 || angle > 135)return;
var forward = container.position - _camera.position;
forward.y = 0;
image.color = Color.Lerp(image.color,hoverColor,Time.deltaTime);
container.forward = forward;
container.position = intersectionPoint;
}
public void OnBeginDrag(PointerEventData eventData)
{
if (eventData.pointerCurrentRaycast.gameObject != gameObject) return;
origin = uiController.origin;
radius = uiController.GetDistance();
// Update the position when you start dragging
UpdateTransformPosition(eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
if (eventData.pointerCurrentRaycast.gameObject != gameObject) return;
image.color = defaultColor;
}
public void OnDrag(PointerEventData eventData)
{
if (eventData.pointerCurrentRaycast.gameObject != gameObject) return;
// Update position while dragging
UpdateTransformPosition(eventData);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_FolderButton : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler
{
private Image image;
public GameObject content;
private bool isShowContent = false;
private float hoverSpeed = 0.5f;
[SerializeField] private Color defaultColor = new(184, 235, 255);
bool isButtonHover = false;
private void Start()
{
image = GetComponent<Image>();
image.color = defaultColor;
}
public void OnPointerDown(PointerEventData eventData)
{
// text.color = Color.red;
isShowContent = !isShowContent;
content.SetActive(isShowContent);
image.transform.Rotate(0, 0, 180);
LayoutRebuilder.ForceRebuildLayoutImmediate(content.transform.parent.gameObject.GetComponent<RectTransform>());
}
public void OnPointerEnter(PointerEventData eventData)
{
isButtonHover = true;
}
public void OnPointerExit(PointerEventData eventData)
{
isButtonHover = false;
image.color = defaultColor;
}
private void Update()
{
if (isButtonHover)
{
image.color = Color.Lerp(image.color, Color.white, hoverSpeed * Time.deltaTime);
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,35 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_LogButton : MonoBehaviour, IPointerDownHandler
{
public LogType type;
[SerializeField]private Color defaultColor;
[SerializeField]private PXR_LogManager logManager;
[SerializeField]private Image icon;
[SerializeField]private Text text;
private bool isFilter = true;
public void OnPointerDown(PointerEventData eventData)
{
isFilter = !isFilter;
logManager.FilterLogs(type,isFilter);
icon.color = isFilter?defaultColor:Color.gray;
text.color = isFilter?defaultColor:Color.gray;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_ToolButton : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler
{
private bool isButtonPress = false;
private bool isButtonHover = false;
// private float hoverSpeed = 0.8f;
[SerializeField] private Color defaultColor;
[SerializeField] private Color hoverColor;
[SerializeField] private Image icon;
public UnityEvent onButtonPressed;
public void OnPointerDown(PointerEventData eventData)
{
if (!isButtonPress)
{
onButtonPressed?.Invoke();
icon.color = hoverColor;
isButtonHover = false;
isButtonPress = true;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (!isButtonPress)
{
icon.color = hoverColor;
isButtonHover = true;
}
}
public void Reset(){
icon.color = defaultColor;
isButtonHover = false;
isButtonPress = false;
}
public void OnPointerExit(PointerEventData eventData)
{
if (!isButtonPress)
{
isButtonHover = false;
icon.color = defaultColor;
}
}
public void CreateTool(){
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f7b0a5fb3a9ea4428b7d1096863a9bb2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
namespace Unity.XR.PXR.Debugger
{
public class Ball : MonoBehaviour
{
void Update()
{
transform.position = Vector3.up*Mathf.Sin(Time.time)+Vector3.forward*0.5f;
}
}
}

View File

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

View File

@@ -0,0 +1,170 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_Tool_Ruler : MonoBehaviour
{
// Start is called before the first frame update
[SerializeField] Material mal;
[SerializeField] private GameObject rulerPrefab;
[SerializeField] private Transform exitPosition;
private Vector3 startPosition;
private float size = 0.02f;
private bool isStart = false;
private GameObject ruler;
private Text text;
private Transform container;
private List<GameObject> rulers = new();
void Start()
{
PXR_DeviceManager.Instance.OnRightGripButtonPress += StartMeasure;
PXR_DeviceManager.Instance.OnRightGripButtonRelease += StopMeasure;
var config = Resources.Load<PXR_PicoDebuggerSO>("PXR_PicoDebuggerSO");
if(config.isOpen)
{
switch (config.rulerClearButton)
{
case LauncherButton.PressA:
PXR_DeviceManager.Instance.OnAButtonPress += OnClearButtonPress;
break;
case LauncherButton.PressB:
PXR_DeviceManager.Instance.OnBButtonPress += OnClearButtonPress;
break;
case LauncherButton.PressX:
PXR_DeviceManager.Instance.OnXButtonPress += OnClearButtonPress;
break;
case LauncherButton.PressY:
PXR_DeviceManager.Instance.OnYButtonPress += OnClearButtonPress;
break;
default:
break;
}
}
}
void Update()
{
if (isStart)
{
GenerateRoundedRectMesh();
}
}
void OnDestroy() {
PXR_DeviceManager.Instance.OnRightGripButtonPress -= StartMeasure;
PXR_DeviceManager.Instance.OnRightGripButtonRelease -= StopMeasure;
var config = Resources.Load<PXR_PicoDebuggerSO>("PXR_PicoDebuggerSO");
if(config.isOpen)
{
switch (config.rulerClearButton)
{
case LauncherButton.PressA:
PXR_DeviceManager.Instance.OnAButtonPress -= OnClearButtonPress;
break;
case LauncherButton.PressB:
PXR_DeviceManager.Instance.OnBButtonPress -= OnClearButtonPress;
break;
case LauncherButton.PressX:
PXR_DeviceManager.Instance.OnXButtonPress -= OnClearButtonPress;
break;
case LauncherButton.PressY:
PXR_DeviceManager.Instance.OnYButtonPress -= OnClearButtonPress;
break;
default:
break;
}
}
}
private void StartMeasure()
{
startPosition = exitPosition.position;
ruler = Instantiate(rulerPrefab);
text = ruler.GetComponentInChildren<Text>();
container = ruler.transform.Find("Container");
ruler.SetActive(true);
isStart = true;
rulers.Add(ruler);
}
private void StopMeasure()
{
isStart = false;
}
private void OnClearButtonPress(){
StopMeasure();
for (var i = 0; i < rulers.Count; i++)
{
Destroy(rulers[i]);
}
}
private void GenerateRoundedRectMesh()
{
var meshFilter = ruler.GetComponent<MeshFilter>();
meshFilter.GetComponent<MeshRenderer>().material = mal;
Mesh mesh = new();
meshFilter.mesh = mesh;
List<Vector3> vertices = new();
List<Vector2> uvs = new();
List<int> triangles = new();
var dir = exitPosition.position-startPosition;
var p0 = startPosition + exitPosition.forward * size;
var p2 = startPosition - exitPosition.forward * size;
var p1 = exitPosition.position + exitPosition.forward * size;
var p3 = exitPosition.position - exitPosition.forward * size;
vertices.Add(p0);
uvs.Add(new Vector2(0, 0));
vertices.Add(p2);
uvs.Add(new Vector2(0, 1));
triangles.Add(0);
triangles.Add(2);
triangles.Add(1);
triangles.Add(0);
triangles.Add(1);
triangles.Add(2);
vertices.Add(p1);
uvs.Add(new Vector2(1, 0));
vertices.Add(p3);
uvs.Add(new Vector2(1, 1));
triangles.Add(1);
triangles.Add(2);
triangles.Add(3);
triangles.Add(2);
triangles.Add(1);
triangles.Add(3);
text.text = string.Format("{0:0.000}", dir.magnitude);
mesh.SetVertices(vertices);
mesh.SetUVs(0,uvs);
mesh.SetIndices(triangles, MeshTopology.Triangles, 0);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
var normal = Vector3.Cross(p2 - p0, p1 - p0);
container.transform.position = startPosition+ dir*0.5f +(exitPosition.forward - normal) * size;
container.transform.forward = normal;
meshFilter.GetComponent<MeshRenderer>().material.SetFloat("_MeshLength", dir.magnitude);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Collections;
using UnityEngine;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_Tool_TimerController : MonoBehaviour
{
private readonly float delayTime = 0.17f;
[SerializeField] private Animator anim;
private bool isTurnOn = false;
private bool isLock = true;
void Start()
{
PXR_DeviceManager.Instance.OnRightGripButtonPress += CutDown;
StartCoroutine(Delay(Open));
}
void OnDestroy()
{
PXR_DeviceManager.Instance.OnRightGripButtonPress -= CutDown;
}
private void CutDown()
{
if (isLock) return;
isTurnOn = !isTurnOn;
anim.SetBool("TurnOn", isTurnOn);
StartCoroutine(Delay(Open));
if (isTurnOn)
{
StartCoroutine(Delay(TimePause));
}
else
{
Time.timeScale = 1f;
}
isLock = true;
}
private IEnumerator Delay(Action action)
{
yield return new WaitForSeconds(delayTime);
action();
}
private void Open()
{
isLock = false;
}
private void TimePause()
{
Time.timeScale = 0f;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10fdeff64c0134bbe95d1939a54eea37
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d08d4a0636fd64c698e3b13b89847379
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_UIController : MonoBehaviour
{
public static PXR_UIController Instance { get; private set; }
public PXR_PicoDebuggerSO config;
[HideInInspector] public Vector3 origin;
private Transform _camera;
private float distance;
private StartPosiion state;
public void Awake()
{
if (config == null)
{
config = Resources.Load<PXR_PicoDebuggerSO>("PXR_PicoDebuggerSO");
}
if (Instance == null)
{
Instance = this;
}
Init();
}
private void Init()
{
_camera = Camera.main.transform;
state = config.startPosition;
distance = GetDistance();
}
public float GetDistance()
{
return state switch
{
StartPosiion.Far => 3f,
StartPosiion.Medium => 2f,
StartPosiion.Near => 1f,
_ => 2f,
};
}
private void OnEnable()
{
ResetTransform();
}
// Update is called once per frame
private void ResetTransform()
{
origin = _camera.position;
transform.position = origin + distance * _camera.transform.forward ;
transform.forward = transform.position - origin;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,60 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_UIManager : MonoBehaviour
{
public PXR_PicoDebuggerSO config;
public PXR_UIController uiController;
private GameObject _controller = null;
private void Start()
{
config = Resources.Load<PXR_PicoDebuggerSO>("PXR_PicoDebuggerSO");
uiController = Resources.Load<GameObject>("PXR_DebuggerPanel").GetComponent<PXR_UIController>();
if(config.isOpen)
{
switch (config.debuggerLauncherButton)
{
case LauncherButton.PressA:
PXR_DeviceManager.Instance.OnAButtonPress += OnStartButtonPress;
break;
case LauncherButton.PressB:
PXR_DeviceManager.Instance.OnBButtonPress += OnStartButtonPress;
break;
case LauncherButton.PressX:
PXR_DeviceManager.Instance.OnXButtonPress += OnStartButtonPress;
break;
case LauncherButton.PressY:
PXR_DeviceManager.Instance.OnYButtonPress += OnStartButtonPress;
break;
default:
break;
}
}
}
private void OnStartButtonPress(){
ToggleController();
}
private void ToggleController(){
if(_controller == null){
_controller = Instantiate(uiController.gameObject);
}else{
_controller.SetActive(!_controller.gameObject.activeSelf);
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8f68a863322194d27a20f7360a9deb30
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_InspectorItem : MonoBehaviour, IPointerDownHandler
{
public Text text;
private bool isShowChildren = false;
private bool hasChild = false;
private string icon => hasChild?(isShowChildren?"- ":"+ "):"";
private string nodeName;
private GameObject target;
public void SetTitle(){
text.text = icon + nodeName;
}
public void Init(Transform item)
{
target = item.gameObject;
nodeName = item.name;
if(item.childCount > 0){
hasChild = true;
TraverseChild(item);
}
SetTitle();
}
public void AddItem(Transform item)
{
var go = Instantiate(PXR_InspectorManager.Instance.inspectItem, transform);
if (go.TryGetComponent(out PXR_InspectorItem inspectItem))
{
inspectItem.Init(item);
inspectItem.gameObject.SetActive(false);
}
}
public void TraverseChild(Transform current)
{
for (int i = 0; i < current.childCount; i++)
{
// Debug.Log($"TraverseChild: {current.GetChild(i).name}");
AddItem(current.GetChild(i));
}
}
public void OnPointerDown(PointerEventData eventData)
{
isShowChildren = !isShowChildren;
// LayoutRebuilder.ForceRebuildLayoutImmediate(gameObject.GetComponent<RectTransform>());
for (int i = 0; i < transform.childCount; i++)
{
// Debug.Log($"TraverseChild: {transform.GetChild(i).name}");
transform.GetChild(i).gameObject.SetActive(isShowChildren);
LayoutRebuilder.ForceRebuildLayoutImmediate(transform.GetChild(i).GetComponent<RectTransform>());
}
var root = transform;
while(root.TryGetComponent(out PXR_InspectorItem _)){
LayoutRebuilder.ForceRebuildLayoutImmediate(root.GetComponent<RectTransform>());
root = root.parent;
}
SetTitle();
PXR_InspectorManager.Instance.SetTransformInfo(target);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,90 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_InspectorManager : MonoBehaviour, IPXR_PanelManager
{
public static PXR_InspectorManager Instance;
private void Awake(){
if(Instance == null){
Instance = this;
}
}
public GameObject inspectItem;
public Transform content;
public Text positionText;
public Text rotationText;
public Text scaleText;
public GameObject transformInfoNode;
private Transform target;
void Update(){
ShowTransformInfo();
}
private void ClearAllChildren(){
int childCount = content.childCount;
for (int i = childCount - 1; i >= 0; i--)
{
DestroyImmediate(content.GetChild(i).gameObject);
}
}
public void CreateInspector()
{
GenerateInspectorTree();
}
public void Init(){
CreateInspector();
}
public void Reset(){
for (int i = 0; i < content.childCount; i++)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(content.GetChild(i).GetComponent<RectTransform>());
}
}
public void SetTransformInfo(GameObject target){
this.target = target.transform;
transformInfoNode.SetActive(true);
ShowTransformInfo();
}
public void Refresh(){
ClearAllChildren();
GenerateInspectorTree();
}
private void GenerateInspectorTree(){
GameObject[] rootObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
// 遍历所有根GameObject
foreach (GameObject obj in rootObjects)
{
if(!obj.TryGetComponent<PXR_UIController>(out _) && !obj.TryGetComponent<PXR_UIManager>(out _) && obj.activeSelf){
var go = Instantiate(inspectItem, content);
if(go.TryGetComponent(out PXR_InspectorItem item)){
item.Init(obj.transform);
}
}
}
Reset();
}
private void ShowTransformInfo(){
if(target != null){
positionText.text = $"x:{target.position.x} y:{target.position.y} z:{target.position.z}";
rotationText.text = $"x:{target.eulerAngles.x} y:{target.eulerAngles.y} z:{target.eulerAngles.z} ";
scaleText.text = $"x:{target.localScale.x} y:{target.localScale.y} z:{target.localScale.z}";
}else{
transformInfoNode.SetActive(false);
Refresh();
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4e6248719bac74cbd9b183852eea9d1b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,124 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_LogManager : MonoBehaviour, IPXR_PanelManager
{
public List<GameObject> infoList = new();
public List<GameObject> warningList = new();
public List<GameObject> errorList = new();
public GameObject errorMessage;
public GameObject warningMessage;
public GameObject infoMessage;
public Text infoText;
public Text warningText;
public Text errorText;
public Transform messageContainer;
private int ListCount => infoList.Count + warningList.Count + errorList.Count;
private void AddMessage(string title, string content, LogType type)
{
switch (type)
{
case LogType.Error:
CreateMessage(title, content, type, errorList, errorMessage);
break;
case LogType.Assert:
break;
case LogType.Warning:
CreateMessage(title, content, type, warningList, warningMessage);
break;
case LogType.Log:
CreateMessage(title, content, type, infoList, infoMessage);
break;
case LogType.Exception:
break;
}
RecaculateLogCount();
}
private void CreateMessage(string title, string content, in LogType type, in List<GameObject> list, in GameObject template)
{
var msg = Instantiate(template, messageContainer).GetComponent<PXR_MessageController>();
msg.Init(title, content);
list.Add(msg.gameObject);
}
private void RecaculateLogCount()
{
infoText.text = infoList.Count.ToString();
warningText.text = warningList.Count.ToString();
errorText.text = errorList.Count.ToString();
}
public void FilterLogs(LogType type, bool isFilter)
{
switch (type)
{
case LogType.Error:
ToggleLogs(errorList, isFilter);
break;
case LogType.Assert:
break;
case LogType.Warning:
ToggleLogs(warningList, isFilter);
break;
case LogType.Log:
ToggleLogs(infoList, isFilter);
break;
case LogType.Exception:
break;
}
}
private void ToggleLogs(in List<GameObject> list, bool status)
{
foreach (var item in list)
{
item.SetActive(status);
}
}
void Start()
{
Application.logMessageReceived += OnLogMessageReceived;
}
private void OnLogMessageReceived(string logString, string stackTrace, LogType type)
{
if (PXR_UIController.Instance.config.maxInfoCount > ListCount)
{
AddMessage(logString, stackTrace, type);
}
}
void OnEnable()
{
foreach (var item in infoList)
{
item.GetComponent<PXR_MessageController>().Reset();
}
foreach (var item in warningList)
{
item.GetComponent<PXR_MessageController>().Reset();
}
foreach (var item in errorList)
{
item.GetComponent<PXR_MessageController>().Reset();
}
}
public void Init(){
}
void OnDestroy()
{
Application.logMessageReceived -= OnLogMessageReceived;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,59 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_MessageController : MonoBehaviour
{
// Start is called before the first frame update
public Text title;
public Text content;
private readonly string widthMark = "------------------------------------------------------------------";
private readonly int maxLength = 47;
public void Init(string title, string content)
{
string timestamp = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string finalTitle = $"{timestamp}: {title}";
TextGenerator generator = new();
var settings = this.title.GetGenerationSettings(this.title.gameObject.GetComponent<RectTransform>().rect.size);
var targetWidth = generator.GetPreferredWidth(widthMark, settings);
var currentWidth = generator.GetPreferredWidth(finalTitle, settings);
if (targetWidth < currentWidth)
{
finalTitle = title[..(maxLength - 3)];
currentWidth = generator.GetPreferredWidth(finalTitle, settings);
while (targetWidth < currentWidth)
{
finalTitle = title[..(title.Length - 1)];
currentWidth = generator.GetPreferredWidth(finalTitle, settings);
}
finalTitle += "...";
}
this.title.text = finalTitle;
this.content.text = $"{title}\n{content}";
Reset();
}
public void Reset()
{
LayoutRebuilder.ForceRebuildLayoutImmediate(gameObject.GetComponent<RectTransform>());
}
public void ToggleContent()
{
content.gameObject.SetActive(!content.gameObject.activeSelf);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_BGWithTouch : MonoBehaviour, IPointerMoveHandler, IPointerEnterHandler, IPointerExitHandler
{
private Material material;
private Vector4 v;
private void Start()
{
var rect = GetComponent<RectTransform>().rect;
material = new Material(GetComponent<Image>().material);
v.z = rect.width;
v.w = rect.height;
material.SetVector("_TouchPos",v);
GetComponent<Image>().material = material;
}
public void OnPointerDown(PointerEventData eventData)
{
}
private void Update()
{
}
public void OnPointerEnter(PointerEventData eventData)
{
}
public void OnPointerExit(PointerEventData eventData)
{
}
public void OnPointerMove(PointerEventData eventData)
{
Vector3 offset = eventData.pointerCurrentRaycast.worldPosition-transform.position;
v.x= offset.x/v.z;
v.y= offset.y/v.w;
material.SetVector("_TouchPos", v);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,33 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_DebuggerConst{
public static string sdkPackageName = "Packages/com.unity.xr.picoxr/";
public static string sdkRootName = "com.unity.xr.picoxr/";
}
public enum LauncherButton
{
PressA,
PressB,
PressX,
PressY,
}
public enum StartPosiion
{
Far,
Near ,
Medium,
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 680b341d8fe6a4b7582f09429fefc6ef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
public class PXR_ToolManager : MonoBehaviour
{
private GameObject currentTool;
public PXR_ToolButton[] toolButtons;
public void CreateTool(GameObject tool){
ResetButtons();
if(currentTool != null){
Destroy(currentTool);
}
currentTool = Instantiate(tool,PXR_DeviceManager.Instance.RightHand);
PXR_DeviceManager.Instance.ToggleRightController(false);
}
private void ResetButtons(){
foreach (var button in toolButtons){
button.Reset();
}
PXR_DeviceManager.Instance.ToggleRightController(true);
}
public void DeleteTool(){
ResetButtons();
Destroy(currentTool);
currentTool = null;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 992f1fd0351f3469cb00e97521173d91
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
namespace Unity.XR.PXR.Debugger
{
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class RoundedRectMesh : MonoBehaviour
{
[SerializeField]public float width = 1f;
[SerializeField]public float height = 1f;
[SerializeField]public float depth = 1f;
[SerializeField]public float cornerRadius = 0.2f;
[SerializeField]public bool[] corner = { true, true, true, true };
[SerializeField]public int cornerSegments = 10; // The number of subdivisions of rounded corners
[SerializeField]public string saveName = "CustomMesh"; // Customize the save name
private MeshFilter meshFilter;
private bool isInit = false;
void OnValidate()
{
Init();
GenerateRoundedRectMesh();
}
private void Init(){
if(!isInit){
meshFilter = GetComponent<MeshFilter>();
isInit = true;
}
}
public static List<Vector3> CreateRoundedRectPath(Vector3 center, float width, float height, float radius, bool[] corners, int cornerSegments)
{
List<Vector3> path = new();
var halfWidth = width *0.5f;
var halfHeight = height *0.5f;
// Check whether the radius of the fillet is reasonable
radius = Mathf.Min(radius, width *0.5f, height *0.5f);
// Define the fillet subdivision Angle
float angleStep = 90f / (float)cornerSegments;
Vector2[] cornerCentersOffset = new Vector2[]
{
new(-1,1), // 左上 Left Top
new (1, 1), // 右上 Right Top
new (1, -1), // 右下 Right Bottom
new (-1, -1) // 左下 Left Bottom
};
// Generate the path of the rounded rectangle
for (int i = 0; i < 4; i++)
{
bool isCorner = corners[i];
var delta = isCorner ? radius : 0;
Vector3 currentCornerCenter = center + new Vector3((halfWidth - delta) * cornerCentersOffset[i].x, (halfHeight - delta) * cornerCentersOffset[i].y, 0);
if (isCorner)
{
// Add arcs
for (int j = 0; j <= cornerSegments; j++)
{
float angle = (i * 90 + angleStep * j) * Mathf.Deg2Rad;
path.Add(currentCornerCenter + new Vector3(-Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0));
}
}
else
{
// Add a right Angle
path.Add(currentCornerCenter);
}
}
return path;
}
private void GenerateRoundedRectMesh()
{
Mesh mesh = new();
meshFilter.mesh = mesh;
cornerRadius = Mathf.Clamp(cornerRadius, 0, Mathf.Min(width, height) *0.5f);
List<Vector3> path = CreateRoundedRectPath(transform.position, width, height, cornerRadius, corner, cornerSegments);
List<Vector3> vertices = new();
List<int> triangles = new();
var count = path.Count;
var doubleCount = count * 2;
var firstIndex = 0;
for (var j = 0; j < count; j++)
{
vertices.Add(path[j]);
vertices.Add(path[j] + Vector3.forward * depth);
triangles.Add(firstIndex);
triangles.Add((firstIndex + 2) % doubleCount );
triangles.Add(doubleCount);
triangles.Add((firstIndex + 1) % doubleCount);
triangles.Add(doubleCount + 1);
triangles.Add((firstIndex + 3) % doubleCount );
firstIndex += 2;
}
vertices.Add(transform.position);
vertices.Add(transform.position + Vector3.forward * depth);
var currentCount = vertices.Count;
firstIndex = 0;
for (var i = 0; i < count; i++)
{
vertices.Add(path[i]);
vertices.Add(path[i] + Vector3.forward * depth);
triangles.Add(firstIndex + currentCount);
triangles.Add((firstIndex + 1) % doubleCount + currentCount);
triangles.Add((firstIndex + 3) % doubleCount + currentCount);
triangles.Add(firstIndex + currentCount);
triangles.Add((firstIndex + 3) % doubleCount + currentCount);
triangles.Add((firstIndex + 2) % doubleCount + currentCount);
firstIndex += 2;
}
mesh.SetVertices(vertices);
mesh.SetIndices(triangles, MeshTopology.Triangles, 0);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f15fcfc3734242f4c84983e6956fd7e5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,252 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if UNITY_INPUT_SYSTEM
using UnityEngine.Scripting;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.XR;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
namespace Unity.XR.PXR.Input
{
/// <summary>
/// A PICO Headset
/// </summary>
[Preserve]
[InputControlLayout(displayName = "PICO HMD")]
public class PXR_HMD : XRHMD
{
[Preserve]
[InputControl]
public ButtonControl userPresence { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "devicetrackingstate" })]
public new IntegerControl trackingState { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "deviceistracked" })]
public new ButtonControl isTracked { get; private set; }
[Preserve]
[InputControl]
public new Vector3Control devicePosition { get; private set; }
[Preserve]
[InputControl]
public new QuaternionControl deviceRotation { get; private set; }
[Preserve]
[InputControl]
public Vector3Control deviceVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control deviceAngularVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control deviceAcceleration { get; private set; }
[Preserve]
[InputControl]
public Vector3Control deviceAngularAcceleration { get; private set; }
[Preserve]
[InputControl]
public new Vector3Control leftEyePosition { get; private set; }
[Preserve]
[InputControl]
public new QuaternionControl leftEyeRotation { get; private set; }
[Preserve]
[InputControl]
public Vector3Control leftEyeVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control leftEyeAngularVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control leftEyeAcceleration { get; private set; }
[Preserve]
[InputControl]
public Vector3Control leftEyeAngularAcceleration { get; private set; }
[Preserve]
[InputControl]
public new Vector3Control rightEyePosition { get; private set; }
[Preserve]
[InputControl]
public new QuaternionControl rightEyeRotation { get; private set; }
[Preserve]
[InputControl]
public Vector3Control rightEyeVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control rightEyeAngularVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control rightEyeAcceleration { get; private set; }
[Preserve]
[InputControl]
public Vector3Control rightEyeAngularAcceleration { get; private set; }
[Preserve]
[InputControl]
public new Vector3Control centerEyePosition { get; private set; }
[Preserve]
[InputControl]
public new QuaternionControl centerEyeRotation { get; private set; }
[Preserve]
[InputControl]
public Vector3Control centerEyeVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control centerEyeAngularVelocity { get; private set; }
[Preserve]
[InputControl]
public Vector3Control centerEyeAcceleration { get; private set; }
[Preserve]
[InputControl]
public Vector3Control centerEyeAngularAcceleration { get; private set; }
protected override void FinishSetup()
{
base.FinishSetup();
userPresence = GetChildControl<ButtonControl>("userPresence");
trackingState = GetChildControl<IntegerControl>("trackingState");
isTracked = GetChildControl<ButtonControl>("isTracked");
devicePosition = GetChildControl<Vector3Control>("devicePosition");
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
deviceAngularAcceleration = GetChildControl<Vector3Control>("deviceAngularAcceleration");
leftEyePosition = GetChildControl<Vector3Control>("leftEyePosition");
leftEyeRotation = GetChildControl<QuaternionControl>("leftEyeRotation");
leftEyeVelocity = GetChildControl<Vector3Control>("leftEyeVelocity");
leftEyeAngularVelocity = GetChildControl<Vector3Control>("leftEyeAngularVelocity");
leftEyeAcceleration = GetChildControl<Vector3Control>("leftEyeAcceleration");
leftEyeAngularAcceleration = GetChildControl<Vector3Control>("leftEyeAngularAcceleration");
rightEyePosition = GetChildControl<Vector3Control>("rightEyePosition");
rightEyeRotation = GetChildControl<QuaternionControl>("rightEyeRotation");
rightEyeVelocity = GetChildControl<Vector3Control>("rightEyeVelocity");
rightEyeAngularVelocity = GetChildControl<Vector3Control>("rightEyeAngularVelocity");
rightEyeAcceleration = GetChildControl<Vector3Control>("rightEyeAcceleration");
rightEyeAngularAcceleration = GetChildControl<Vector3Control>("rightEyeAngularAcceleration");
centerEyePosition = GetChildControl<Vector3Control>("centerEyePosition");
centerEyeRotation = GetChildControl<QuaternionControl>("centerEyeRotation");
centerEyeVelocity = GetChildControl<Vector3Control>("centerEyeVelocity");
centerEyeAngularVelocity = GetChildControl<Vector3Control>("centerEyeAngularVelocity");
centerEyeAcceleration = GetChildControl<Vector3Control>("centerEyeAcceleration");
centerEyeAngularAcceleration = GetChildControl<Vector3Control>("centerEyeAngularAcceleration");
}
}
/// <summary>
/// A PICO Controller
/// </summary>
[Preserve]
[InputControlLayout(displayName = "PICO Controller", commonUsages = new[] { "LeftHand", "RightHand" })]
public class PXR_Controller : XRControllerWithRumble
{
[Preserve]
[InputControl(aliases = new[] { "Primary2DAxis", "Thumbstick" })]
public Vector2Control thumbstick { get; private set; }
[Preserve]
[InputControl]
public AxisControl trigger { get; private set; }
[Preserve]
[InputControl]
public AxisControl grip { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "A", "X" })]
public ButtonControl primaryButton { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "B", "Y" })]
public ButtonControl secondaryButton { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "GripButton", "GripPress" })]
public ButtonControl gripPressed { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "Primary2DAxisClick", "ThumbstickPress" })]
public ButtonControl thumbstickClicked { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "ATouch", "XTouch" })]
public ButtonControl primaryTouched { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "BTouch", "YTouch" })]
public ButtonControl secondaryTouched { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "TriggerTouch" })]
public ButtonControl triggerTouched { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "TriggerPress" })]
public ButtonControl triggerPressed { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "Menu" })]
public ButtonControl menu { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "ThumbstickTouch" })]
public ButtonControl thumbstickTouched { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "ThumbRestTouch" })]
public ButtonControl thumbRestTouched { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerTrackingState" })]
public new IntegerControl trackingState { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "ControllerIsTracked" })]
public new ButtonControl isTracked { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerPosition" })]
public new Vector3Control devicePosition { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerRotation" })]
public new QuaternionControl deviceRotation { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerVelocity" })]
public Vector3Control deviceVelocity { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerAngularVelocity" })]
public Vector3Control deviceAngularVelocity { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerAcceleration" })]
public Vector3Control deviceAcceleration { get; private set; }
[Preserve]
[InputControl(aliases = new[] { "controllerAngularAcceleration" })]
public Vector3Control deviceAngularAcceleration { get; private set; }
protected override void FinishSetup()
{
base.FinishSetup();
thumbstick = GetChildControl<Vector2Control>("thumbstick");
trigger = GetChildControl<AxisControl>("trigger");
triggerTouched = GetChildControl<ButtonControl>("triggerTouched");
grip = GetChildControl<AxisControl>("grip");
primaryButton = GetChildControl<ButtonControl>("primaryButton");
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
gripPressed = GetChildControl<ButtonControl>("gripPressed");
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
primaryTouched = GetChildControl<ButtonControl>("primaryTouched");
secondaryTouched = GetChildControl<ButtonControl>("secondaryTouched");
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
trackingState = GetChildControl<IntegerControl>("trackingState");
isTracked = GetChildControl<ButtonControl>("isTracked");
devicePosition = GetChildControl<Vector3Control>("devicePosition");
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
deviceAngularAcceleration = GetChildControl<Vector3Control>("deviceAngularAcceleration");
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More