namespace Zinnia.Utility { using System.Collections.Generic; #if UNITY_2019_3_OR_NEWER using UnityEngine; #endif using UnityEngine.XR; /// /// Wrapper class for properties that have become obsolete in later versions of Unity. /// public static class XRDeviceProperties { /// /// The number of devices found with the same node identifier. /// /// The node to check for. /// The number of devices found. public static int DeviceCount(XRNode node = XRNode.Head) { int deviceCount = 0; #if UNITY_2019_3_OR_NEWER List devices = new List(); InputDevices.GetDevicesAtXRNode(node, devices); deviceCount = devices.Count; #else List nodeStates = new List(); InputTracking.GetNodeStates(nodeStates); foreach (XRNodeState nodeState in nodeStates) { if (nodeState.nodeType == node) { deviceCount++; } } #endif return deviceCount; } /// /// Determines whether the device is present. /// /// Whether the device is present. public static bool IsPresent() { bool isPresent = false; #if UNITY_2019_3_OR_NEWER List xrDisplaySubsystems = new List(); SubsystemManager.GetInstances(xrDisplaySubsystems); foreach (XRDisplaySubsystem xrDisplay in xrDisplaySubsystems) { if (xrDisplay.running) { isPresent = true; } } #else isPresent = XRDevice.isPresent; #endif return isPresent; } /// /// Determines whether the device has positional tracking. /// /// The node to check for. /// Whether the device has positional tracking. public static bool HasPositionalTracking(XRNode node = XRNode.Head) { bool hasPositionalTracking = false; #if UNITY_2019_3_OR_NEWER InputDevice positionalTrackingDevice = InputDevices.GetDeviceAtXRNode(node); if (positionalTrackingDevice != null) { positionalTrackingDevice.TryGetFeatureValue(CommonUsages.trackingState, out InputTrackingState trackingState); hasPositionalTracking = (trackingState & InputTrackingState.Position) != 0; } #else List nodeStates = new List(); InputTracking.GetNodeStates(nodeStates); foreach (XRNodeState nodeState in nodeStates) { if (nodeState.nodeType == node) { hasPositionalTracking = nodeState.TryGetPosition(out _); break; } } #endif return hasPositionalTracking; } /// /// Determines whether the device has rotational tracking. /// /// The node to check for. /// Whether the device has rotational tracking. public static bool HasRotationalTracking(XRNode node = XRNode.Head) { bool hasRotationalTracking = false; #if UNITY_2019_3_OR_NEWER InputDevice rotationalTrackingDevice = InputDevices.GetDeviceAtXRNode(node); if (rotationalTrackingDevice != null) { rotationalTrackingDevice.TryGetFeatureValue(CommonUsages.trackingState, out InputTrackingState trackingState); hasRotationalTracking = (trackingState & InputTrackingState.Rotation) != 0; } #else List nodeStates = new List(); InputTracking.GetNodeStates(nodeStates); foreach (XRNodeState nodeState in nodeStates) { if (nodeState.nodeType == node) { hasRotationalTracking = nodeState.TryGetRotation(out _); break; } } #endif return hasRotationalTracking; } /// /// The manufacturer name of the given node. /// /// The node to check for. /// The manufacturer name. public static string Manufacturer(XRNode node = XRNode.Head) { string manufacturerName = ""; #if UNITY_2019_3_OR_NEWER InputDevice manufacturerDevice = InputDevices.GetDeviceAtXRNode(node); manufacturerName = manufacturerDevice != null && manufacturerDevice.manufacturer != null ? manufacturerDevice.manufacturer : ""; #endif return manufacturerName; } /// /// The model name of the given node. /// /// The node to check for. /// The model name. public static string Model(XRNode node = XRNode.Head) { string modelName = ""; #if UNITY_2019_3_OR_NEWER InputDevice modelDevice = InputDevices.GetDeviceAtXRNode(node); modelName = modelDevice != null && modelDevice.name != null ? modelDevice.name : ""; #else modelName = XRDevice.model; #endif return modelName; } /// /// Determines whether the device is being tracked. /// /// The node to check for. /// Whether the device is being tracked. public static bool IsTracked(XRNode node = XRNode.Head) { bool isTracked = false; #if UNITY_2019_3_OR_NEWER InputDevice trackedDevice = InputDevices.GetDeviceAtXRNode(node); if (trackedDevice != null) { trackedDevice.TryGetFeatureValue(CommonUsages.isTracked, out isTracked); } #else List nodeStates = new List(); InputTracking.GetNodeStates(nodeStates); foreach (XRNodeState nodeState in nodeStates) { if (nodeState.nodeType == node) { isTracked = nodeState.tracked; break; } } #endif return isTracked; } /// /// Determines whether the device is valid. /// /// The node to check for. /// Whether the device is valid. public static bool IsValid(XRNode node = XRNode.Head) { bool isValid = false; #if UNITY_2019_3_OR_NEWER InputDevice validDevice = InputDevices.GetDeviceAtXRNode(node); isValid = validDevice != null && validDevice.isValid; #endif return isValid; } /// /// The user presence state for the given node. /// /// The node to check for. /// The user presence state. public static string UserPresence(XRNode node = XRNode.Head) { string userPresence = "Unknown"; #if UNITY_2019_3_OR_NEWER InputDevice userPresenceDevice = InputDevices.GetDeviceAtXRNode(node); if (userPresenceDevice != null) { if (userPresenceDevice.TryGetFeatureValue(CommonUsages.userPresence, out bool userPresent)) { userPresence = userPresent ? "Present" : "NotPresent"; } else { userPresence = "Unsupported"; } } #else userPresence = XRDevice.userPresence.ToString(); #endif return userPresence; } /// /// The current battery level of the device at the given node. /// /// The node to check for. /// The current battery level. public static float BatteryLevel(XRNode node = XRNode.Head) { float batteryLevel = -1f; #if UNITY_2019_3_OR_NEWER InputDevice batteryLevelDevice = InputDevices.GetDeviceAtXRNode(node); if (batteryLevelDevice != null) { batteryLevelDevice.TryGetFeatureValue(CommonUsages.batteryLevel, out batteryLevel); } #endif return batteryLevel; } #if UNITY_2019_3_OR_NEWER /// /// Returns the first device found at the given node. /// /// The node to check for. /// The first found device. public static InputDevice DeviceInstance(XRNode node = XRNode.Head) { List devices = new List(); InputDevices.GetDevicesAtXRNode(node, devices); if (devices.Count == 0) { return default; } if (devices.Count > 1) { Debug.Log("Multiple devices found at node: " + node); } return devices[0]; } /// /// Determines whether the given device is the same as a default unset device. /// /// The device to check for. /// Whether the device is the same as a default unset device. public static bool IsDeviceDefault(InputDevice device) { return device == default; } #endif } }