public void Update() { var nodeStates = new List <XRNodeState>(); var unassignedDevices = new Queue <XRNodeState>(); var serialNumbers = new string[0]; InputTracking.GetNodeStates(nodeStates); if (OpenVRActionManager.isRunning) { serialNumbers = OpenVRWrapper.GetTrackedDeviceSerialNumbers(); } XRNodeState?headNodeState = null; XRNodeState?leftHandNodeState = null; XRNodeState?rightHandNodeState = null; XRNodeState?leftFootNodeState = null; XRNodeState?rightFootNodeState = null; XRNodeState?waistNodeState = null; int trackerCount = 0; foreach (XRNodeState nodeState in nodeStates) { if (!_foundDevices.Contains(nodeState.uniqueID)) { _foundDevices.Add(nodeState.uniqueID); Plugin.logger.Debug($"Found new XR device of type \"{nodeState.nodeType}\" named \"{InputTracking.GetNodeName(nodeState.uniqueID)}\" with ID {nodeState.uniqueID}"); } switch (nodeState.nodeType) { case XRNode.CenterEye: headNodeState = nodeState; break; case XRNode.LeftHand: leftHandNodeState = nodeState; break; case XRNode.RightHand: rightHandNodeState = nodeState; break; case XRNode.HardwareTracker: if (OpenVRActionManager.isRunning) { // try to figure out tracker role using OpenVR string deviceName = InputTracking.GetNodeName(nodeState.uniqueID); int openVRDeviceId = Array.FindIndex(serialNumbers, s => !string.IsNullOrEmpty(s) && deviceName.Contains(s)); var role = TrackedDeviceType.Unknown; if (openVRDeviceId != -1) { role = OpenVRWrapper.GetTrackedDeviceType((uint)openVRDeviceId); } switch (role) { case TrackedDeviceType.LeftFoot: leftFootNodeState = nodeState; break; case TrackedDeviceType.RightFoot: rightFootNodeState = nodeState; break; case TrackedDeviceType.Waist: waistNodeState = nodeState; break; default: unassignedDevices.Enqueue(nodeState); break; } } else { unassignedDevices.Enqueue(nodeState); } trackerCount++; break; } } // fallback if OpenVR tracker roles aren't set/supported if (leftFootNodeState == null && trackerCount >= 2 && unassignedDevices.Count > 0) { leftFootNodeState = unassignedDevices.Dequeue(); } if (rightFootNodeState == null && trackerCount >= 2 && unassignedDevices.Count > 0) { rightFootNodeState = unassignedDevices.Dequeue(); } if (waistNodeState == null && unassignedDevices.Count > 0) { waistNodeState = unassignedDevices.Dequeue(); } UpdateTrackedDevice(head, headNodeState, nameof(head)); UpdateTrackedDevice(leftHand, leftHandNodeState, nameof(leftHand)); UpdateTrackedDevice(rightHand, rightHandNodeState, nameof(rightHand)); UpdateTrackedDevice(leftFoot, leftFootNodeState, nameof(leftFoot)); UpdateTrackedDevice(rightFoot, rightFootNodeState, nameof(rightFoot)); UpdateTrackedDevice(waist, waistNodeState, nameof(waist)); foreach (ulong id in _foundDevices.ToList()) { if (!nodeStates.Exists(n => n.uniqueID == id)) { Plugin.logger.Debug($"Lost XR device with ID " + id); _foundDevices.Remove(id); } } }
// ReSharper restore UnusedMember.Local #pragma warning restore IDE0051 #endregion private void UpdateInputDevices() { var inputDevices = new List <InputDevice>(); var unassignedDevices = new Queue <InputDevice>(); var openVRDevicesBySerialNumber = new Dictionary <string, uint>(); InputDevices.GetDevices(inputDevices); var deviceRoles = new Dictionary <string, TrackedDeviceRole>(inputDevices.Count); if (_isOpenVRRunning) { string[] serialNumbers = OpenVRWrapper.GetTrackedDeviceSerialNumbers(); for (uint i = 0; i < serialNumbers.Length; i++) { if (string.IsNullOrEmpty(serialNumbers[i])) { continue; } Plugin.logger.Debug($"Got serial number \"{serialNumbers[i]}\" for device at index {i}"); openVRDevicesBySerialNumber.Add(serialNumbers[i], i); } } InputDevice?headInputDevice = null; InputDevice?leftHandInputDevice = null; InputDevice?rightHandInputDevice = null; InputDevice?waistInputDevice = null; InputDevice?leftFootInputDevice = null; InputDevice?rightFootInputDevice = null; int trackerCount = 0; foreach (InputDevice device in inputDevices) { if (!device.isValid) { continue; } deviceRoles.Add(device.name, TrackedDeviceRole.Unknown); if (!_foundDevices.Contains(device.name)) { Plugin.logger.Info($"Found new input device \"{device.name}\" with serial number \"{device.serialNumber}\""); _foundDevices.Add(device.name); } if (device.HasCharacteristics(InputDeviceCharacteristics.HeadMounted)) { headInputDevice = device; } else if (device.HasCharacteristics(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Left)) { leftHandInputDevice = device; } else if (device.HasCharacteristics(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Right)) { rightHandInputDevice = device; } else if (device.HasCharacteristics(InputDeviceCharacteristics.TrackedDevice) && !device.HasCharacteristics(InputDeviceCharacteristics.TrackingReference)) { if (_isOpenVRRunning && !string.IsNullOrEmpty(device.serialNumber) && openVRDevicesBySerialNumber.TryGetValue(device.serialNumber, out uint openVRDeviceId)) { // try to figure out tracker role using OpenVR var role = OpenVRWrapper.GetTrackedDeviceRole(openVRDeviceId); deviceRoles[device.name] = role; Plugin.logger.Info($"Tracker \"{device.name}\" has role {role}"); switch (role) { case TrackedDeviceRole.Waist: waistInputDevice = device; break; case TrackedDeviceRole.LeftFoot: leftFootInputDevice = device; break; case TrackedDeviceRole.RightFoot: rightFootInputDevice = device; break; default: unassignedDevices.Enqueue(device); break; } } else { unassignedDevices.Enqueue(device); } trackerCount++; } } // fallback if OpenVR tracker roles aren't set/supported if (leftFootInputDevice == null && trackerCount >= 2 && unassignedDevices.Count > 0) { leftFootInputDevice = unassignedDevices.Dequeue(); } if (rightFootInputDevice == null && trackerCount >= 2 && unassignedDevices.Count > 0) { rightFootInputDevice = unassignedDevices.Dequeue(); } if (waistInputDevice == null && unassignedDevices.Count > 0) { waistInputDevice = unassignedDevices.Dequeue(); } AssignTrackedDevice(head, headInputDevice, DeviceUse.Head, headInputDevice.HasValue ? deviceRoles[headInputDevice.Value.name] : TrackedDeviceRole.Unknown); AssignTrackedDevice(leftHand, leftHandInputDevice, DeviceUse.LeftHand, leftHandInputDevice.HasValue ? deviceRoles[leftHandInputDevice.Value.name] : TrackedDeviceRole.Unknown); AssignTrackedDevice(rightHand, rightHandInputDevice, DeviceUse.RightHand, rightHandInputDevice.HasValue ? deviceRoles[rightHandInputDevice.Value.name] : TrackedDeviceRole.Unknown); AssignTrackedDevice(waist, waistInputDevice, DeviceUse.Waist, waistInputDevice.HasValue ? deviceRoles[waistInputDevice.Value.name] : TrackedDeviceRole.Unknown); AssignTrackedDevice(leftFoot, leftFootInputDevice, DeviceUse.LeftFoot, leftFootInputDevice.HasValue ? deviceRoles[leftFootInputDevice.Value.name] : TrackedDeviceRole.Unknown); AssignTrackedDevice(rightFoot, rightFootInputDevice, DeviceUse.RightFoot, rightFootInputDevice.HasValue ? deviceRoles[rightFootInputDevice.Value.name] : TrackedDeviceRole.Unknown); foreach (string deviceName in _foundDevices.ToList()) { if (!inputDevices.Exists(d => d.name == deviceName)) { Plugin.logger.Info($"Lost device \"{deviceName}\""); _foundDevices.Remove(deviceName); } } }