123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- using UnityEngine;
- using System.Collections;
- namespace CurvedUI
- {
- /// <summary>
- /// Contains a bunch of events you can subscribe to and bools to ask for current state of the controller. Can also trigger haptic feedback if you ask nicely.
- /// </summary>
- public class CurvedUIViveController : MonoBehaviour
- {
- #if CURVEDUI_STEAMVR_LEGACY
-
- #region settings
- public int axisFidelity = 1;
- #endregion
- #region internal variables
- private uint controllerIndex;
- private Type controllerType = Type.UNDEFINED;
- private SteamVR_TrackedObject trackedController;
- private SteamVR_Controller.Device device;
- private Vector2 touchpadAxis = Vector2.zero;
- private Vector2 triggerAxis = Vector2.zero;
- private bool controllerVisible = true;
- private ushort hapticPulseStrength;
- private int hapticPulseCountdown;
- private ushort maxHapticVibration = 3999;
- private Vector3 oculusTouchPoitingOriginOffset = new Vector3(0, -0.0258f, -0.033f);
- private Vector3 oculusTouchPoitingRotationOffset = new Vector3(38, 0, 0);
- public enum Type
- {
- UNDEFINED = 0,
- VIVE = 1,
- OCULUS_TOUCH = 2,
- }
- #endregion
- #region EVENTS
- public event ViveInputEvent TriggerClicked;
- public event ViveInputEvent TriggerUnclicked;
- public event ViveInputEvent TriggerAxisChanged;
- public event ViveInputEvent ApplicationMenuClicked;
- public event ViveInputEvent ApplicationMenuUnclicked;
- public event ViveInputEvent GripClicked;
- public event ViveInputEvent GripUnclicked;
- public event ViveInputEvent TouchpadClicked;
- public event ViveInputEvent TouchpadUnclicked;
- public event ViveInputEvent TouchpadTouched;
- public event ViveInputEvent TouchpadUntouched;
- public event ViveInputEvent TouchpadAxisChanged;
- public event ViveEvent ModelLoaded;
- public virtual void OnTriggerClicked(ViveInputArgs e)
- {
- if (TriggerClicked != null)
- TriggerClicked(this, e);
- }
- public virtual void OnTriggerUnclicked(ViveInputArgs e)
- {
- if (TriggerUnclicked != null)
- TriggerUnclicked(this, e);
- }
- public virtual void OnTriggerAxisChanged(ViveInputArgs e)
- {
- if (TriggerAxisChanged != null)
- TriggerAxisChanged(this, e);
- }
- public virtual void OnApplicationMenuClicked(ViveInputArgs e)
- {
- if (ApplicationMenuClicked != null)
- ApplicationMenuClicked(this, e);
- }
- public virtual void OnApplicationMenuUnclicked(ViveInputArgs e)
- {
- if (ApplicationMenuUnclicked != null)
- ApplicationMenuUnclicked(this, e);
- }
- public virtual void OnGripClicked(ViveInputArgs e)
- {
- if (GripClicked != null)
- GripClicked(this, e);
- }
- public virtual void OnGripUnclicked(ViveInputArgs e)
- {
- if (GripUnclicked != null)
- GripUnclicked(this, e);
- }
- public virtual void OnTouchpadClicked(ViveInputArgs e)
- {
- if (TouchpadClicked != null)
- TouchpadClicked(this, e);
- }
- public virtual void OnTouchpadUnclicked(ViveInputArgs e)
- {
- if (TouchpadUnclicked != null)
- TouchpadUnclicked(this, e);
- }
- public virtual void OnTouchpadTouched(ViveInputArgs e)
- {
- if (TouchpadTouched != null)
- TouchpadTouched(this, e);
- }
- public virtual void OnTouchpadUntouched(ViveInputArgs e)
- {
- if (TouchpadUntouched != null)
- TouchpadUntouched(this, e);
- }
- public virtual void OnTouchpadAxisChanged(ViveInputArgs e)
- {
- if (TouchpadAxisChanged != null)
- TouchpadAxisChanged(this, e);
- }
- #endregion
- #region LIFECYCLE
- void Awake()
- {
- trackedController = GetComponent<SteamVR_TrackedObject>();
- SteamVR_Events.RenderModelLoaded.AddListener(SteamVRModelLoaded);
- }
- void Update()
- {
- controllerIndex = (uint)trackedController.index;
- //this device is not tracked right now - it has no device index - skip it.
- if (controllerIndex < 0 || controllerIndex >= Valve.VR.OpenVR.k_unMaxTrackedDeviceCount) return;
- device = SteamVR_Controller.Input((int)controllerIndex);
- //get axis inputfrom debice
- Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);
- Vector2 currentTouchpadAxis = device.GetAxis();
- //haptic feedback
- if (hapticPulseCountdown > 0)
- {
- device.TriggerHapticPulse(hapticPulseStrength);
- hapticPulseCountdown -= 1;
- }
- //check for changes in trigger press
- if (Vector2ShallowEquals(triggerAxis, currentTriggerAxis))
- {
- triggerAxisChanged = false;
- }
- else
- {
- OnTriggerAxisChanged(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));
- triggerAxisChanged = true;
- }
- //check for changes in finger pos on touchpad
- if (Vector2ShallowEquals(touchpadAxis, currentTouchpadAxis))
- {
- touchpadAxisChanged = false;
- }
- else
- {
- OnTouchpadAxisChanged(SetButtonEvent(ref touchpadTouched, true, 1f));
- touchpadAxisChanged = true;
- }
- touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);
- triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
- //Trigger
- if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
- {
- OnTriggerClicked(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));
- triggerDown = true;
- }
- else {
- triggerDown = false;
- }
- if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger))
- {
- OnTriggerUnclicked(SetButtonEvent(ref triggerPressed, false, 0f));
- triggerUp = true;
- }
- else {
- triggerUp = false;
- }
- //ApplicationMenu
- if (device.GetPressDown(SteamVR_Controller.ButtonMask.ApplicationMenu))
- {
- OnApplicationMenuClicked(SetButtonEvent(ref applicationMenuPressed, true, 1f));
- }
- else if (device.GetPressUp(SteamVR_Controller.ButtonMask.ApplicationMenu))
- {
- OnApplicationMenuUnclicked(SetButtonEvent(ref applicationMenuPressed, false, 0f));
- }
- //Grip
- if (device.GetPressDown(SteamVR_Controller.ButtonMask.Grip))
- {
- OnGripClicked(SetButtonEvent(ref gripPressed, true, 1f));
- }
- else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Grip))
- {
- OnGripUnclicked(SetButtonEvent(ref gripPressed, false, 0f));
- }
-
- //Touchpad Clicked
- if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
- {
- OnTouchpadClicked(SetButtonEvent(ref touchpadPressed, true, 1f));
- }
- else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
- {
- OnTouchpadUnclicked(SetButtonEvent(ref touchpadPressed, false, 0f));
- }
- //Touchpad Touched
- if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))
- {
- OnTouchpadTouched(SetButtonEvent(ref touchpadTouched, true, 1f));
- }
- else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
- {
- OnTouchpadUntouched(SetButtonEvent(ref touchpadTouched, false, 0f));
- }
- }
- #endregion
- #region PRIVATE
- /// <summary>
- /// Compare two vectors if there are about equal.
- /// </summary>
- bool Vector2ShallowEquals(Vector2 vectorA, Vector2 vectorB)
- {
- return (vectorA.x.ToString("F" + axisFidelity) == vectorB.x.ToString("F" + axisFidelity) &&
- vectorA.y.ToString("F" + axisFidelity) == vectorB.y.ToString("F" + axisFidelity));
- }
- void SteamVRModelLoaded(SteamVR_RenderModel model, bool loaded)
- {
- //find if the controller is touch or vive by the type of its trackpad
- Valve.VR.ETrackedPropertyError pError = new Valve.VR.ETrackedPropertyError();
- int axisprop = Valve.VR.OpenVR.System.GetInt32TrackedDeviceProperty((uint)trackedController.index, Valve.VR.ETrackedDeviceProperty.Prop_Axis0Type_Int32, ref pError);
- controllerType = axisprop == (int)Valve.VR.EVRControllerAxisType.k_eControllerAxis_Joystick ? Type.OCULUS_TOUCH : Type.VIVE;
- //call evenets
- if (ModelLoaded != null) ModelLoaded(this);
- }
- #endregion
- #region PUBLIC
- public void ToggleControllerVisible(bool on)
- {
- foreach (MeshRenderer renderer in this.GetComponentsInChildren<MeshRenderer>())
- {
- renderer.enabled = on;
- }
- foreach (SkinnedMeshRenderer renderer in this.GetComponentsInChildren<SkinnedMeshRenderer>())
- {
- renderer.enabled = on;
- }
- controllerVisible = on;
- }
- /// <summary>
- /// Triggers the haptic pulse.
- /// </summary>
- /// <param name="duration">Duration in frames.</param>
- /// <param name="strength">Strength of the pulse. 100 is barely noticable, 300-500 seems about right for most uses. </param>
- public void TriggerHapticPulse(int duration, ushort strength)
- {
- hapticPulseCountdown = duration;
- hapticPulseStrength = (strength <= maxHapticVibration ? strength : maxHapticVibration);
- }
- #endregion
- #region SETTERS AND GETTERS
- /// <summary>
- /// Is this controller a Vive Controller, Oculush Touch, or other?
- /// </summary>
- public Type ControllerType {
- get { return controllerType; }
- }
- /// <summary>
- /// Returns the pointing direction, based on controller type. Oculus touch controllers point in a slighlty different way than Vive controllers.
- /// </summary>
- public Vector3 PointingDirection {
- get { return controllerType == Type.OCULUS_TOUCH ? transform.localToWorldMatrix.MultiplyVector(Quaternion.Euler(oculusTouchPoitingRotationOffset) * Vector3.forward) : transform.forward; }
- }
- /// <summary>
- /// Returns the pointing origin, based on controller type. Oculus touch controllers point in a slighlty different way than Vive controllers.
- /// </summary>
- public Vector3 PointingOrigin {
- get { return transform.TransformPoint(controllerType == Type.OCULUS_TOUCH ? oculusTouchPoitingOriginOffset : Vector3.zero); }
- }
- /// <summary>
- /// Are the render components of the Controller enabled?
- /// </summary>
- /// <returns><c>true</c> if this instance is controller visible; otherwise, <c>false</c>.</returns>
- public bool IsControllerVisible() { return controllerVisible; }
- /// <summary>
- /// Has trigger been pressed down this frame?
- /// </summary>
- public bool IsTriggerDown { get { return triggerDown; } }
- bool triggerDown = false;
- /// <summary>
- /// Has trigger been released this frame?
- /// </summary>
- public bool IsTriggerUp { get { return triggerUp; } }
- bool triggerUp = false;
- /// <summary>
- /// Is trigger pressed during this frame?
- /// </summary>
- public bool IsTriggerPressed { get { return triggerAxis.x > 0.5f; } }
- bool triggerPressed = false;
- /// <summary>
- /// Has trigger axis (how hard trigger is pressed) changed this frame?
- /// </summary>
- public bool IsTriggerAxisChanged { get { return triggerAxisChanged; } }
- bool triggerAxisChanged = false;
- /// <summary>
- /// Has user's finger position changed on touchpad this grame?
- /// </summary>
- public bool IsTouchpadAxisChanged { get { return touchpadAxisChanged; } }
- bool touchpadAxisChanged = false;
- /// <summary>
- /// Is Application menu pressed right now?
- /// </summary>
- public bool IsApplicationMenuPressed { get { return applicationMenuPressed; } }
- bool applicationMenuPressed = false;
- /// <summary>
- /// Is touchpad pressed this frame?
- /// </summary>
- public bool IsTouchpadPressed { get { return touchpadPressed; } }
- bool touchpadPressed = false;
- /// <summary>
- /// Is user's finger resting on the touchpad?
- /// </summary>
- public bool IsTouchpadTouched { get { return touchpadTouched; } }
- bool touchpadTouched = false;
- /// <summary>
- /// Is user holding the grip button?
- /// </summary>
- public bool IsGripPressed { get { return gripPressed; } }
- bool gripPressed = false;
- /// <summary>
- /// FingerPosition on touchpad?
- /// </summary>
- public Vector2 TouchPadAxis { get { return touchpadAxis; } }
- #endregion
-
- ViveInputArgs SetButtonEvent(ref bool buttonBool, bool value, float buttonPressure)
- {
- buttonBool = value;
- ViveInputArgs e;
- e.controllerIndex = controllerIndex;
- e.buttonPressure = buttonPressure;
- e.touchpadAxis = device.GetAxis();
- return e;
- }
- #endif
- }
- public struct ViveInputArgs
- {
- public uint controllerIndex;
- public float buttonPressure;
- public Vector2 touchpadAxis;
- }
- public delegate void ViveInputEvent(object sender, ViveInputArgs e);
- public delegate void ViveEvent(object sender);
- }
|