TaiZhouCangChu_VRanime/Assets/HTC.UnityPlugin/VRModule/Modules/UnityXRModuleUtil.cs

476 lines
21 KiB
C#

//========= Copyright 2016-2023, HTC Corporation. All rights reserved. ===========
using HTC.UnityPlugin.Utility;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_2017_2_OR_NEWER
using UnityEngine.XR;
#endif
#if VIU_XR_GENERAL_SETTINGS
using UnityEngine.XR.Management;
using System;
#endif
namespace HTC.UnityPlugin.VRModuleManagement
{
public abstract partial class UnityXRModuleBase : VRModule.ModuleBase
{
#if UNITY_2019_3_OR_NEWER && VIU_XR_GENERAL_SETTINGS
private class IndexMap
{
private Dictionary<int, uint> hashID2index = new Dictionary<int, uint>();
private InputDevice[] index2Device = new InputDevice[VRModule.MAX_DEVICE_COUNT];
private int[] index2DeviceHashID = new int[VRModule.MAX_DEVICE_COUNT];
public IndexMap() { Clear(); }
private bool IsValidDevice(InputDevice device) { return device != default(InputDevice); }
private bool IsValidIndex(uint index) { return index < index2Device.Length; }
public uint Device2Index(InputDevice device)
{
if (IsValidDevice(device))
{
uint index;
if (hashID2index.TryGetValue(HashID(device), out index))
{
return index;
}
}
return VRModule.INVALID_DEVICE_INDEX;
}
public bool TryGetIndex(InputDevice device, out uint index)
{
index = Device2Index(device);
return IsValidIndex(index);
}
public InputDevice Index2Device(uint index)
{
return IsValidIndex(index) ? index2Device[index] : default(InputDevice);
}
public bool TryGetDevice(uint index, out InputDevice device)
{
device = Index2Device(index);
return IsValidDevice(device);
}
public bool IsMapped(int hashID)
{
uint index;
return hashID2index.TryGetValue(hashID, out index) && IsValidIndex(index);
}
public bool IsMapped(uint index)
{
return IsValidIndex(index) && index2DeviceHashID[index] != 0;
}
public static bool IsHMD(InputDevice device)
{
return (device.characteristics & InputDeviceCharacteristics.HeadMounted) > 0u;
}
public bool TryMapAsHMD(InputDevice device)
{
if (!IsValidDevice(device)) { throw new ArgumentException("Invalid device", "device"); }
var hashID = HashID(device);
if (IsMapped(hashID)) { throw new Exception("device(" + device.ToString() + ") already mapped"); }
if (!IsHMD(device)) { return false; }
hashID2index[hashID] = VRModule.HMD_DEVICE_INDEX;
index2Device[VRModule.HMD_DEVICE_INDEX] = device;
index2DeviceHashID[VRModule.HMD_DEVICE_INDEX] = hashID;
return true;
}
public void MapNonHMD(InputDevice device, uint index)
{
if (!IsValidDevice(device)) { throw new ArgumentException("Invalid device", "device"); }
if (!IsValidIndex(index)) { throw new ArgumentException("index larger then VRModule.MAX_DEVICE_COUNT(" + VRModule.MAX_DEVICE_COUNT + ")", "index"); }
var hashID = HashID(device);
if (IsMapped(hashID)) { throw new Exception("device(" + device.ToString() + ") already mapped"); }
if (IsMapped(index)) { throw new Exception("index(" + index + ") already mapped"); }
if (IsHMD(device)) { throw new Exception("device(" + device.ToString() + ") is hmd"); }
if (index == VRModule.HMD_DEVICE_INDEX) { throw new Exception("index cannot be VRModule.HMD_DEVICE_INDEX(" + VRModule.HMD_DEVICE_INDEX + ")"); }
hashID2index[hashID] = index;
index2Device[index] = device;
index2DeviceHashID[index] = hashID;
}
public void UnmapByDevice(InputDevice device)
{
if (!IsValidDevice(device)) { throw new ArgumentException("Invalid device", "device"); }
var hashID = HashID(device);
uint index;
if (!hashID2index.TryGetValue(hashID, out index)) { return; }
hashID2index.Remove(hashID);
index2Device[index] = default(InputDevice);
index2DeviceHashID[index] = 0;
}
public void UnmapByIndex(uint index)
{
if (!IsValidIndex(index)) { throw new ArgumentException("Invalid index", "index"); }
hashID2index.Remove(index2DeviceHashID[index]);
index2Device[index] = default(InputDevice);
index2DeviceHashID[index] = 0;
}
public void Clear()
{
hashID2index.Clear();
for (int i = index2Device.Length - 1; i >= 0; --i) { index2Device[i] = default(InputDevice); }
}
public static int HashID(InputDevice device)
{
#if CSHARP_7_OR_LATER
return (device, device.name, device.characteristics).GetHashCode();
#else
return new { device, device.name, device.characteristics }.GetHashCode();
#endif
}
}
public static bool HasActiveLoader()
{
var instance = XRGeneralSettings.Instance;
if (instance == null) { return false; }
var manager = instance.Manager;
if (manager == null) { return false; }
return manager.activeLoader != null;
}
public static bool HasActiveLoader(string loaderName)
{
string activeLoaderName;
return TryGetActiveLoaderName(out activeLoaderName) && activeLoaderName == loaderName;
}
public static bool HasActiveLoader(VRModuleKnownXRLoader knownLoader)
{
string activeLoaderName;
return TryGetActiveLoaderName(out activeLoaderName) && knownLoader == ToKnownXRLoader(activeLoaderName);
}
public static VRModuleKnownXRLoader GetKnownActiveLoader()
{
var instance = XRGeneralSettings.Instance;
if (instance == null) { return VRModuleKnownXRLoader.Unknown; }
var manager = instance.Manager;
if (manager == null) { return VRModuleKnownXRLoader.Unknown; }
var loader = manager.activeLoader;
if (loader == null) { return VRModuleKnownXRLoader.Unknown; }
var loaderName = loader.name;
if (string.IsNullOrEmpty(loaderName)) { return VRModuleKnownXRLoader.Unknown; }
foreach (var profile in loaderProfiles)
{
if (string.IsNullOrEmpty(profile.fixedName) || profile.fixedName != loaderName) { continue; }
if (profile.matchNameRgx == null || !profile.matchNameRgx.IsMatch(loaderName)) { continue; }
return profile.loader;
}
return VRModuleKnownXRLoader.Unknown;
}
public static VRModuleKnownXRLoader ToKnownXRLoader(string loaderName)
{
foreach (var profile in loaderProfiles)
{
if (string.IsNullOrEmpty(profile.fixedName) || profile.fixedName != loaderName) { continue; }
if (profile.matchNameRgx == null || !profile.matchNameRgx.IsMatch(loaderName)) { continue; }
return profile.loader;
}
return VRModuleKnownXRLoader.Unknown;
}
public static bool TryGetActiveLoaderName(out string loaderName)
{
loaderName = default(string);
var instance = XRGeneralSettings.Instance;
if (instance == null) { return false; }
var manager = instance.Manager;
if (manager == null) { return false; }
var loader = manager.activeLoader;
if (loader == null) { return false; }
loaderName = loader.name;
return true;
}
protected void LogDeviceFeatureUsages(InputDevice device)
{
List<InputFeatureUsage> usages = new List<InputFeatureUsage>();
if (device.TryGetFeatureUsages(usages))
{
string strUsages = "";
foreach (var usage in usages)
{
strUsages += "[" + usage.type.Name + "] " + usage.name + "\n";
}
Debug.Log(device.name + " feature usages:\n\n" + strUsages);
}
}
protected static string CharacteristicsToString(InputDeviceCharacteristics ch)
{
if (ch == 0u) { return " No Characteristic"; }
var chu = (uint)ch;
var str = string.Empty;
for (var i = 1u; chu > 0u; i <<= 1)
{
if ((chu & i) == 0u) { continue; }
str += " " + (InputDeviceCharacteristics)i;
chu &= ~i;
}
return str;
}
public static VRModuleKnownXRInputSubsystem GetKnownActiveInputSubsystem()
{
var activeSubsys = ListPool<XRInputSubsystem>.Get();
try
{
SubsystemManager.GetInstances(activeSubsys);
if (activeSubsys.Count == 0)
{
Debug.LogWarning("No XRInputSubsystem detected.");
}
else
{
foreach (var subsys in activeSubsys)
{
if (!subsys.running) { continue; }
var subsysName = subsys.SubsystemDescriptor.id;
if (string.IsNullOrEmpty(subsysName)) { continue; }
foreach (var profile in inputSubsystemProfiles)
{
if (!string.IsNullOrEmpty(profile.fixedName) && profile.fixedName != subsysName) { continue; }
if (profile.matchNameRgx == null || !profile.matchNameRgx.IsMatch(subsysName)) { continue; }
return profile.subsystem;
}
}
}
return VRModuleKnownXRInputSubsystem.Unknown;
}
finally
{
ListPool<XRInputSubsystem>.Release(activeSubsys);
}
}
public static InputFeatureUsage<Vector3> pointerPositionFeature = new InputFeatureUsage<Vector3>("PointerPosition");
public static InputFeatureUsage<Quaternion> pointerRotationFeature = new InputFeatureUsage<Quaternion>("PointerRotation");
public static InputFeatureUsage<Vector3> pointerVelocityFeature = new InputFeatureUsage<Vector3>("PointerVelocity");
public static InputFeatureUsage<Vector3> pointerAngularVelocityFeature = new InputFeatureUsage<Vector3>("PointerAngularVelocity");
#if UNITY_EDITOR
public static bool GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<bool> feature, bool defaultValue = default(bool))
{
bool value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static uint GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<uint> feature, uint defaultValue = default(uint))
{
uint value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static float GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<float> feature, float defaultValue = default(float))
{
float value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Vector2 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector2> feature, Vector2 defaultValue = default(Vector2))
{
Vector2 value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Vector3 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector3> feature, Vector3 defaultValue = default(Vector3))
{
Vector3 value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Vector3 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector3> feature, InputFeatureUsage<Vector3> fallbackFeature, Vector3 defaultValue = default(Vector3))
{
Vector3 value;
if (device.TryGetFeatureValue(feature, out value)) { return value; }
if (device.TryGetFeatureValue(fallbackFeature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
LogWarningFeatureNotFound(device, fallbackFeature);
return defaultValue;
}
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature) { return GetDeviceFeatureValueOrDefault(device, feature, Quaternion.identity); }
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, Quaternion defaultValue)
{
Quaternion value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, InputFeatureUsage<Quaternion> fallbackFeature) { return GetDeviceFeatureValueOrDefault(device, feature, fallbackFeature, Quaternion.identity); }
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, InputFeatureUsage<Quaternion> fallbackFeature, Quaternion defaultValue)
{
Quaternion value;
if (device.TryGetFeatureValue(feature, out value)) { return value; }
if (device.TryGetFeatureValue(fallbackFeature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
LogWarningFeatureNotFound(device, fallbackFeature);
return defaultValue;
}
public static UnityEngine.XR.Hand GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<UnityEngine.XR.Hand> feature, UnityEngine.XR.Hand defaultValue = default(UnityEngine.XR.Hand))
{
UnityEngine.XR.Hand value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Bone GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Bone> feature, Bone defaultValue = default(Bone))
{
Bone value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
public static Eyes GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Eyes> feature, Eyes defaultValue = default(Eyes))
{
Eyes value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
LogWarningFeatureNotFound(device, feature);
return defaultValue;
}
private static HashSet<int> warnedFeatures = new HashSet<int>();
private static void LogWarningFeatureNotFound<T>(InputDevice device, InputFeatureUsage<T> feature)
{
#if CSHARP_7_OR_LATER
var hashCode = (device, feature).GetHashCode();
#else
var hashCode = new { device, feature }.GetHashCode();
#endif
if (warnedFeatures.Add(hashCode))
{
Debug.LogWarningFormat("Device {0} doesn't have {1} feature {2}.", device.name, typeof(T).Name, feature.name);
}
}
#else
public static bool GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<bool> feature, bool defaultValue = default(bool))
{
bool value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static uint GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<uint> feature, uint defaultValue = default(uint))
{
uint value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static float GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<float> feature, float defaultValue = default(float))
{
float value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Vector2 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector2> feature, Vector2 defaultValue = default(Vector2))
{
Vector2 value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Vector3 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector3> feature, Vector3 defaultValue = default(Vector3))
{
Vector3 value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Vector3 GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Vector3> feature, InputFeatureUsage<Vector3> fallbackFeature, Vector3 defaultValue = default(Vector3))
{
Vector3 value;
if (device.TryGetFeatureValue(feature, out value)) { return value; }
if (device.TryGetFeatureValue(fallbackFeature, out value)) { return value; }
return defaultValue;
}
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature) { return GetDeviceFeatureValueOrDefault(device, feature, Quaternion.identity); }
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, Quaternion defaultValue)
{
Quaternion value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, InputFeatureUsage<Quaternion> fallbackFeature) { return GetDeviceFeatureValueOrDefault(device, feature, fallbackFeature, Quaternion.identity); }
public static Quaternion GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Quaternion> feature, InputFeatureUsage<Quaternion> fallbackFeature, Quaternion defaultValue)
{
Quaternion value;
if (device.TryGetFeatureValue(feature, out value)) { return value; }
if (device.TryGetFeatureValue(fallbackFeature, out value)) { return value; }
return defaultValue;
}
public static Hand GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Hand> feature, Hand defaultValue = default(Hand))
{
Hand value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Bone GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Bone> feature, Bone defaultValue = default(Bone))
{
Bone value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
public static Eyes GetDeviceFeatureValueOrDefault(InputDevice device, InputFeatureUsage<Eyes> feature, Eyes defaultValue = default(Eyes))
{
Eyes value; if (device.TryGetFeatureValue(feature, out value)) { return value; }
return defaultValue;
}
#endif
#else
public static bool HasActiveLoader() { return false; }
public static bool HasActiveLoader(string loaderName) { return false; }
public static bool HasActiveLoader(VRModuleKnownXRLoader knownLoader) { return false; }
public static VRModuleKnownXRLoader GetKnownActiveLoader() { return VRModuleKnownXRLoader.Unknown; }
public static VRModuleKnownXRLoader ToKnownXRLoader(string loaderName) { return VRModuleKnownXRLoader.Unknown; }
public static bool TryGetActiveLoaderName(out string loaderName) { loaderName = default(string); return false; }
public static VRModuleKnownXRInputSubsystem GetKnownActiveInputSubsystem() { return VRModuleKnownXRInputSubsystem.Unknown; }
#endif
}
}