using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; namespace Passer.Tracking { public class UnityXRController : ControllerComponent { #if pUNITYXR //public TrackerComponent tracker; //public Transform sensorTransform { // get { return this.transform; } //} protected InputDevice device; protected XRNode xrNode; public GameObject model; #region Manage /// /// Find a Unity XR Controller /// /// /// /// public static UnityXRController Find(UnityXR unityXR, bool isLeft) { UnityXRController[] controllers = unityXR.GetComponentsInChildren(); foreach (UnityXRController controller in controllers) { if (controller.isLeft == isLeft) return controller; } return null; } /// /// Find or Create a Unity XR Controller /// /// /// /// public static UnityXRController Get(UnityXR unityXR, bool isLeft, Vector3 position, Quaternion rotation) { if (unityXR == null || unityXR.transform == null) return null; //Transform controllerTransform = tracker.transform.Find(name); UnityXRController unityController = Find(unityXR, isLeft); if (unityController == null) { GameObject trackerObject = new GameObject(isLeft ? "Left Controller" : "Right Controller"); Transform controllerTransform = trackerObject.transform; controllerTransform.parent = unityXR.transform; controllerTransform.position = position; controllerTransform.rotation = rotation; unityController = controllerTransform.gameObject.AddComponent(); unityController.isLeft = isLeft; } return unityController; } protected Dictionary modelNames = new Dictionary() { { "Oculus Touch Controller - Left", "Left Touch Controller" }, { "Oculus Touch Controller - Right", "Right Touch Controller" }, }; protected virtual void ShowModel(string deviceName) { if (model != null) Destroy(model); if (deviceName == null) return; string modelName = deviceName; if (modelNames.ContainsKey(modelName)) modelName = modelNames[deviceName]; CreateModel(modelName); } protected void CreateModel() { #if hLEGACY switch (UnityTracker.DetermineLoadedDevice()) { case UnityTracker.XRDeviceType.Oculus: CreateModel(isLeft ? "Left Touch Controller" : "Right Touch Controller"); break; case UnityTracker.XRDeviceType.OpenVR: CreateModel("Vive Controller"); break; case UnityTracker.XRDeviceType.None: CreateModel("Generic Controller"); break; } #endif } protected void CreateModel(string resourceName) { GameObject sensorObject; if (resourceName == null) { sensorObject = new GameObject("Model"); } else { Object controllerPrefab = Resources.Load(resourceName); if (controllerPrefab == null) sensorObject = new GameObject("Model"); else sensorObject = (GameObject)Instantiate(controllerPrefab); sensorObject.name = resourceName; } model = sensorObject; model.transform.parent = this.transform; model.transform.localPosition = Vector3.zero; model.transform.localRotation = Quaternion.identity; } #endregion #region Init protected override void Start() { base.Start(); //if (tracker == null) // tracker = GetComponentInParent(); xrNode = isLeft ? XRNode.LeftHand : XRNode.RightHand; device = InputDevices.GetDeviceAtXRNode(xrNode); ShowModel(device.name); InputDevices.deviceConnected += OnDeviceConnected; InputDevices.deviceDisconnected += OnDeviceDisconnected; } /// /// Controller has connected /// /// The InputDevice of the controller protected virtual void OnDeviceConnected(InputDevice device) { bool isLeft = (device.characteristics & InputDeviceCharacteristics.Left) != 0; bool isController = (device.characteristics & InputDeviceCharacteristics.Controller) != 0; if (isController && isLeft == this.isLeft) { if (this.device.name != device.name) ShowModel(device.name); this.device = device; Show(true); } } /// /// Controller has disconnected /// /// This also happens when the device is no longer tracked. /// The InputDevice of the controller protected virtual void OnDeviceDisconnected(InputDevice device) { bool isLeft = (device.characteristics & InputDeviceCharacteristics.Left) != 0; bool isController = (device.characteristics & InputDeviceCharacteristics.Controller) != 0; if (isController && isLeft == this.isLeft) { this.device = device; Show(false); } } #endregion #region Update public override void UpdateComponent() { base.UpdateComponent(); status = Tracker.Status.Unavailable; positionConfidence = 0; rotationConfidence = 0; if (device == null) return; status = Tracker.Status.Present; Vector3 position; if (device.TryGetFeatureValue(CommonUsages.devicePosition, out position)) { transform.position = trackerTransform.TransformPoint(position); positionConfidence = 1; status = Tracker.Status.Tracking; } Quaternion rotation; if (device.TryGetFeatureValue(CommonUsages.deviceRotation, out rotation)) { transform.rotation = trackerTransform.rotation * rotation; rotationConfidence = 1; status = Tracker.Status.Tracking; } UpdateInput(); show = (status == Tracker.Status.Tracking); } protected virtual void UpdateInput() { device.TryGetFeatureValue(CommonUsages.trigger, out trigger1); device.TryGetFeatureValue(CommonUsages.grip, out trigger2); bool buttonPress; bool buttonTouch; device.TryGetFeatureValue(CommonUsages.primaryButton, out buttonPress); device.TryGetFeatureValue(CommonUsages.primaryTouch, out buttonTouch); button1 = buttonPress ? 1 : buttonTouch ? 0 : -1; device.TryGetFeatureValue(CommonUsages.secondaryButton, out buttonPress); device.TryGetFeatureValue(CommonUsages.secondaryTouch, out buttonTouch); button2 = buttonPress ? 1 : buttonTouch ? 0 : -1; device.TryGetFeatureValue(CommonUsages.menuButton, out buttonPress); option = buttonPress ? 1 : 0; Vector2 axis; float axisButton; device.TryGetFeatureValue(CommonUsages.primary2DAxis, out axis); device.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out buttonPress); device.TryGetFeatureValue(CommonUsages.primary2DAxisTouch, out buttonTouch); axisButton = buttonPress ? 1 : buttonTouch ? 0 : -1; primaryAxis = new Vector3(axis.x, axis.y, axisButton); device.TryGetFeatureValue(CommonUsages.secondary2DAxis, out axis); device.TryGetFeatureValue(CommonUsages.secondary2DAxisClick, out buttonPress); device.TryGetFeatureValue(CommonUsages.secondary2DAxisTouch, out buttonTouch); axisButton = buttonPress ? 1 : buttonTouch ? 0 : -1; secondaryAxis = new Vector3(axis.x, axis.y, axisButton); device.TryGetFeatureValue(CommonUsages.batteryLevel, out battery); } public void Show(bool showModel) { if (model == null) return; if (!Application.isPlaying) model.SetActive(showModel); Renderer[] renderers = model.GetComponentsInChildren(); for (int i = 0; i < renderers.Length; i++) renderers[i].enabled = showModel; } #endregion Init #endif } }