Files
valheim/Assets/_Valheim/Scripts/VIVECamera.cs
2025-07-04 14:16:14 +08:00

216 lines
7.2 KiB
C#

using System.Net;
using UnityEngine;
using System;
using Wave.Native;
using Wave.Essence;
using System.Runtime.InteropServices;
using System.Collections;
using UnityEngine.XR;
using Valheim;
public class VIVECamera : MonoBehaviour
{
public GameObject marker;
[NonSerialized]
public InputDevice leftHandDevice;
[NonSerialized]
public InputDevice rightHandDevice;
private bool is_start = false;
private bool _clickA = false;
private bool _clickB = false;
private bool _clickX = false;
private bool _clickY = false;
void Start()
{
#if !UNITY_EDITOR && UNITY_ANDROID && VIVE
string polling_value;
string key = "PLAYER00InitMA";
key += "{\"marker1\":{\"id\":0,\"behavior\":3,\"size\":0.21,\"pose\":[0,0,0,1,0,0.7,0]}}";
uint RETURN_SIZE = 256;
IntPtr value = Marshal.AllocHGlobal(new IntPtr(RETURN_SIZE));
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key), value, RETURN_SIZE);
polling_value = Marshal.PtrToStringAnsi(value);
Marshal.FreeCoTaskMem(value);
Debug.Log("初始化marker");
if (string.Compare(polling_value, "InitErr") == 0) // initialization failed, should check config string
{
Debug.Log("初始化marker失败");
}
leftHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
#endif
}
void Update()
{
#if !UNITY_EDITOR && UNITY_ANDROID && VIVE
// X键
bool triggerX = false;
bool pressedOnceX = false;
if (leftHandDevice != null &&
leftHandDevice.TryGetFeatureValue(CommonUsages.primaryButton, out triggerX) &&
triggerX)
{
if (!_clickX)
{
_clickX = true;
pressedOnceX = true;
Debug.Log("按下X键");
}
}
else
{
_clickX = false;
}
// Y键
bool triggerY = false;
bool pressedOnceY = false;
if (leftHandDevice != null &&
leftHandDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out triggerY) &&
triggerY)
{
if (!_clickY)
{
_clickY = true;
pressedOnceY = true;
Debug.Log("按下Y键");
}
}
else
{
_clickY = false;
}
// A键
bool triggerA = false;
bool pressedOnceA = false;
if (rightHandDevice != null &&
rightHandDevice.TryGetFeatureValue(CommonUsages.primaryButton, out triggerA) &&
triggerA)
{
if (!_clickA)
{
_clickA = true;
pressedOnceA = true;
Debug.Log("按下A键");
}
}
else
{
_clickA = false;
}
// B键
bool triggerB = false;
bool pressedOnceB = false;
if (rightHandDevice != null &&
rightHandDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out triggerB) &&
triggerB)
{
if (!_clickB)
{
_clickB = true;
pressedOnceB = true;
Debug.Log("按下B键");
}
}
else
{
_clickB = false;
}
// A+X扫描
if (pressedOnceA && pressedOnceX)
{
Debug.Log("按下A+X键");
if (is_start == false)
{
string key = "ClearRecenterXform";
Interop.WVR_SetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key));
Interop.WVR_SetParameters(WVR_DeviceType.WVR_DeviceType_Controller_Right, Marshal.StringToHGlobalAnsi(key));
Interop.WVR_SetParameters(WVR_DeviceType.WVR_DeviceType_Controller_Left, Marshal.StringToHGlobalAnsi(key));
key = "PLAYER00StartScan";
uint RETURN_SIZE = 256;
IntPtr value = Marshal.AllocHGlobal(new IntPtr(RETURN_SIZE));
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key), value, RETURN_SIZE);
Marshal.FreeCoTaskMem(value);
is_start = true;
StartCoroutine("Polling");
}
else
{
string key = "PLAYER00StopScan";
uint RETURN_SIZE = 256;
IntPtr value = Marshal.AllocHGlobal(new IntPtr(RETURN_SIZE));
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key), value, RETURN_SIZE);
Marshal.FreeCoTaskMem(value);
StopCoroutine("Polling");
is_start = false;
Debug.Log("手动停止扫描marker");
}
}
// B+Y退出游戏
if (pressedOnceB && pressedOnceY)
{
Debug.Log("按下B+Y键");
ExitPanel.Show();
}
#endif
}
IEnumerator Polling()
{
string key = "PLAYER00CheckMA";
string key2 = "PLAYER00GetArucoPoseByID=0";
string key3 = "PLAYER00StopScan";
uint RETURN_SIZE = 2048 * 128;
IntPtr value = Marshal.AllocHGlobal(new IntPtr(RETURN_SIZE));
string polling_value;
bool need_do_check = true;
bool need_do_MA = true, need_do_IMU = true;
while (need_do_check)
{
Debug.Log("开始check");
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key), value, RETURN_SIZE);
polling_value = Marshal.PtrToStringAnsi(value);
Debug.Log("polling_value: " + polling_value);
if (string.Compare(polling_value, "CTdone") == 0)
Debug.Log("第一个marker已对齐, 请扫描下一个marker");
if (string.Compare(polling_value, "CTdone") == 0)
{
Debug.Log("地图已对齐,停止扫描");
need_do_MA = false;
}
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key2), value, RETURN_SIZE);
polling_value = Marshal.PtrToStringAnsi(value);
if (string.Compare(polling_value, "f") != 0)
{
char[] separator = { ',' };
string[] sArray = polling_value.Split(separator);
if (sArray.Length == 8 && float.TryParse(sArray[1], out float x) && float.TryParse(sArray[2], out float y) && float.TryParse(sArray[3], out float z))
{
if (marker != null)
{
marker.transform.position = new Vector3(x, y, z);
}
Debug.Log("marker已放置新位置");
need_do_IMU = false;
}
}
need_do_check = need_do_MA || need_do_IMU;
yield return new WaitForSeconds(1.0f);
}
Interop.WVR_GetParameters(WVR_DeviceType.WVR_DeviceType_HMD, Marshal.StringToHGlobalAnsi(key3), value, RETURN_SIZE);
Marshal.FreeCoTaskMem(value);
is_start = false;
}
}