|
|
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Enables/disables objects based on connectivity and assigned roles.
- //
- //=============================================================================
-
- using UnityEngine;
- using Valve.VR;
-
- public class SteamVR_ControllerManager : MonoBehaviour
- {
- public GameObject left, right;
-
- [Tooltip("Populate with objects you want to assign to additional controllers")]
- public GameObject[] objects;
-
- [Tooltip("Set to true if you want objects arbitrarily assigned to controllers before their role (left vs right) is identified")]
- public bool assignAllBeforeIdentified;
-
- uint[] indices; // assigned
- bool[] connected = new bool[OpenVR.k_unMaxTrackedDeviceCount]; // controllers only
-
- // cached roles - may or may not be connected
- uint leftIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
- uint rightIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
-
- // Helper function to avoid adding duplicates to object array.
- void SetUniqueObject(GameObject o, int index)
- {
- for (int i = 0; i < index; i++)
- if (objects[i] == o)
- return;
-
- objects[index] = o;
- }
-
- // This needs to be called if you update left, right or objects at runtime (e.g. when dyanmically spawned).
- public void UpdateTargets()
- {
- // Add left and right entries to the head of the list so we only have to operate on the list itself.
- var objects = this.objects;
- var additional = (objects != null) ? objects.Length : 0;
- this.objects = new GameObject[2 + additional];
- SetUniqueObject(right, 0);
- SetUniqueObject(left, 1);
- for (int i = 0; i < additional; i++)
- SetUniqueObject(objects[i], 2 + i);
-
- // Reset assignments.
- indices = new uint[2 + additional];
- for (int i = 0; i < indices.Length; i++)
- indices[i] = OpenVR.k_unTrackedDeviceIndexInvalid;
- }
-
- SteamVR_Events.Action inputFocusAction, deviceConnectedAction, trackedDeviceRoleChangedAction;
-
- void Awake()
- {
- UpdateTargets();
- }
-
- SteamVR_ControllerManager()
- {
- inputFocusAction = SteamVR_Events.InputFocusAction(OnInputFocus);
- deviceConnectedAction = SteamVR_Events.DeviceConnectedAction(OnDeviceConnected);
- trackedDeviceRoleChangedAction = SteamVR_Events.SystemAction(EVREventType.VREvent_TrackedDeviceRoleChanged, OnTrackedDeviceRoleChanged);
- }
-
- void OnEnable()
- {
- for (int i = 0; i < objects.Length; i++)
- {
- var obj = objects[i];
- if (obj != null)
- obj.SetActive(false);
-
- indices[i] = OpenVR.k_unTrackedDeviceIndexInvalid;
- }
-
- Refresh();
-
- for (int i = 0; i < SteamVR.connected.Length; i++)
- if (SteamVR.connected[i])
- OnDeviceConnected(i, true);
-
- inputFocusAction.enabled = true;
- deviceConnectedAction.enabled = true;
- trackedDeviceRoleChangedAction.enabled = true;
- }
-
- void OnDisable()
- {
- inputFocusAction.enabled = false;
- deviceConnectedAction.enabled = false;
- trackedDeviceRoleChangedAction.enabled = false;
- }
-
- static string hiddenPrefix = "hidden (", hiddenPostfix = ")";
- static string[] labels = { "left", "right" };
-
- // Hide controllers when the dashboard is up.
- private void OnInputFocus(bool hasFocus)
- {
- if (hasFocus)
- {
- for (int i = 0; i < objects.Length; i++)
- {
- var obj = objects[i];
- if (obj != null)
- {
- var label = (i < 2) ? labels[i] : (i - 1).ToString();
- ShowObject(obj.transform, hiddenPrefix + label + hiddenPostfix);
- }
- }
- }
- else
- {
- for (int i = 0; i < objects.Length; i++)
- {
- var obj = objects[i];
- if (obj != null)
- {
- var label = (i < 2) ? labels[i] : (i - 1).ToString();
- HideObject(obj.transform, hiddenPrefix + label + hiddenPostfix);
- }
- }
- }
- }
-
- // Reparents to a new object and deactivates that object (this allows
- // us to call SetActive in OnDeviceConnected independently.
- private void HideObject(Transform t, string name)
- {
- if (t.gameObject.name.StartsWith(hiddenPrefix))
- {
- Debug.Log("Ignoring double-hide.");
- return;
- }
- var hidden = new GameObject(name).transform;
- hidden.parent = t.parent;
- t.parent = hidden;
- hidden.gameObject.SetActive(false);
- }
- private void ShowObject(Transform t, string name)
- {
- var hidden = t.parent;
- if (hidden.gameObject.name != name)
- return;
- t.parent = hidden.parent;
- Destroy(hidden.gameObject);
- }
-
- private void SetTrackedDeviceIndex(int objectIndex, uint trackedDeviceIndex)
- {
- // First make sure no one else is already using this index.
- if (trackedDeviceIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
- {
- for (int i = 0; i < objects.Length; i++)
- {
- if (i != objectIndex && indices[i] == trackedDeviceIndex)
- {
- var obj = objects[i];
- if (obj != null)
- obj.SetActive(false);
-
- indices[i] = OpenVR.k_unTrackedDeviceIndexInvalid;
- }
- }
- }
-
- // Only set when changed.
- if (trackedDeviceIndex != indices[objectIndex])
- {
- indices[objectIndex] = trackedDeviceIndex;
-
- var obj = objects[objectIndex];
- if (obj != null)
- {
- if (trackedDeviceIndex == OpenVR.k_unTrackedDeviceIndexInvalid)
- obj.SetActive(false);
- else
- {
- obj.SetActive(true);
- obj.BroadcastMessage("SetDeviceIndex", (int)trackedDeviceIndex, SendMessageOptions.DontRequireReceiver);
- }
- }
- }
- }
-
- // Keep track of assigned roles.
- private void OnTrackedDeviceRoleChanged(VREvent_t vrEvent)
- {
- Refresh();
- }
-
- // Keep track of connected controller indices.
- private void OnDeviceConnected(int index, bool connected)
- {
- bool changed = this.connected[index];
- this.connected[index] = false;
-
- if (connected)
- {
- var system = OpenVR.System;
- if (system != null)
- {
- var deviceClass = system.GetTrackedDeviceClass((uint)index);
- if (deviceClass == ETrackedDeviceClass.Controller ||
- deviceClass == ETrackedDeviceClass.GenericTracker)
- {
- this.connected[index] = true;
- changed = !changed; // if we clear and set the same index, nothing has changed
- }
- }
- }
-
- if (changed)
- Refresh();
- }
-
- public void Refresh()
- {
- int objectIndex = 0;
-
- var system = OpenVR.System;
- if (system != null)
- {
- leftIndex = system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
- rightIndex = system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand);
- }
-
- // If neither role has been assigned yet, try hooking up at least the right controller.
- if (leftIndex == OpenVR.k_unTrackedDeviceIndexInvalid && rightIndex == OpenVR.k_unTrackedDeviceIndexInvalid)
- {
- for (uint deviceIndex = 0; deviceIndex < connected.Length; deviceIndex++)
- {
- if (objectIndex >= objects.Length)
- break;
-
- if (!connected[deviceIndex])
- continue;
-
- SetTrackedDeviceIndex(objectIndex++, deviceIndex);
-
- if (!assignAllBeforeIdentified)
- break;
- }
- }
- else
- {
- SetTrackedDeviceIndex(objectIndex++, (rightIndex < connected.Length && connected[rightIndex]) ? rightIndex : OpenVR.k_unTrackedDeviceIndexInvalid);
- SetTrackedDeviceIndex(objectIndex++, (leftIndex < connected.Length && connected[leftIndex]) ? leftIndex : OpenVR.k_unTrackedDeviceIndexInvalid);
-
- // Assign out any additional controllers only after both left and right have been assigned.
- if (leftIndex != OpenVR.k_unTrackedDeviceIndexInvalid && rightIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
- {
- for (uint deviceIndex = 0; deviceIndex < connected.Length; deviceIndex++)
- {
- if (objectIndex >= objects.Length)
- break;
-
- if (!connected[deviceIndex])
- continue;
-
- if (deviceIndex != leftIndex && deviceIndex != rightIndex)
- {
- SetTrackedDeviceIndex(objectIndex++, deviceIndex);
- }
- }
- }
- }
-
- // Reset the rest.
- while (objectIndex < objects.Length)
- {
- SetTrackedDeviceIndex(objectIndex++, OpenVR.k_unTrackedDeviceIndexInvalid);
- }
- }
- }
-
|