/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; using Node = UnityEngine.XR.XRNode; /// /// Provides a unified input system for Oculus controllers and gamepads. /// public static class OVRInput { [Flags] /// Virtual button mappings that allow the same input bindings to work across different controllers. public enum Button { None = 0, ///< Maps to RawButton: [Gamepad, Touch, LTouch, RTouch, Remote: None] One = 0x00000001, ///< Maps to RawButton: [Gamepad, Touch, RTouch: A], [LTouch: X], [Remote: Start] Two = 0x00000002, ///< Maps to RawButton: [Gamepad, Touch, RTouch: B], [LTouch: Y], [Remote: Back] Three = 0x00000004, ///< Maps to RawButton: [Gamepad, Touch: X], [LTouch, RTouch, Remote: None] Four = 0x00000008, ///< Maps to RawButton: [Gamepad, Touch: Y], [LTouch, RTouch, Remote: None] Start = 0x00000100, ///< Maps to RawButton: [Gamepad: Start], [Touch, LTouch, Remote: Start], [RTouch: None] Back = 0x00000200, ///< Maps to RawButton: [Gamepad, Remote: Back], [Touch, LTouch, RTouch: None] PrimaryShoulder = 0x00001000, ///< Maps to RawButton: [Gamepad: LShoulder], [Touch, LTouch, RTouch, Remote: None] PrimaryIndexTrigger = 0x00002000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LIndexTrigger], [RTouch: RIndexTrigger], [Remote: None] PrimaryHandTrigger = 0x00004000, ///< Maps to RawButton: [Touch, LTouch: LHandTrigger], [RTouch: RHandTrigger], [Gamepad, Remote: None] PrimaryThumbstick = 0x00008000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstick], [RTouch: RThumbstick], [Remote: None] PrimaryThumbstickUp = 0x00010000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickUp], [RTouch: RThumbstickUp], [Remote: None] PrimaryThumbstickDown = 0x00020000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickDown], [RTouch: RThumbstickDown], [Remote: None] PrimaryThumbstickLeft = 0x00040000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickLeft], [RTouch: RThumbstickLeft], [Remote: None] PrimaryThumbstickRight = 0x00080000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickRight], [RTouch: RThumbstickRight], [Remote: None] PrimaryTouchpad = 0x00000400, ///< Maps to RawButton: [Gamepad, Touch, LTouch, RTouch, Remote: None] SecondaryShoulder = 0x00100000, ///< Maps to RawButton: [Gamepad: RShoulder], [Touch, LTouch, RTouch, Remote: None] SecondaryIndexTrigger = 0x00200000, ///< Maps to RawButton: [Gamepad, Touch: RIndexTrigger], [LTouch, RTouch, Remote: None] SecondaryHandTrigger = 0x00400000, ///< Maps to RawButton: [Touch: RHandTrigger], [Gamepad, LTouch, RTouch, Remote: None] SecondaryThumbstick = 0x00800000, ///< Maps to RawButton: [Gamepad, Touch: RThumbstick], [LTouch, RTouch, Remote: None] SecondaryThumbstickUp = 0x01000000, ///< Maps to RawButton: [Gamepad, Touch: RThumbstickUp], [LTouch, RTouch, Remote: None] SecondaryThumbstickDown = 0x02000000, ///< Maps to RawButton: [Gamepad, Touch: RThumbstickDown], [LTouch, RTouch, Remote: None] SecondaryThumbstickLeft = 0x04000000, ///< Maps to RawButton: [Gamepad, Touch: RThumbstickLeft], [LTouch, RTouch, Remote: None] SecondaryThumbstickRight = 0x08000000, ///< Maps to RawButton: [Gamepad, Touch: RThumbstickRight], [LTouch, RTouch, Remote: None] SecondaryTouchpad = 0x00000800, ///< Maps to RawButton: [Gamepad, Touch, LTouch, RTouch, Remote: None] DpadUp = 0x00000010, ///< Maps to RawButton: [Gamepad, Remote: DpadUp], [Touch, LTouch, RTouch: None] DpadDown = 0x00000020, ///< Maps to RawButton: [Gamepad, Remote: DpadDown], [Touch, LTouch, RTouch: None] DpadLeft = 0x00000040, ///< Maps to RawButton: [Gamepad, Remote: DpadLeft], [Touch, LTouch, RTouch: None] DpadRight = 0x00000080, ///< Maps to RawButton: [Gamepad, Remote: DpadRight], [Touch, LTouch, RTouch: None] Up = 0x10000000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickUp], [RTouch: RThumbstickUp], [Remote: DpadUp] Down = 0x20000000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickDown], [RTouch: RThumbstickDown], [Remote: DpadDown] Left = 0x40000000, ///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickLeft], [RTouch: RThumbstickLeft], [Remote: DpadLeft] Right = unchecked((int)0x80000000),///< Maps to RawButton: [Gamepad, Touch, LTouch: LThumbstickRight], [RTouch: RThumbstickRight], [Remote: DpadRight] Any = ~None, ///< Maps to RawButton: [Gamepad, Touch, LTouch, RTouch: Any] } [Flags] /// Raw button mappings that can be used to directly query the state of a controller. public enum RawButton { None = 0, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, Remote: None] A = 0x00000001, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: A], [LTouch, Remote: None] B = 0x00000002, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: B], [LTouch, Remote: None] X = 0x00000100, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: X], [RTouch, Remote: None] Y = 0x00000200, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: Y], [RTouch, Remote: None] Start = 0x00100000, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, Remote: Start], [RTouch: None] Back = 0x00200000, ///< Maps to Physical Button: [Gamepad, Remote: Back], [Touch, LTouch, RTouch: None] LShoulder = 0x00000800, ///< Maps to Physical Button: [Gamepad: LShoulder], [Touch, LTouch, RTouch, Remote: None] LIndexTrigger = 0x10000000, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LIndexTrigger], [RTouch, Remote: None] LHandTrigger = 0x20000000, ///< Maps to Physical Button: [Touch, LTouch: LHandTrigger], [Gamepad, RTouch, Remote: None] LThumbstick = 0x00000400, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstick], [RTouch, Remote: None] LThumbstickUp = 0x00000010, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickUp], [RTouch, Remote: None] LThumbstickDown = 0x00000020, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickDown], [RTouch, Remote: None] LThumbstickLeft = 0x00000040, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickLeft], [RTouch, Remote: None] LThumbstickRight = 0x00000080, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickRight], [RTouch, Remote: None] LTouchpad = 0x40000000, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, Remote: None] RShoulder = 0x00000008, ///< Maps to Physical Button: [Gamepad: RShoulder], [Touch, LTouch, RTouch, Remote: None] RIndexTrigger = 0x04000000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RIndexTrigger], [LTouch, Remote: None] RHandTrigger = 0x08000000, ///< Maps to Physical Button: [Touch, RTouch: RHandTrigger], [Gamepad, LTouch, Remote: None] RThumbstick = 0x00000004, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstick], [LTouch, Remote: None] RThumbstickUp = 0x00001000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickUp], [LTouch, Remote: None] RThumbstickDown = 0x00002000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickDown], [LTouch, Remote: None] RThumbstickLeft = 0x00004000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickLeft], [LTouch, Remote: None] RThumbstickRight = 0x00008000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickRight], [LTouch, Remote: None] RTouchpad = unchecked((int)0x80000000),///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, Remote: None] DpadUp = 0x00010000, ///< Maps to Physical Button: [Gamepad, Remote: DpadUp], [Touch, LTouch, RTouch: None] DpadDown = 0x00020000, ///< Maps to Physical Button: [Gamepad, Remote: DpadDown], [Touch, LTouch, RTouch: None] DpadLeft = 0x00040000, ///< Maps to Physical Button: [Gamepad, Remote: DpadLeft], [Touch, LTouch, RTouch: None] DpadRight = 0x00080000, ///< Maps to Physical Button: [Gamepad, Remote: DpadRight], [Touch, LTouch, RTouch: None] Any = ~None, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, Remote: Any] } [Flags] /// Virtual capacitive touch mappings that allow the same input bindings to work across different controllers with capacitive touch support. public enum Touch { None = 0, ///< Maps to RawTouch: [Gamepad, Touch, LTouch, RTouch, Remote: None] One = Button.One, ///< Maps to RawTouch: [Touch, RTouch: A], [LTouch: X], [Gamepad, Remote: None] Two = Button.Two, ///< Maps to RawTouch: [Touch, RTouch: B], [LTouch: Y], [Gamepad, Remote: None] Three = Button.Three, ///< Maps to RawTouch: [Touch: X], [Gamepad, LTouch, RTouch, Remote: None] Four = Button.Four, ///< Maps to RawTouch: [Touch: Y], [Gamepad, LTouch, RTouch, Remote: None] PrimaryIndexTrigger = Button.PrimaryIndexTrigger, ///< Maps to RawTouch: [Touch, LTouch: LIndexTrigger], [RTouch: RIndexTrigger], [Gamepad, Remote: None] PrimaryThumbstick = Button.PrimaryThumbstick, ///< Maps to RawTouch: [Touch, LTouch: LThumbstick], [RTouch: RThumbstick], [Gamepad, Remote: None] PrimaryThumbRest = 0x00001000, ///< Maps to RawTouch: [Touch, LTouch: LThumbRest], [RTouch: RThumbRest], [Gamepad, Remote: None] PrimaryTouchpad = Button.PrimaryTouchpad, ///< Maps to RawTouch: [Gamepad, Touch, LTouch, RTouch, Remote: None] SecondaryIndexTrigger = Button.SecondaryIndexTrigger, ///< Maps to RawTouch: [Touch: RIndexTrigger], [Gamepad, LTouch, RTouch, Remote: None] SecondaryThumbstick = Button.SecondaryThumbstick, ///< Maps to RawTouch: [Touch: RThumbstick], [Gamepad, LTouch, RTouch, Remote: None] SecondaryThumbRest = 0x00100000, ///< Maps to RawTouch: [Touch: RThumbRest], [Gamepad, LTouch, RTouch, Remote: None] SecondaryTouchpad = Button.SecondaryTouchpad, ///< Maps to RawTouch: [Gamepad, Touch, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to RawTouch: [Touch, LTouch, RTouch: Any], [Gamepad, Remote: None] } [Flags] /// Raw capacitive touch mappings that can be used to directly query the state of a controller. public enum RawTouch { None = 0, ///< Maps to Physical Touch: [Gamepad, Touch, LTouch, RTouch, Remote: None] A = RawButton.A, ///< Maps to Physical Touch: [Touch, RTouch: A], [Gamepad, LTouch, Remote: None] B = RawButton.B, ///< Maps to Physical Touch: [Touch, RTouch: B], [Gamepad, LTouch, Remote: None] X = RawButton.X, ///< Maps to Physical Touch: [Touch, LTouch: X], [Gamepad, RTouch, Remote: None] Y = RawButton.Y, ///< Maps to Physical Touch: [Touch, LTouch: Y], [Gamepad, RTouch, Remote: None] LIndexTrigger = 0x00001000, ///< Maps to Physical Touch: [Touch, LTouch: LIndexTrigger], [Gamepad, RTouch, Remote: None] LThumbstick = RawButton.LThumbstick, ///< Maps to Physical Touch: [Touch, LTouch: LThumbstick], [Gamepad, RTouch, Remote: None] LThumbRest = 0x00000800, ///< Maps to Physical Touch: [Touch, LTouch: LThumbRest], [Gamepad, RTouch, Remote: None] LTouchpad = RawButton.LTouchpad, ///< Maps to Physical Touch: [Gamepad, Touch, LTouch, RTouch, Remote: None] RIndexTrigger = 0x00000010, ///< Maps to Physical Touch: [Touch, RTouch: RIndexTrigger], [Gamepad, LTouch, Remote: None] RThumbstick = RawButton.RThumbstick, ///< Maps to Physical Touch: [Touch, RTouch: RThumbstick], [Gamepad, LTouch, Remote: None] RThumbRest = 0x00000008, ///< Maps to Physical Touch: [Touch, RTouch: RThumbRest], [Gamepad, LTouch, Remote: None] RTouchpad = RawButton.RTouchpad, ///< Maps to Physical Touch: [Gamepad, Touch, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to Physical Touch: [Touch, LTouch, RTouch: Any], [Gamepad, Remote: None] } [Flags] /// Virtual near touch mappings that allow the same input bindings to work across different controllers with near touch support. /// A near touch uses the capacitive touch sensors of a controller to detect approximate finger proximity prior to a full touch being reported. public enum NearTouch { None = 0, ///< Maps to RawNearTouch: [Gamepad, Touch, LTouch, RTouch, Remote: None] PrimaryIndexTrigger = 0x00000001, ///< Maps to RawNearTouch: [Touch, LTouch: LIndexTrigger], [RTouch: RIndexTrigger], [Gamepad, Remote: None] PrimaryThumbButtons = 0x00000002, ///< Maps to RawNearTouch: [Touch, LTouch: LThumbButtons], [RTouch: RThumbButtons], [Gamepad, Remote: None] SecondaryIndexTrigger = 0x00000004, ///< Maps to RawNearTouch: [Touch: RIndexTrigger], [Gamepad, LTouch, RTouch, Remote: None] SecondaryThumbButtons = 0x00000008, ///< Maps to RawNearTouch: [Touch: RThumbButtons], [Gamepad, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to RawNearTouch: [Touch, LTouch, RTouch: Any], [Gamepad, Remote: None] } [Flags] /// Raw near touch mappings that can be used to directly query the state of a controller. public enum RawNearTouch { None = 0, ///< Maps to Physical NearTouch: [Gamepad, Touch, LTouch, RTouch, Remote: None] LIndexTrigger = 0x00000001, ///< Maps to Physical NearTouch: [Touch, LTouch: Implies finger is in close proximity to LIndexTrigger.], [Gamepad, RTouch, Remote: None] LThumbButtons = 0x00000002, ///< Maps to Physical NearTouch: [Touch, LTouch: Implies thumb is in close proximity to LThumbstick OR X/Y buttons.], [Gamepad, RTouch, Remote: None] RIndexTrigger = 0x00000004, ///< Maps to Physical NearTouch: [Touch, RTouch: Implies finger is in close proximity to RIndexTrigger.], [Gamepad, LTouch, Remote: None] RThumbButtons = 0x00000008, ///< Maps to Physical NearTouch: [Touch, RTouch: Implies thumb is in close proximity to RThumbstick OR A/B buttons.], [Gamepad, LTouch, Remote: None] Any = ~None, ///< Maps to Physical NearTouch: [Touch, LTouch, RTouch: Any], [Gamepad, Remote: None] } [Flags] /// Virtual 1-dimensional axis (float) mappings that allow the same input bindings to work across different controllers. public enum Axis1D { None = 0, ///< Maps to RawAxis1D: [Gamepad, Touch, LTouch, RTouch, Remote: None] PrimaryIndexTrigger = 0x01, ///< Maps to RawAxis1D: [Gamepad, Touch, LTouch: LIndexTrigger], [RTouch: RIndexTrigger], [Remote: None] PrimaryHandTrigger = 0x04, ///< Maps to RawAxis1D: [Touch, LTouch: LHandTrigger], [RTouch: RHandTrigger], [Gamepad, Remote: None] SecondaryIndexTrigger = 0x02, ///< Maps to RawAxis1D: [Gamepad, Touch: RIndexTrigger], [LTouch, RTouch, Remote: None] SecondaryHandTrigger = 0x08, ///< Maps to RawAxis1D: [Touch: RHandTrigger], [Gamepad, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to RawAxis1D: [Gamepad, Touch, LTouch, RTouch: Any], [Remote: None] } [Flags] /// Raw 1-dimensional axis (float) mappings that can be used to directly query the state of a controller. public enum RawAxis1D { None = 0, ///< Maps to Physical Axis1D: [Gamepad, Touch, LTouch, RTouch, Remote: None] LIndexTrigger = 0x01, ///< Maps to Physical Axis1D: [Gamepad, Touch, LTouch: LIndexTrigger], [RTouch, Remote: None] LHandTrigger = 0x04, ///< Maps to Physical Axis1D: [Touch, LTouch: LHandTrigger], [Gamepad, RTouch, Remote: None] RIndexTrigger = 0x02, ///< Maps to Physical Axis1D: [Gamepad, Touch, RTouch: RIndexTrigger], [LTouch, Remote: None] RHandTrigger = 0x08, ///< Maps to Physical Axis1D: [Touch, RTouch: RHandTrigger], [Gamepad, LTouch, Remote: None] Any = ~None, ///< Maps to Physical Axis1D: [Gamepad, Touch, LTouch, RTouch: Any], [Remote: None] } [Flags] /// Virtual 2-dimensional axis (Vector2) mappings that allow the same input bindings to work across different controllers. public enum Axis2D { None = 0, ///< Maps to RawAxis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] PrimaryThumbstick = 0x01, ///< Maps to RawAxis2D: [Gamepad, Touch, LTouch: LThumbstick], [RTouch: RThumbstick], [Remote: None] PrimaryTouchpad = 0x04, ///< Maps to RawAxis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] SecondaryThumbstick = 0x02, ///< Maps to RawAxis2D: [Gamepad, Touch: RThumbstick], [LTouch, RTouch, Remote: None] SecondaryTouchpad = 0x08, ///< Maps to RawAxis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to RawAxis2D: [Gamepad, Touch, LTouch, RTouch: Any], [Remote: None] } [Flags] /// Raw 2-dimensional axis (Vector2) mappings that can be used to directly query the state of a controller. public enum RawAxis2D { None = 0, ///< Maps to Physical Axis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] LThumbstick = 0x01, ///< Maps to Physical Axis2D: [Gamepad, Touch, LTouch: LThumbstick], [RTouch, Remote: None] LTouchpad = 0x04, ///< Maps to Physical Axis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] RThumbstick = 0x02, ///< Maps to Physical Axis2D: [Gamepad, Touch, RTouch: RThumbstick], [LTouch, Remote: None] RTouchpad = 0x08, ///< Maps to Physical Axis2D: [Gamepad, Touch, LTouch, RTouch, Remote: None] Any = ~None, ///< Maps to Physical Axis2D: [Gamepad, Touch, LTouch, RTouch: Any], [Remote: None] } [Flags] /// OpenVR Controller State Enum public enum OpenVRButton : ulong { None = 0, Two = 0x0002, Thumbstick = 0x100000000, Grip = 0x0004, } [Flags] /// Identifies a controller which can be used to query the virtual or raw input state. public enum Controller { None = OVRPlugin.Controller.None, ///< Null controller. LTouch = OVRPlugin.Controller.LTouch, ///< Left Oculus Touch controller. Virtual input mapping differs from the combined L/R Touch mapping. RTouch = OVRPlugin.Controller.RTouch, ///< Right Oculus Touch controller. Virtual input mapping differs from the combined L/R Touch mapping. Touch = OVRPlugin.Controller.Touch, ///< Combined Left/Right pair of Oculus Touch controllers. Remote = OVRPlugin.Controller.Remote, ///< Oculus Remote controller. Gamepad = OVRPlugin.Controller.Gamepad, ///< Xbox 360 or Xbox One gamepad on PC. Generic gamepad on Android. Hands = OVRPlugin.Controller.Hands, ///< Left Hand provided by hand-tracking. LHand = OVRPlugin.Controller.LHand, ///< Left Hand provided by hand-tracking. RHand = OVRPlugin.Controller.RHand, ///< Right Hand provided by hand-tracking. Active = OVRPlugin.Controller.Active, ///< Default controller. Represents the controller that most recently registered a button press from the user. All = OVRPlugin.Controller.All, ///< Represents the logical OR of all controllers. } public enum Handedness { Unsupported = OVRPlugin.Handedness.Unsupported, LeftHanded = OVRPlugin.Handedness.LeftHanded, RightHanded = OVRPlugin.Handedness.RightHanded, } private static readonly float AXIS_AS_BUTTON_THRESHOLD = 0.5f; private static readonly float AXIS_DEADZONE_THRESHOLD = 0.2f; private static List controllers; private static Controller activeControllerType = Controller.None; private static Controller connectedControllerTypes = Controller.None; private static OVRPlugin.Step stepType = OVRPlugin.Step.Render; private static int fixedUpdateCount = 0; private static bool _pluginSupportsActiveController = false; private static bool _pluginSupportsActiveControllerCached = false; private static System.Version _pluginSupportsActiveControllerMinVersion = new System.Version(1, 9, 0); private static bool pluginSupportsActiveController { get { if (!_pluginSupportsActiveControllerCached) { bool isSupportedPlatform = true; #if (UNITY_ANDROID && !UNITY_EDITOR) || UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX isSupportedPlatform = false; #endif _pluginSupportsActiveController = isSupportedPlatform && (OVRPlugin.version >= _pluginSupportsActiveControllerMinVersion); _pluginSupportsActiveControllerCached = true; } return _pluginSupportsActiveController; } } /// /// Creates an instance of OVRInput. /// static OVRInput() { controllers = new List { #if UNITY_ANDROID && !UNITY_EDITOR new OVRControllerGamepadAndroid(), new OVRControllerTouch(), new OVRControllerLTouch(), new OVRControllerRTouch(), new OVRControllerHands(), new OVRControllerLHand(), new OVRControllerRHand(), #elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX new OVRControllerGamepadMac(), #else new OVRControllerGamepadPC(), new OVRControllerTouch(), new OVRControllerLTouch(), new OVRControllerRTouch(), new OVRControllerHands(), new OVRControllerLHand(), new OVRControllerRHand(), new OVRControllerRemote(), #endif }; InitHapticInfo(); } /// /// Updates the internal state of OVRInput. Must be called manually if used independently from OVRManager. /// public static void Update() { connectedControllerTypes = Controller.None; stepType = OVRPlugin.Step.Render; fixedUpdateCount = 0; if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) { UpdateXRControllerNodeIds(); UpdateXRControllerHaptics(); } for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; connectedControllerTypes |= controller.Update(); if ((connectedControllerTypes & controller.controllerType) != 0) { RawButton rawButtonMask = RawButton.Any; RawTouch rawTouchMask = RawTouch.Any; if (Get(rawButtonMask, controller.controllerType) || Get(rawTouchMask, controller.controllerType)) { activeControllerType = controller.controllerType; } } } if ((activeControllerType == Controller.LTouch) || (activeControllerType == Controller.RTouch)) { if ((connectedControllerTypes & Controller.Touch) == Controller.Touch) { // If either Touch controller is Active and both Touch controllers are connected, set both to Active. activeControllerType = Controller.Touch; } } if ((activeControllerType == Controller.LHand) || (activeControllerType == Controller.RHand)) { if ((connectedControllerTypes & Controller.Hands) == Controller.Hands) { // If either Hand controller is Active and both Hand controllers are connected, set both to Active. activeControllerType = Controller.Hands; } } if ((connectedControllerTypes & activeControllerType) == 0) { activeControllerType = Controller.None; } if ( OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus && pluginSupportsActiveController) { Controller localActiveController = activeControllerType; // override locally derived active and connected controllers if plugin provides more accurate data connectedControllerTypes = (OVRInput.Controller)OVRPlugin.GetConnectedControllers(); activeControllerType = (OVRInput.Controller)OVRPlugin.GetActiveController(); // unless the plugin reports none and we locally detected hands as the active controller if (activeControllerType == Controller.None && ((localActiveController & Controller.Hands) != 0)) { activeControllerType = localActiveController; } } else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) { activeControllerType = connectedControllerTypes; } } /// /// Updates the internal physics state of OVRInput. Must be called manually if used independently from OVRManager. /// public static void FixedUpdate() { if (OVRPlugin.nativeXrApi != OVRPlugin.XrApi.OpenXR) { stepType = OVRPlugin.Step.Physics; double predictionSeconds = (double)fixedUpdateCount * Time.fixedDeltaTime / Mathf.Max(Time.timeScale, 1e-6f); fixedUpdateCount++; OVRPlugin.UpdateNodePhysicsPoses(0, predictionSeconds); } } /// /// Returns true if the given Controller's orientation is currently tracked. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return false. /// public static bool GetControllerOrientationTracked(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: return OVRPlugin.GetNodeOrientationTracked(OVRPlugin.Node.HandLeft); case Controller.RTouch: case Controller.RHand: return OVRPlugin.GetNodeOrientationTracked(OVRPlugin.Node.HandRight); default: return false; } } /// /// Returns true if the given Controller's orientation is currently valid. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return false. /// public static bool GetControllerOrientationValid(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: return OVRPlugin.GetNodeOrientationValid(OVRPlugin.Node.HandLeft); case Controller.RTouch: case Controller.RHand: return OVRPlugin.GetNodeOrientationValid(OVRPlugin.Node.HandRight); default: return false; } } /// /// Returns true if the given Controller's position is currently tracked. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return false. /// public static bool GetControllerPositionTracked(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: return OVRPlugin.GetNodePositionTracked(OVRPlugin.Node.HandLeft); case Controller.RTouch: case Controller.RHand: return OVRPlugin.GetNodePositionTracked(OVRPlugin.Node.HandRight); default: return false; } } /// /// Returns true if the given Controller's position is currently valid. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return false. /// public static bool GetControllerPositionValid(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: return OVRPlugin.GetNodePositionValid(OVRPlugin.Node.HandLeft); case Controller.RTouch: case Controller.RHand: return OVRPlugin.GetNodePositionValid(OVRPlugin.Node.HandRight); default: return false; } } /// /// Gets the position of the given Controller local to its tracking space. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Vector3.zero. /// public static Vector3 GetLocalControllerPosition(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus) return OVRPlugin.GetNodePose(OVRPlugin.Node.HandLeft, stepType).ToOVRPose().position; else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) return openVRControllerDetails[0].localPosition; else { Vector3 retVec; if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.Position, OVRPlugin.Node.HandLeft, stepType, out retVec)) return retVec; return Vector3.zero; //Will never be hit, but is a final fallback. } case Controller.RTouch: case Controller.RHand: if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus) return OVRPlugin.GetNodePose(OVRPlugin.Node.HandRight, stepType).ToOVRPose().position; else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) return openVRControllerDetails[1].localPosition; else { Vector3 retVec; if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.Position, OVRPlugin.Node.HandRight, stepType, out retVec)) return retVec; return Vector3.zero; } default: return Vector3.zero; } } /// /// Gets the linear velocity of the given Controller local to its tracking space. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Vector3.zero. /// public static Vector3 GetLocalControllerVelocity(OVRInput.Controller controllerType) { Vector3 velocity = Vector3.zero; switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.Velocity, OVRPlugin.Node.HandLeft, stepType, out velocity)) { return velocity; } else { return Vector3.zero; } case Controller.RTouch: case Controller.RHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.Velocity, OVRPlugin.Node.HandRight, stepType, out velocity)) { return velocity; } else { return Vector3.zero; } default: return Vector3.zero; } } /// /// Gets the linear acceleration of the given Controller local to its tracking space. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Vector3.zero. /// public static Vector3 GetLocalControllerAcceleration(OVRInput.Controller controllerType) { Vector3 accel = Vector3.zero; switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.Acceleration, OVRPlugin.Node.HandLeft, stepType, out accel)) { return accel; } else { return Vector3.zero; } case Controller.RTouch: case Controller.RHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.Acceleration, OVRPlugin.Node.HandRight, stepType, out accel)) { return accel; } else { return Vector3.zero; } default: return Vector3.zero; } } /// /// Gets the rotation of the given Controller local to its tracking space. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Quaternion.identity. /// public static Quaternion GetLocalControllerRotation(OVRInput.Controller controllerType) { switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus) return OVRPlugin.GetNodePose(OVRPlugin.Node.HandLeft, stepType).ToOVRPose().orientation; else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) return openVRControllerDetails[0].localOrientation; else { Quaternion retQuat; if (OVRNodeStateProperties.GetNodeStatePropertyQuaternion(Node.LeftHand, NodeStatePropertyType.Orientation, OVRPlugin.Node.HandLeft, stepType, out retQuat)) return retQuat; return Quaternion.identity; } case Controller.RTouch: case Controller.RHand: if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus) return OVRPlugin.GetNodePose(OVRPlugin.Node.HandRight, stepType).ToOVRPose().orientation; else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) return openVRControllerDetails[1].localOrientation; else { Quaternion retQuat; if (OVRNodeStateProperties.GetNodeStatePropertyQuaternion(Node.RightHand, NodeStatePropertyType.Orientation, OVRPlugin.Node.HandRight, stepType, out retQuat)) return retQuat; return Quaternion.identity; } default: return Quaternion.identity; } } /// /// Gets the angular velocity of the given Controller local to its tracking space in radians per second around each axis. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Vector3.zero. /// public static Vector3 GetLocalControllerAngularVelocity(OVRInput.Controller controllerType) { Vector3 velocity = Vector3.zero; switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.AngularVelocity, OVRPlugin.Node.HandLeft, stepType, out velocity)) { return velocity; } else { return Vector3.zero; } case Controller.RTouch: case Controller.RHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.AngularVelocity, OVRPlugin.Node.HandRight, stepType, out velocity)) { return velocity; } else { return Vector3.zero; } default: return Vector3.zero; } } /// /// Gets the angular acceleration of the given Controller local to its tracking space in radians per second per second around each axis. /// Only supported for Oculus LTouch and RTouch controllers. Non-tracked controllers will return Vector3.zero. /// public static Vector3 GetLocalControllerAngularAcceleration(OVRInput.Controller controllerType) { Vector3 accel = Vector3.zero; switch (controllerType) { case Controller.LTouch: case Controller.LHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.AngularAcceleration, OVRPlugin.Node.HandLeft, stepType, out accel)) { return accel; } else { return Vector3.zero; } case Controller.RTouch: case Controller.RHand: if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.AngularAcceleration, OVRPlugin.Node.HandRight, stepType, out accel)) { return accel; } else { return Vector3.zero; } default: return Vector3.zero; } } /// /// Gets the current position, rotation and velocity of given Controller local to its tracking space without prediction. /// Only supported for Oculus LTouch and RTouch controllers, when using OpenXR backend /// public static bool GetLocalControllerStatesWithoutPrediction(OVRInput.Controller controllerType, out Vector3 position, out Quaternion rotation, out Vector3 velocity, out Vector3 angularVelocity) { position = Vector3.zero; rotation = Quaternion.identity; velocity = Vector3.zero; angularVelocity = Vector3.zero; if (OVRManager.loadedXRDevice != OVRManager.XRDevice.Oculus) return false; if (OVRPlugin.nativeXrApi != OVRPlugin.XrApi.OpenXR) return false; OVRPlugin.PoseStatef poseState; switch (controllerType) { case Controller.LTouch: case Controller.LHand: poseState = OVRPlugin.GetNodePoseStateImmediate(OVRPlugin.Node.HandLeft); break; case Controller.RTouch: case Controller.RHand: poseState = OVRPlugin.GetNodePoseStateImmediate(OVRPlugin.Node.HandRight); break; default: return false; } if (GetControllerPositionValid(controllerType)) { position = poseState.Pose.ToOVRPose().position; velocity = poseState.Velocity.FromFlippedZVector3f(); } if (GetControllerOrientationValid(controllerType)) { rotation = poseState.Pose.ToOVRPose().orientation; angularVelocity = poseState.AngularVelocity.FromFlippedZVector3f(); } return true; } /// /// Gets the dominant hand that the user has specified in settings, for mobile devices. /// public static Handedness GetDominantHand() { return (Handedness) OVRPlugin.GetDominantHand(); } /// /// Gets the current state of the given virtual button mask with the given controller mask. /// Returns true if any masked button is down on any masked controller. /// public static bool Get(Button virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedButton(virtualMask, RawButton.None, controllerMask); } /// /// Gets the current state of the given raw button mask with the given controller mask. /// Returns true if any masked button is down on any masked controllers. /// public static bool Get(RawButton rawMask, Controller controllerMask = Controller.Active) { return GetResolvedButton(Button.None, rawMask, controllerMask); } private static bool GetResolvedButton(Button virtualMask, RawButton rawMask, Controller controllerMask) { if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawButton resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawButton)controller.currentState.Buttons & resolvedMask) != 0) { return true; } } } return false; } /// /// Gets the current down state of the given virtual button mask with the given controller mask. /// Returns true if any masked button was pressed this frame on any masked controller and no masked button was previously down last frame. /// public static bool GetDown(Button virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedButtonDown(virtualMask, RawButton.None, controllerMask); } /// /// Gets the current down state of the given raw button mask with the given controller mask. /// Returns true if any masked button was pressed this frame on any masked controller and no masked button was previously down last frame. /// public static bool GetDown(RawButton rawMask, Controller controllerMask = Controller.Active) { return GetResolvedButtonDown(Button.None, rawMask, controllerMask); } private static bool GetResolvedButtonDown(Button virtualMask, RawButton rawMask, Controller controllerMask) { bool down = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawButton resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawButton)controller.previousState.Buttons & resolvedMask) != 0) { return false; } if ((((RawButton)controller.currentState.Buttons & resolvedMask) != 0) && (((RawButton)controller.previousState.Buttons & resolvedMask) == 0)) { down = true; } } } return down; } /// /// Gets the current up state of the given virtual button mask with the given controller mask. /// Returns true if any masked button was released this frame on any masked controller and no other masked button is still down this frame. /// public static bool GetUp(Button virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedButtonUp(virtualMask, RawButton.None, controllerMask); } /// /// Gets the current up state of the given raw button mask with the given controller mask. /// Returns true if any masked button was released this frame on any masked controller and no other masked button is still down this frame. /// public static bool GetUp(RawButton rawMask, Controller controllerMask = Controller.Active) { return GetResolvedButtonUp(Button.None, rawMask, controllerMask); } private static bool GetResolvedButtonUp(Button virtualMask, RawButton rawMask, Controller controllerMask) { bool up = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawButton resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawButton)controller.currentState.Buttons & resolvedMask) != 0) { return false; } if ((((RawButton)controller.currentState.Buttons & resolvedMask) == 0) && (((RawButton)controller.previousState.Buttons & resolvedMask) != 0)) { up = true; } } } return up; } /// /// Gets the current state of the given virtual touch mask with the given controller mask. /// Returns true if any masked touch is down on any masked controller. /// public static bool Get(Touch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedTouch(virtualMask, RawTouch.None, controllerMask); } /// /// Gets the current state of the given raw touch mask with the given controller mask. /// Returns true if any masked touch is down on any masked controllers. /// public static bool Get(RawTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedTouch(Touch.None, rawMask, controllerMask); } private static bool GetResolvedTouch(Touch virtualMask, RawTouch rawMask, Controller controllerMask) { if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawTouch)controller.currentState.Touches & resolvedMask) != 0) { return true; } } } return false; } /// /// Gets the current down state of the given virtual touch mask with the given controller mask. /// Returns true if any masked touch was pressed this frame on any masked controller and no masked touch was previously down last frame. /// public static bool GetDown(Touch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedTouchDown(virtualMask, RawTouch.None, controllerMask); } /// /// Gets the current down state of the given raw touch mask with the given controller mask. /// Returns true if any masked touch was pressed this frame on any masked controller and no masked touch was previously down last frame. /// public static bool GetDown(RawTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedTouchDown(Touch.None, rawMask, controllerMask); } private static bool GetResolvedTouchDown(Touch virtualMask, RawTouch rawMask, Controller controllerMask) { bool down = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawTouch)controller.previousState.Touches & resolvedMask) != 0) { return false; } if ((((RawTouch)controller.currentState.Touches & resolvedMask) != 0) && (((RawTouch)controller.previousState.Touches & resolvedMask) == 0)) { down = true; } } } return down; } /// /// Gets the current up state of the given virtual touch mask with the given controller mask. /// Returns true if any masked touch was released this frame on any masked controller and no other masked touch is still down this frame. /// public static bool GetUp(Touch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedTouchUp(virtualMask, RawTouch.None, controllerMask); } /// /// Gets the current up state of the given raw touch mask with the given controller mask. /// Returns true if any masked touch was released this frame on any masked controller and no other masked touch is still down this frame. /// public static bool GetUp(RawTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedTouchUp(Touch.None, rawMask, controllerMask); } private static bool GetResolvedTouchUp(Touch virtualMask, RawTouch rawMask, Controller controllerMask) { bool up = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawTouch)controller.currentState.Touches & resolvedMask) != 0) { return false; } if ((((RawTouch)controller.currentState.Touches & resolvedMask) == 0) && (((RawTouch)controller.previousState.Touches & resolvedMask) != 0)) { up = true; } } } return up; } /// /// Gets the current state of the given virtual near touch mask with the given controller mask. /// Returns true if any masked near touch is down on any masked controller. /// public static bool Get(NearTouch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouch(virtualMask, RawNearTouch.None, controllerMask); } /// /// Gets the current state of the given raw near touch mask with the given controller mask. /// Returns true if any masked near touch is down on any masked controllers. /// public static bool Get(RawNearTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouch(NearTouch.None, rawMask, controllerMask); } private static bool GetResolvedNearTouch(NearTouch virtualMask, RawNearTouch rawMask, Controller controllerMask) { if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawNearTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawNearTouch)controller.currentState.NearTouches & resolvedMask) != 0) { return true; } } } return false; } /// /// Gets the current down state of the given virtual near touch mask with the given controller mask. /// Returns true if any masked near touch was pressed this frame on any masked controller and no masked near touch was previously down last frame. /// public static bool GetDown(NearTouch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouchDown(virtualMask, RawNearTouch.None, controllerMask); } /// /// Gets the current down state of the given raw near touch mask with the given controller mask. /// Returns true if any masked near touch was pressed this frame on any masked controller and no masked near touch was previously down last frame. /// public static bool GetDown(RawNearTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouchDown(NearTouch.None, rawMask, controllerMask); } private static bool GetResolvedNearTouchDown(NearTouch virtualMask, RawNearTouch rawMask, Controller controllerMask) { bool down = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawNearTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawNearTouch)controller.previousState.NearTouches & resolvedMask) != 0) { return false; } if ((((RawNearTouch)controller.currentState.NearTouches & resolvedMask) != 0) && (((RawNearTouch)controller.previousState.NearTouches & resolvedMask) == 0)) { down = true; } } } return down; } /// /// Gets the current up state of the given virtual near touch mask with the given controller mask. /// Returns true if any masked near touch was released this frame on any masked controller and no other masked near touch is still down this frame. /// public static bool GetUp(NearTouch virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouchUp(virtualMask, RawNearTouch.None, controllerMask); } /// /// Gets the current up state of the given raw near touch mask with the given controller mask. /// Returns true if any masked near touch was released this frame on any masked controller and no other masked near touch is still down this frame. /// public static bool GetUp(RawNearTouch rawMask, Controller controllerMask = Controller.Active) { return GetResolvedNearTouchUp(NearTouch.None, rawMask, controllerMask); } private static bool GetResolvedNearTouchUp(NearTouch virtualMask, RawNearTouch rawMask, Controller controllerMask) { bool up = false; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawNearTouch resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if (((RawNearTouch)controller.currentState.NearTouches & resolvedMask) != 0) { return false; } if ((((RawNearTouch)controller.currentState.NearTouches & resolvedMask) == 0) && (((RawNearTouch)controller.previousState.NearTouches & resolvedMask) != 0)) { up = true; } } } return up; } /// /// Gets the current state of the given virtual 1-dimensional axis mask on the given controller mask. /// Returns the value of the largest masked axis across all masked controllers. Values range from 0 to 1. /// public static float Get(Axis1D virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedAxis1D(virtualMask, RawAxis1D.None, controllerMask); } /// /// Gets the current state of the given raw 1-dimensional axis mask on the given controller mask. /// Returns the value of the largest masked axis across all masked controllers. Values range from 0 to 1. /// public static float Get(RawAxis1D rawMask, Controller controllerMask = Controller.Active) { return GetResolvedAxis1D(Axis1D.None, rawMask, controllerMask); } private static float GetResolvedAxis1D(Axis1D virtualMask, RawAxis1D rawMask, Controller controllerMask) { float maxAxis = 0.0f; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (OVRManager.loadedXRDevice != OVRManager.XRDevice.Oculus) controller.shouldApplyDeadzone = false; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawAxis1D resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if ((RawAxis1D.LIndexTrigger & resolvedMask) != 0) { float axis = controller.currentState.LIndexTrigger; if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis1D.RIndexTrigger & resolvedMask) != 0) { float axis = controller.currentState.RIndexTrigger; if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis1D.LHandTrigger & resolvedMask) != 0) { float axis = controller.currentState.LHandTrigger; if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis1D.RHandTrigger & resolvedMask) != 0) { float axis = controller.currentState.RHandTrigger; if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } } } return maxAxis; } /// /// Gets the current state of the given virtual 2-dimensional axis mask on the given controller mask. /// Returns the vector of the largest masked axis across all masked controllers. Values range from -1 to 1. /// public static Vector2 Get(Axis2D virtualMask, Controller controllerMask = Controller.Active) { return GetResolvedAxis2D(virtualMask, RawAxis2D.None, controllerMask); } /// /// Gets the current state of the given raw 2-dimensional axis mask on the given controller mask. /// Returns the vector of the largest masked axis across all masked controllers. Values range from -1 to 1. /// public static Vector2 Get(RawAxis2D rawMask, Controller controllerMask = Controller.Active) { return GetResolvedAxis2D(Axis2D.None, rawMask, controllerMask); } private static Vector2 GetResolvedAxis2D(Axis2D virtualMask, RawAxis2D rawMask, Controller controllerMask) { Vector2 maxAxis = Vector2.zero; if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (OVRManager.loadedXRDevice != OVRManager.XRDevice.Oculus) controller.shouldApplyDeadzone = false; if (ShouldResolveController(controller.controllerType, controllerMask)) { RawAxis2D resolvedMask = rawMask | controller.ResolveToRawMask(virtualMask); if ((RawAxis2D.LThumbstick & resolvedMask) != 0) { Vector2 axis = new Vector2( controller.currentState.LThumbstick.x, controller.currentState.LThumbstick.y); if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis2D.LTouchpad & resolvedMask) != 0) { Vector2 axis = new Vector2( controller.currentState.LTouchpad.x, controller.currentState.LTouchpad.y); //if (controller.shouldApplyDeadzone) // axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis2D.RThumbstick & resolvedMask) != 0) { Vector2 axis = new Vector2( controller.currentState.RThumbstick.x, controller.currentState.RThumbstick.y); if (controller.shouldApplyDeadzone) axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } if ((RawAxis2D.RTouchpad & resolvedMask) != 0) { Vector2 axis = new Vector2( controller.currentState.RTouchpad.x, controller.currentState.RTouchpad.y); //if (controller.shouldApplyDeadzone) // axis = CalculateDeadzone(axis, AXIS_DEADZONE_THRESHOLD); maxAxis = CalculateAbsMax(maxAxis, axis); } } } return maxAxis; } /// /// Returns a mask of all currently connected controller types. /// public static Controller GetConnectedControllers() { return connectedControllerTypes; } /// /// Returns true if the specified controller type is currently connected. /// public static bool IsControllerConnected(Controller controller) { return (connectedControllerTypes & controller) == controller; } /// /// Returns the current active controller type. /// public static Controller GetActiveController() { return activeControllerType; } private static void StartVibration(float amplitude, float duration, Node controllerNode) { int index = (controllerNode == Node.LeftHand) ? 0 : 1; hapticInfos[index].hapticsDurationPlayed = 0.0f; hapticInfos[index].hapticAmplitude = amplitude; hapticInfos[index].hapticsDuration = duration; hapticInfos[index].playingHaptics = (amplitude != 0.0f); hapticInfos[index].node = controllerNode; if (amplitude <= 0.0f || duration <= 0.0f) { hapticInfos[index].playingHaptics = false; } } private static int NUM_HAPTIC_CHANNELS = 2; private static HapticInfo[] hapticInfos; private static float OPENVR_MAX_HAPTIC_AMPLITUDE = 4000.0f; private static float HAPTIC_VIBRATION_DURATION_SECONDS = 2.0f; private static String OPENVR_TOUCH_NAME = "oculus_touch"; private static String OPENVR_VIVE_CONTROLLER_NAME = "vive_controller"; private static String OPENVR_WINDOWSMR_CONTROLLER_NAME = "holographic_controller"; [Flags] /// OpenVR Controller Enum public enum OpenVRController : ulong { Unknown = 0, OculusTouch = 1, ViveController = 2, WindowsMRController = 3 } [StructLayout(LayoutKind.Sequential)] public struct OpenVRControllerDetails { public OVR.OpenVR.VRControllerState_t state; public OpenVRController controllerType; public uint deviceID; public Vector3 localPosition; //Position relative to Tracking Space public Quaternion localOrientation; //Orientation relative to Tracking Space } public static OpenVRControllerDetails[] openVRControllerDetails = new OpenVRControllerDetails[2]; private class HapticInfo { public bool playingHaptics; public float hapticsDurationPlayed; public float hapticsDuration; public float hapticAmplitude; public Node node; } /// /// Sets OpenVR left and right controller poses local to tracking space /// public static void SetOpenVRLocalPose(Vector3 leftPos, Vector3 rightPos, Quaternion leftRot, Quaternion rightRot) { openVRControllerDetails[0].localPosition = leftPos; openVRControllerDetails[0].localOrientation = leftRot; openVRControllerDetails[1].localPosition = rightPos; openVRControllerDetails[1].localOrientation = rightRot; } /// /// Accesses OpenVR properties about a given deviceID. Especially useful for differentiating per type of OpenVR device (i.e. Oculus, Vive) /// public static string GetOpenVRStringProperty(OVR.OpenVR.ETrackedDeviceProperty prop, uint deviceId = OVR.OpenVR.OpenVR.k_unTrackedDeviceIndex_Hmd) { OVR.OpenVR.ETrackedPropertyError error = OVR.OpenVR.ETrackedPropertyError.TrackedProp_Success; OVR.OpenVR.CVRSystem system = OVR.OpenVR.OpenVR.System; if (system != null) { uint capacity = system.GetStringTrackedDeviceProperty(deviceId, prop, null, 0, ref error); if (capacity > 1) { var result = new System.Text.StringBuilder((int)capacity); system.GetStringTrackedDeviceProperty(deviceId, prop, result, capacity, ref error); return result.ToString(); } return (error != OVR.OpenVR.ETrackedPropertyError.TrackedProp_Success) ? error.ToString() : ""; } return ""; } /// /// Associates OpenVR device IDs with left and right motion controllers, for later haptic playback. /// private static void UpdateXRControllerNodeIds() { if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) { openVRControllerDetails[0].deviceID = OVR.OpenVR.OpenVR.k_unMaxTrackedDeviceCount; openVRControllerDetails[1].deviceID = OVR.OpenVR.OpenVR.k_unMaxTrackedDeviceCount; OVR.OpenVR.CVRSystem system = OVR.OpenVR.OpenVR.System; if (system != null) { for (uint id = 0; id < OVR.OpenVR.OpenVR.k_unMaxTrackedDeviceCount; id++) { OVR.OpenVR.ETrackedDeviceClass deviceClass = system.GetTrackedDeviceClass(id); if (deviceClass == OVR.OpenVR.ETrackedDeviceClass.Controller && system.IsTrackedDeviceConnected(id)) { OpenVRController controllerType; String controllerName = GetOpenVRStringProperty(OVR.OpenVR.ETrackedDeviceProperty.Prop_ControllerType_String, id); if (controllerName == OPENVR_TOUCH_NAME) controllerType = OpenVRController.OculusTouch; else if (controllerName == OPENVR_VIVE_CONTROLLER_NAME) controllerType = OpenVRController.ViveController; else if (controllerName == OPENVR_WINDOWSMR_CONTROLLER_NAME) controllerType = OpenVRController.WindowsMRController; else controllerType = OpenVRController.Unknown; OVR.OpenVR.ETrackedControllerRole role = system.GetControllerRoleForTrackedDeviceIndex(id); if (role == OVR.OpenVR.ETrackedControllerRole.LeftHand) { system.GetControllerState(id, ref openVRControllerDetails[0].state, (uint)Marshal.SizeOf(typeof(OVR.OpenVR.VRControllerState_t))); openVRControllerDetails[0].deviceID = id; openVRControllerDetails[0].controllerType = controllerType; connectedControllerTypes |= Controller.LTouch; } else if (role == OVR.OpenVR.ETrackedControllerRole.RightHand) { system.GetControllerState(id, ref openVRControllerDetails[1].state, (uint)Marshal.SizeOf(typeof(OVR.OpenVR.VRControllerState_t))); openVRControllerDetails[1].deviceID = id; openVRControllerDetails[1].controllerType = controllerType; connectedControllerTypes |= Controller.RTouch; } } } } } } /// /// Runs once a frame to update cross-platform haptic playback /// private static void UpdateXRControllerHaptics() { if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) { for (int i = 0; i < NUM_HAPTIC_CHANNELS; i++) { if (hapticInfos[i].playingHaptics) { hapticInfos[i].hapticsDurationPlayed += Time.deltaTime; PlayHapticImpulse(hapticInfos[i].hapticAmplitude, hapticInfos[i].node); if (hapticInfos[i].hapticsDurationPlayed >= hapticInfos[i].hapticsDuration) { hapticInfos[i].playingHaptics = false; } } } } } private static void InitHapticInfo() { hapticInfos = new HapticInfo[NUM_HAPTIC_CHANNELS]; for (int i = 0; i < NUM_HAPTIC_CHANNELS; i++) { hapticInfos[i] = new HapticInfo(); } } private static void PlayHapticImpulse(float amplitude, Node deviceNode) { OVR.OpenVR.CVRSystem system = OVR.OpenVR.OpenVR.System; if (system != null && amplitude != 0.0f) { uint controllerId = (deviceNode == Node.LeftHand) ? openVRControllerDetails[0].deviceID : openVRControllerDetails[1].deviceID; if (IsValidOpenVRDevice(controllerId)) system.TriggerHapticPulse(controllerId, 0, (char)(OPENVR_MAX_HAPTIC_AMPLITUDE * amplitude)); } } private static bool IsValidOpenVRDevice(uint deviceId) { return (deviceId >= 0 && deviceId < OVR.OpenVR.OpenVR.k_unMaxTrackedDeviceCount); } /// /// Activates vibration with the given frequency and amplitude with the given controller mask. /// Ignored on controllers that do not support vibration. Expected values range from 0 to 1. /// public static void SetControllerVibration(float frequency, float amplitude, Controller controllerMask = Controller.Active) { if (OVRManager.loadedXRDevice == OVRManager.XRDevice.Oculus) { if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { controller.SetControllerVibration(frequency, amplitude); } } } else if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR) { if (controllerMask == Controller.LTouch || controllerMask == Controller.RTouch) { Node controllerNode = (controllerMask == Controller.LTouch) ? Node.LeftHand : Node.RightHand; StartVibration(amplitude, HAPTIC_VIBRATION_DURATION_SECONDS, controllerNode); } } } /// /// Returns the battery percentage remaining for the specified controller. Values range from 0 to 100. /// Only applicable to controllers that report battery level. /// Returns 0 for controllers that do not report battery level. /// public static byte GetControllerBatteryPercentRemaining(Controller controllerMask = Controller.Active) { if ((controllerMask & Controller.Active) != 0) controllerMask |= activeControllerType; byte battery = 0; for (int i = 0; i < controllers.Count; i++) { OVRControllerBase controller = controllers[i]; if (ShouldResolveController(controller.controllerType, controllerMask)) { battery = controller.GetBatteryPercentRemaining(); break; } } return battery; } private static Vector2 CalculateAbsMax(Vector2 a, Vector2 b) { float absA = a.sqrMagnitude; float absB = b.sqrMagnitude; if (absA >= absB) return a; return b; } private static float CalculateAbsMax(float a, float b) { float absA = (a >= 0) ? a : -a; float absB = (b >= 0) ? b : -b; if (absA >= absB) return a; return b; } private static Vector2 CalculateDeadzone(Vector2 a, float deadzone) { if (a.sqrMagnitude <= (deadzone * deadzone)) return Vector2.zero; a *= ((a.magnitude - deadzone) / (1.0f - deadzone)); if (a.sqrMagnitude > 1.0f) return a.normalized; return a; } private static float CalculateDeadzone(float a, float deadzone) { float mag = (a >= 0) ? a : -a; if (mag <= deadzone) return 0.0f; a *= (mag - deadzone) / (1.0f - deadzone); if ((a * a) > 1.0f) return (a >= 0) ? 1.0f : -1.0f; return a; } private static bool ShouldResolveController(Controller controllerType, Controller controllerMask) { bool isValid = false; if ((controllerType & controllerMask) == controllerType) { isValid = true; } // If the mask requests both Touch controllers, reject the individual touch controllers. if (((controllerMask & Controller.Touch) == Controller.Touch) && ((controllerType & Controller.Touch) != 0) && ((controllerType & Controller.Touch) != Controller.Touch)) { isValid = false; } // If the mask requests both Hands, reject the individual hands. if (((controllerMask & Controller.Hands) == Controller.Hands) && ((controllerType & Controller.Hands) != 0) && ((controllerType & Controller.Hands) != Controller.Hands)) { isValid = false; } return isValid; } private abstract class OVRControllerBase { public class VirtualButtonMap { public RawButton None = RawButton.None; public RawButton One = RawButton.None; public RawButton Two = RawButton.None; public RawButton Three = RawButton.None; public RawButton Four = RawButton.None; public RawButton Start = RawButton.None; public RawButton Back = RawButton.None; public RawButton PrimaryShoulder = RawButton.None; public RawButton PrimaryIndexTrigger = RawButton.None; public RawButton PrimaryHandTrigger = RawButton.None; public RawButton PrimaryThumbstick = RawButton.None; public RawButton PrimaryThumbstickUp = RawButton.None; public RawButton PrimaryThumbstickDown = RawButton.None; public RawButton PrimaryThumbstickLeft = RawButton.None; public RawButton PrimaryThumbstickRight = RawButton.None; public RawButton PrimaryTouchpad = RawButton.None; public RawButton SecondaryShoulder = RawButton.None; public RawButton SecondaryIndexTrigger = RawButton.None; public RawButton SecondaryHandTrigger = RawButton.None; public RawButton SecondaryThumbstick = RawButton.None; public RawButton SecondaryThumbstickUp = RawButton.None; public RawButton SecondaryThumbstickDown = RawButton.None; public RawButton SecondaryThumbstickLeft = RawButton.None; public RawButton SecondaryThumbstickRight = RawButton.None; public RawButton SecondaryTouchpad = RawButton.None; public RawButton DpadUp = RawButton.None; public RawButton DpadDown = RawButton.None; public RawButton DpadLeft = RawButton.None; public RawButton DpadRight = RawButton.None; public RawButton Up = RawButton.None; public RawButton Down = RawButton.None; public RawButton Left = RawButton.None; public RawButton Right = RawButton.None; public RawButton ToRawMask(Button virtualMask) { RawButton rawMask = 0; if (virtualMask == Button.None) return RawButton.None; if ((virtualMask & Button.One) != 0) rawMask |= One; if ((virtualMask & Button.Two) != 0) rawMask |= Two; if ((virtualMask & Button.Three) != 0) rawMask |= Three; if ((virtualMask & Button.Four) != 0) rawMask |= Four; if ((virtualMask & Button.Start) != 0) rawMask |= Start; if ((virtualMask & Button.Back) != 0) rawMask |= Back; if ((virtualMask & Button.PrimaryShoulder) != 0) rawMask |= PrimaryShoulder; if ((virtualMask & Button.PrimaryIndexTrigger) != 0) rawMask |= PrimaryIndexTrigger; if ((virtualMask & Button.PrimaryHandTrigger) != 0) rawMask |= PrimaryHandTrigger; if ((virtualMask & Button.PrimaryThumbstick) != 0) rawMask |= PrimaryThumbstick; if ((virtualMask & Button.PrimaryThumbstickUp) != 0) rawMask |= PrimaryThumbstickUp; if ((virtualMask & Button.PrimaryThumbstickDown) != 0) rawMask |= PrimaryThumbstickDown; if ((virtualMask & Button.PrimaryThumbstickLeft) != 0) rawMask |= PrimaryThumbstickLeft; if ((virtualMask & Button.PrimaryThumbstickRight) != 0) rawMask |= PrimaryThumbstickRight; if ((virtualMask & Button.PrimaryTouchpad) != 0) rawMask |= PrimaryTouchpad; if ((virtualMask & Button.SecondaryShoulder) != 0) rawMask |= SecondaryShoulder; if ((virtualMask & Button.SecondaryIndexTrigger) != 0) rawMask |= SecondaryIndexTrigger; if ((virtualMask & Button.SecondaryHandTrigger) != 0) rawMask |= SecondaryHandTrigger; if ((virtualMask & Button.SecondaryThumbstick) != 0) rawMask |= SecondaryThumbstick; if ((virtualMask & Button.SecondaryThumbstickUp) != 0) rawMask |= SecondaryThumbstickUp; if ((virtualMask & Button.SecondaryThumbstickDown) != 0) rawMask |= SecondaryThumbstickDown; if ((virtualMask & Button.SecondaryThumbstickLeft) != 0) rawMask |= SecondaryThumbstickLeft; if ((virtualMask & Button.SecondaryThumbstickRight) != 0) rawMask |= SecondaryThumbstickRight; if ((virtualMask & Button.SecondaryTouchpad) != 0) rawMask |= SecondaryTouchpad; if ((virtualMask & Button.DpadUp) != 0) rawMask |= DpadUp; if ((virtualMask & Button.DpadDown) != 0) rawMask |= DpadDown; if ((virtualMask & Button.DpadLeft) != 0) rawMask |= DpadLeft; if ((virtualMask & Button.DpadRight) != 0) rawMask |= DpadRight; if ((virtualMask & Button.Up) != 0) rawMask |= Up; if ((virtualMask & Button.Down) != 0) rawMask |= Down; if ((virtualMask & Button.Left) != 0) rawMask |= Left; if ((virtualMask & Button.Right) != 0) rawMask |= Right; return rawMask; } } public class VirtualTouchMap { public RawTouch None = RawTouch.None; public RawTouch One = RawTouch.None; public RawTouch Two = RawTouch.None; public RawTouch Three = RawTouch.None; public RawTouch Four = RawTouch.None; public RawTouch PrimaryIndexTrigger = RawTouch.None; public RawTouch PrimaryThumbstick = RawTouch.None; public RawTouch PrimaryThumbRest = RawTouch.None; public RawTouch PrimaryTouchpad = RawTouch.None; public RawTouch SecondaryIndexTrigger = RawTouch.None; public RawTouch SecondaryThumbstick = RawTouch.None; public RawTouch SecondaryThumbRest = RawTouch.None; public RawTouch SecondaryTouchpad = RawTouch.None; public RawTouch ToRawMask(Touch virtualMask) { RawTouch rawMask = 0; if (virtualMask == Touch.None) return RawTouch.None; if ((virtualMask & Touch.One) != 0) rawMask |= One; if ((virtualMask & Touch.Two) != 0) rawMask |= Two; if ((virtualMask & Touch.Three) != 0) rawMask |= Three; if ((virtualMask & Touch.Four) != 0) rawMask |= Four; if ((virtualMask & Touch.PrimaryIndexTrigger) != 0) rawMask |= PrimaryIndexTrigger; if ((virtualMask & Touch.PrimaryThumbstick) != 0) rawMask |= PrimaryThumbstick; if ((virtualMask & Touch.PrimaryThumbRest) != 0) rawMask |= PrimaryThumbRest; if ((virtualMask & Touch.PrimaryTouchpad) != 0) rawMask |= PrimaryTouchpad; if ((virtualMask & Touch.SecondaryIndexTrigger) != 0) rawMask |= SecondaryIndexTrigger; if ((virtualMask & Touch.SecondaryThumbstick) != 0) rawMask |= SecondaryThumbstick; if ((virtualMask & Touch.SecondaryThumbRest) != 0) rawMask |= SecondaryThumbRest; if ((virtualMask & Touch.SecondaryTouchpad) != 0) rawMask |= SecondaryTouchpad; return rawMask; } } public class VirtualNearTouchMap { public RawNearTouch None = RawNearTouch.None; public RawNearTouch PrimaryIndexTrigger = RawNearTouch.None; public RawNearTouch PrimaryThumbButtons = RawNearTouch.None; public RawNearTouch SecondaryIndexTrigger = RawNearTouch.None; public RawNearTouch SecondaryThumbButtons = RawNearTouch.None; public RawNearTouch ToRawMask(NearTouch virtualMask) { RawNearTouch rawMask = 0; if (virtualMask == NearTouch.None) return RawNearTouch.None; if ((virtualMask & NearTouch.PrimaryIndexTrigger) != 0) rawMask |= PrimaryIndexTrigger; if ((virtualMask & NearTouch.PrimaryThumbButtons) != 0) rawMask |= PrimaryThumbButtons; if ((virtualMask & NearTouch.SecondaryIndexTrigger) != 0) rawMask |= SecondaryIndexTrigger; if ((virtualMask & NearTouch.SecondaryThumbButtons) != 0) rawMask |= SecondaryThumbButtons; return rawMask; } } public class VirtualAxis1DMap { public RawAxis1D None = RawAxis1D.None; public RawAxis1D PrimaryIndexTrigger = RawAxis1D.None; public RawAxis1D PrimaryHandTrigger = RawAxis1D.None; public RawAxis1D SecondaryIndexTrigger = RawAxis1D.None; public RawAxis1D SecondaryHandTrigger = RawAxis1D.None; public RawAxis1D ToRawMask(Axis1D virtualMask) { RawAxis1D rawMask = 0; if (virtualMask == Axis1D.None) return RawAxis1D.None; if ((virtualMask & Axis1D.PrimaryIndexTrigger) != 0) rawMask |= PrimaryIndexTrigger; if ((virtualMask & Axis1D.PrimaryHandTrigger) != 0) rawMask |= PrimaryHandTrigger; if ((virtualMask & Axis1D.SecondaryIndexTrigger) != 0) rawMask |= SecondaryIndexTrigger; if ((virtualMask & Axis1D.SecondaryHandTrigger) != 0) rawMask |= SecondaryHandTrigger; return rawMask; } } public class VirtualAxis2DMap { public RawAxis2D None = RawAxis2D.None; public RawAxis2D PrimaryThumbstick = RawAxis2D.None; public RawAxis2D PrimaryTouchpad = RawAxis2D.None; public RawAxis2D SecondaryThumbstick = RawAxis2D.None; public RawAxis2D SecondaryTouchpad = RawAxis2D.None; public RawAxis2D ToRawMask(Axis2D virtualMask) { RawAxis2D rawMask = 0; if (virtualMask == Axis2D.None) return RawAxis2D.None; if ((virtualMask & Axis2D.PrimaryThumbstick) != 0) rawMask |= PrimaryThumbstick; if ((virtualMask & Axis2D.PrimaryTouchpad) != 0) rawMask |= PrimaryTouchpad; if ((virtualMask & Axis2D.SecondaryThumbstick) != 0) rawMask |= SecondaryThumbstick; if ((virtualMask & Axis2D.SecondaryTouchpad) != 0) rawMask |= SecondaryTouchpad; return rawMask; } } public Controller controllerType = Controller.None; public VirtualButtonMap buttonMap = new VirtualButtonMap(); public VirtualTouchMap touchMap = new VirtualTouchMap(); public VirtualNearTouchMap nearTouchMap = new VirtualNearTouchMap(); public VirtualAxis1DMap axis1DMap = new VirtualAxis1DMap(); public VirtualAxis2DMap axis2DMap = new VirtualAxis2DMap(); public OVRPlugin.ControllerState4 previousState = new OVRPlugin.ControllerState4(); public OVRPlugin.ControllerState4 currentState = new OVRPlugin.ControllerState4(); public bool shouldApplyDeadzone = true; public OVRControllerBase() { ConfigureButtonMap(); ConfigureTouchMap(); ConfigureNearTouchMap(); ConfigureAxis1DMap(); ConfigureAxis2DMap(); } public virtual Controller Update() { OVRPlugin.ControllerState4 state; if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR && ( (controllerType & Controller.Touch) != 0) ) state = GetOpenVRControllerState(controllerType); else state = OVRPlugin.GetControllerState4((uint)controllerType); if (state.LIndexTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LIndexTrigger; if (state.LHandTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LHandTrigger; if (state.LThumbstick.y >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickUp; if (state.LThumbstick.y <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickDown; if (state.LThumbstick.x <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickLeft; if (state.LThumbstick.x >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickRight; if (state.RIndexTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RIndexTrigger; if (state.RHandTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RHandTrigger; if (state.RThumbstick.y >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickUp; if (state.RThumbstick.y <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickDown; if (state.RThumbstick.x <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickLeft; if (state.RThumbstick.x >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickRight; previousState = currentState; currentState = state; return ((Controller)currentState.ConnectedControllers & controllerType); } private OVRPlugin.ControllerState4 GetOpenVRControllerState(Controller controllerType) { OVRPlugin.ControllerState4 state = new OVRPlugin.ControllerState4(); if ((controllerType & Controller.LTouch) == Controller.LTouch && IsValidOpenVRDevice(openVRControllerDetails[0].deviceID)) { OVR.OpenVR.VRControllerState_t leftControllerState = openVRControllerDetails[0].state; if ((leftControllerState.ulButtonPressed & ((ulong)OpenVRButton.Two)) == (ulong)OpenVRButton.Two) state.Buttons |= (uint)RawButton.Y; if ((leftControllerState.ulButtonPressed & ((ulong)OpenVRButton.Thumbstick)) == (ulong)OpenVRButton.Thumbstick) state.Buttons |= (uint)RawButton.LThumbstick; state.LIndexTrigger = leftControllerState.rAxis1.x; if (openVRControllerDetails[0].controllerType == OpenVRController.OculusTouch || openVRControllerDetails[0].controllerType == OpenVRController.ViveController) { state.LThumbstick.x = leftControllerState.rAxis0.x; state.LThumbstick.y = leftControllerState.rAxis0.y; } else if (openVRControllerDetails[0].controllerType == OpenVRController.WindowsMRController) { state.LThumbstick.x = leftControllerState.rAxis2.x; state.LThumbstick.y = leftControllerState.rAxis2.y; } if (openVRControllerDetails[0].controllerType == OpenVRController.OculusTouch) state.LHandTrigger = leftControllerState.rAxis2.x; else if (openVRControllerDetails[0].controllerType == OpenVRController.ViveController || openVRControllerDetails[0].controllerType == OpenVRController.WindowsMRController) state.LHandTrigger = ((leftControllerState.ulButtonPressed & ((ulong)OpenVRButton.Grip)) == ((ulong)OpenVRButton.Grip)) ? 1 : 0; } if ((controllerType & Controller.RTouch) == Controller.RTouch && IsValidOpenVRDevice(openVRControllerDetails[1].deviceID)) { OVR.OpenVR.VRControllerState_t rightControllerState = openVRControllerDetails[1].state; if ((rightControllerState.ulButtonPressed & ((ulong)OpenVRButton.Two)) == (ulong)OpenVRButton.Two) state.Buttons |= (uint)RawButton.B; if ((rightControllerState.ulButtonPressed & ((ulong)OpenVRButton.Thumbstick)) == (ulong)OpenVRButton.Thumbstick) state.Buttons |= (uint)RawButton.RThumbstick; state.RIndexTrigger = rightControllerState.rAxis1.x; if (openVRControllerDetails[1].controllerType == OpenVRController.OculusTouch || openVRControllerDetails[1].controllerType == OpenVRController.ViveController) { state.RThumbstick.x = rightControllerState.rAxis0.x; state.RThumbstick.y = rightControllerState.rAxis0.y; } else if (openVRControllerDetails[1].controllerType == OpenVRController.WindowsMRController) { state.RThumbstick.x = rightControllerState.rAxis2.x; state.RThumbstick.y = rightControllerState.rAxis2.y; } if (openVRControllerDetails[1].controllerType == OpenVRController.OculusTouch) state.RHandTrigger = rightControllerState.rAxis2.x; else if (openVRControllerDetails[1].controllerType == OpenVRController.ViveController || openVRControllerDetails[1].controllerType == OpenVRController.WindowsMRController) state.RHandTrigger = ((rightControllerState.ulButtonPressed & ((ulong)OpenVRButton.Grip)) == ((ulong)OpenVRButton.Grip)) ? 1 : 0; } return state; } public virtual void SetControllerVibration(float frequency, float amplitude) { OVRPlugin.SetControllerVibration((uint)controllerType, frequency, amplitude); } public virtual byte GetBatteryPercentRemaining() { return 0; } public abstract void ConfigureButtonMap(); public abstract void ConfigureTouchMap(); public abstract void ConfigureNearTouchMap(); public abstract void ConfigureAxis1DMap(); public abstract void ConfigureAxis2DMap(); public RawButton ResolveToRawMask(Button virtualMask) { return buttonMap.ToRawMask(virtualMask); } public RawTouch ResolveToRawMask(Touch virtualMask) { return touchMap.ToRawMask(virtualMask); } public RawNearTouch ResolveToRawMask(NearTouch virtualMask) { return nearTouchMap.ToRawMask(virtualMask); } public RawAxis1D ResolveToRawMask(Axis1D virtualMask) { return axis1DMap.ToRawMask(virtualMask); } public RawAxis2D ResolveToRawMask(Axis2D virtualMask) { return axis2DMap.ToRawMask(virtualMask); } } private class OVRControllerTouch : OVRControllerBase { public OVRControllerTouch() { controllerType = Controller.Touch; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.B; buttonMap.Three = RawButton.X; buttonMap.Four = RawButton.Y; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.LIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.LHandTrigger; buttonMap.PrimaryThumbstick = RawButton.LThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.LThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.LThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.LThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.LThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.RIndexTrigger; buttonMap.SecondaryHandTrigger = RawButton.RHandTrigger; buttonMap.SecondaryThumbstick = RawButton.RThumbstick; buttonMap.SecondaryThumbstickUp = RawButton.RThumbstickUp; buttonMap.SecondaryThumbstickDown = RawButton.RThumbstickDown; buttonMap.SecondaryThumbstickLeft = RawButton.RThumbstickLeft; buttonMap.SecondaryThumbstickRight = RawButton.RThumbstickRight; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.LThumbstickUp; buttonMap.Down = RawButton.LThumbstickDown; buttonMap.Left = RawButton.LThumbstickLeft; buttonMap.Right = RawButton.LThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.A; touchMap.Two = RawTouch.B; touchMap.Three = RawTouch.X; touchMap.Four = RawTouch.Y; touchMap.PrimaryIndexTrigger = RawTouch.LIndexTrigger; touchMap.PrimaryThumbstick = RawTouch.LThumbstick; touchMap.PrimaryThumbRest = RawTouch.LThumbRest; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.RIndexTrigger; touchMap.SecondaryThumbstick = RawTouch.RThumbstick; touchMap.SecondaryThumbRest = RawTouch.RThumbRest; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.LIndexTrigger; nearTouchMap.PrimaryThumbButtons = RawNearTouch.LThumbButtons; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.RIndexTrigger; nearTouchMap.SecondaryThumbButtons = RawNearTouch.RThumbButtons; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.LIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.LHandTrigger; axis1DMap.SecondaryIndexTrigger = RawAxis1D.RIndexTrigger; axis1DMap.SecondaryHandTrigger = RawAxis1D.RHandTrigger; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.LThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.RThumbstick; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { byte leftBattery = currentState.LBatteryPercentRemaining; byte rightBattery = currentState.RBatteryPercentRemaining; byte minBattery = (leftBattery <= rightBattery) ? leftBattery : rightBattery; return minBattery; } } private class OVRControllerLTouch : OVRControllerBase { public OVRControllerLTouch() { controllerType = Controller.LTouch; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.X; buttonMap.Two = RawButton.Y; buttonMap.Three = RawButton.None; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.LIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.LHandTrigger; buttonMap.PrimaryThumbstick = RawButton.LThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.LThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.LThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.LThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.LThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.LThumbstickUp; buttonMap.Down = RawButton.LThumbstickDown; buttonMap.Left = RawButton.LThumbstickLeft; buttonMap.Right = RawButton.LThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.X; touchMap.Two = RawTouch.Y; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.LIndexTrigger; touchMap.PrimaryThumbstick = RawTouch.LThumbstick; touchMap.PrimaryThumbRest = RawTouch.LThumbRest; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.LIndexTrigger; nearTouchMap.PrimaryThumbButtons = RawNearTouch.LThumbButtons; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.LIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.LHandTrigger; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.LThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { return currentState.LBatteryPercentRemaining; } } private class OVRControllerRTouch : OVRControllerBase { public OVRControllerRTouch() { controllerType = Controller.RTouch; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.B; buttonMap.Three = RawButton.None; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.None; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.RIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.RHandTrigger; buttonMap.PrimaryThumbstick = RawButton.RThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.RThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.RThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.RThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.RThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.RThumbstickUp; buttonMap.Down = RawButton.RThumbstickDown; buttonMap.Left = RawButton.RThumbstickLeft; buttonMap.Right = RawButton.RThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.A; touchMap.Two = RawTouch.B; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.RIndexTrigger; touchMap.PrimaryThumbstick = RawTouch.RThumbstick; touchMap.PrimaryThumbRest = RawTouch.RThumbRest; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.RIndexTrigger; nearTouchMap.PrimaryThumbButtons = RawNearTouch.RThumbButtons; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.RIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.RHandTrigger; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.RThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { return currentState.RBatteryPercentRemaining; } } private class OVRControllerHands : OVRControllerBase { public OVRControllerHands() { controllerType = Controller.Hands; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.None; buttonMap.Three = RawButton.X; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.None; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.None; buttonMap.PrimaryThumbstickUp = RawButton.None; buttonMap.PrimaryThumbstickDown = RawButton.None; buttonMap.PrimaryThumbstickLeft = RawButton.None; buttonMap.PrimaryThumbstickRight = RawButton.None; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.None; buttonMap.Down = RawButton.None; buttonMap.Left = RawButton.None; buttonMap.Right = RawButton.None; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.None; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.None; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { byte leftBattery = currentState.LBatteryPercentRemaining; byte rightBattery = currentState.RBatteryPercentRemaining; byte minBattery = (leftBattery <= rightBattery) ? leftBattery : rightBattery; return minBattery; } } private class OVRControllerLHand : OVRControllerBase { public OVRControllerLHand() { controllerType = Controller.LHand; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.X; buttonMap.Two = RawButton.None; buttonMap.Three = RawButton.None; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.None; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.None; buttonMap.PrimaryThumbstickUp = RawButton.None; buttonMap.PrimaryThumbstickDown = RawButton.None; buttonMap.PrimaryThumbstickLeft = RawButton.None; buttonMap.PrimaryThumbstickRight = RawButton.None; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.None; buttonMap.Down = RawButton.None; buttonMap.Left = RawButton.None; buttonMap.Right = RawButton.None; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.None; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.None; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { return currentState.LBatteryPercentRemaining; } } private class OVRControllerRHand : OVRControllerBase { public OVRControllerRHand() { controllerType = Controller.RHand; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.None; buttonMap.Three = RawButton.None; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.None; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.None; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.None; buttonMap.PrimaryThumbstickUp = RawButton.None; buttonMap.PrimaryThumbstickDown = RawButton.None; buttonMap.PrimaryThumbstickLeft = RawButton.None; buttonMap.PrimaryThumbstickRight = RawButton.None; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.None; buttonMap.DpadDown = RawButton.None; buttonMap.DpadLeft = RawButton.None; buttonMap.DpadRight = RawButton.None; buttonMap.Up = RawButton.None; buttonMap.Down = RawButton.None; buttonMap.Left = RawButton.None; buttonMap.Right = RawButton.None; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.None; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.None; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override byte GetBatteryPercentRemaining() { return currentState.RBatteryPercentRemaining; } } private class OVRControllerRemote : OVRControllerBase { public OVRControllerRemote() { controllerType = Controller.Remote; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.Start; buttonMap.Two = RawButton.Back; buttonMap.Three = RawButton.None; buttonMap.Four = RawButton.None; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.Back; buttonMap.PrimaryShoulder = RawButton.None; buttonMap.PrimaryIndexTrigger = RawButton.None; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.None; buttonMap.PrimaryThumbstickUp = RawButton.None; buttonMap.PrimaryThumbstickDown = RawButton.None; buttonMap.PrimaryThumbstickLeft = RawButton.None; buttonMap.PrimaryThumbstickRight = RawButton.None; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.None; buttonMap.SecondaryIndexTrigger = RawButton.None; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.None; buttonMap.SecondaryThumbstickUp = RawButton.None; buttonMap.SecondaryThumbstickDown = RawButton.None; buttonMap.SecondaryThumbstickLeft = RawButton.None; buttonMap.SecondaryThumbstickRight = RawButton.None; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.DpadUp; buttonMap.DpadDown = RawButton.DpadDown; buttonMap.DpadLeft = RawButton.DpadLeft; buttonMap.DpadRight = RawButton.DpadRight; buttonMap.Up = RawButton.DpadUp; buttonMap.Down = RawButton.DpadDown; buttonMap.Left = RawButton.DpadLeft; buttonMap.Right = RawButton.DpadRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.None; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.None; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.None; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.None; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } } private class OVRControllerGamepadPC : OVRControllerBase { public OVRControllerGamepadPC() { controllerType = Controller.Gamepad; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.B; buttonMap.Three = RawButton.X; buttonMap.Four = RawButton.Y; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.Back; buttonMap.PrimaryShoulder = RawButton.LShoulder; buttonMap.PrimaryIndexTrigger = RawButton.LIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.LThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.LThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.LThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.LThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.LThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.RShoulder; buttonMap.SecondaryIndexTrigger = RawButton.RIndexTrigger; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.RThumbstick; buttonMap.SecondaryThumbstickUp = RawButton.RThumbstickUp; buttonMap.SecondaryThumbstickDown = RawButton.RThumbstickDown; buttonMap.SecondaryThumbstickLeft = RawButton.RThumbstickLeft; buttonMap.SecondaryThumbstickRight = RawButton.RThumbstickRight; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.DpadUp; buttonMap.DpadDown = RawButton.DpadDown; buttonMap.DpadLeft = RawButton.DpadLeft; buttonMap.DpadRight = RawButton.DpadRight; buttonMap.Up = RawButton.LThumbstickUp; buttonMap.Down = RawButton.LThumbstickDown; buttonMap.Left = RawButton.LThumbstickLeft; buttonMap.Right = RawButton.LThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.LIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.RIndexTrigger; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.LThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.RThumbstick; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } } private class OVRControllerGamepadMac : OVRControllerBase { /// An axis on the gamepad. private enum AxisGPC { None = -1, LeftXAxis = 0, LeftYAxis, RightXAxis, RightYAxis, LeftTrigger, RightTrigger, DPad_X_Axis, DPad_Y_Axis, Max, }; /// A button on the gamepad. public enum ButtonGPC { None = -1, A = 0, B, X, Y, Up, Down, Left, Right, Start, Back, LStick, RStick, LeftShoulder, RightShoulder, Max }; private bool initialized = false; public OVRControllerGamepadMac() { controllerType = Controller.Gamepad; initialized = OVR_GamepadController_Initialize(); } ~OVRControllerGamepadMac() { if (!initialized) return; OVR_GamepadController_Destroy(); } public override Controller Update() { if (!initialized) { return Controller.None; } OVRPlugin.ControllerState4 state = new OVRPlugin.ControllerState4(); bool result = OVR_GamepadController_Update(); if (result) state.ConnectedControllers = (uint)Controller.Gamepad; if (OVR_GamepadController_GetButton((int)ButtonGPC.A)) state.Buttons |= (uint)RawButton.A; if (OVR_GamepadController_GetButton((int)ButtonGPC.B)) state.Buttons |= (uint)RawButton.B; if (OVR_GamepadController_GetButton((int)ButtonGPC.X)) state.Buttons |= (uint)RawButton.X; if (OVR_GamepadController_GetButton((int)ButtonGPC.Y)) state.Buttons |= (uint)RawButton.Y; if (OVR_GamepadController_GetButton((int)ButtonGPC.Up)) state.Buttons |= (uint)RawButton.DpadUp; if (OVR_GamepadController_GetButton((int)ButtonGPC.Down)) state.Buttons |= (uint)RawButton.DpadDown; if (OVR_GamepadController_GetButton((int)ButtonGPC.Left)) state.Buttons |= (uint)RawButton.DpadLeft; if (OVR_GamepadController_GetButton((int)ButtonGPC.Right)) state.Buttons |= (uint)RawButton.DpadRight; if (OVR_GamepadController_GetButton((int)ButtonGPC.Start)) state.Buttons |= (uint)RawButton.Start; if (OVR_GamepadController_GetButton((int)ButtonGPC.Back)) state.Buttons |= (uint)RawButton.Back; if (OVR_GamepadController_GetButton((int)ButtonGPC.LStick)) state.Buttons |= (uint)RawButton.LThumbstick; if (OVR_GamepadController_GetButton((int)ButtonGPC.RStick)) state.Buttons |= (uint)RawButton.RThumbstick; if (OVR_GamepadController_GetButton((int)ButtonGPC.LeftShoulder)) state.Buttons |= (uint)RawButton.LShoulder; if (OVR_GamepadController_GetButton((int)ButtonGPC.RightShoulder)) state.Buttons |= (uint)RawButton.RShoulder; state.LThumbstick.x = OVR_GamepadController_GetAxis((int)AxisGPC.LeftXAxis); state.LThumbstick.y = OVR_GamepadController_GetAxis((int)AxisGPC.LeftYAxis); state.RThumbstick.x = OVR_GamepadController_GetAxis((int)AxisGPC.RightXAxis); state.RThumbstick.y = OVR_GamepadController_GetAxis((int)AxisGPC.RightYAxis); state.LIndexTrigger = OVR_GamepadController_GetAxis((int)AxisGPC.LeftTrigger); state.RIndexTrigger = OVR_GamepadController_GetAxis((int)AxisGPC.RightTrigger); if (state.LIndexTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LIndexTrigger; if (state.LHandTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LHandTrigger; if (state.LThumbstick.y >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickUp; if (state.LThumbstick.y <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickDown; if (state.LThumbstick.x <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickLeft; if (state.LThumbstick.x >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.LThumbstickRight; if (state.RIndexTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RIndexTrigger; if (state.RHandTrigger >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RHandTrigger; if (state.RThumbstick.y >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickUp; if (state.RThumbstick.y <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickDown; if (state.RThumbstick.x <= -AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickLeft; if (state.RThumbstick.x >= AXIS_AS_BUTTON_THRESHOLD) state.Buttons |= (uint)RawButton.RThumbstickRight; previousState = currentState; currentState = state; return ((Controller)currentState.ConnectedControllers & controllerType); } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.B; buttonMap.Three = RawButton.X; buttonMap.Four = RawButton.Y; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.Back; buttonMap.PrimaryShoulder = RawButton.LShoulder; buttonMap.PrimaryIndexTrigger = RawButton.LIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.LThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.LThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.LThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.LThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.LThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.RShoulder; buttonMap.SecondaryIndexTrigger = RawButton.RIndexTrigger; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.RThumbstick; buttonMap.SecondaryThumbstickUp = RawButton.RThumbstickUp; buttonMap.SecondaryThumbstickDown = RawButton.RThumbstickDown; buttonMap.SecondaryThumbstickLeft = RawButton.RThumbstickLeft; buttonMap.SecondaryThumbstickRight = RawButton.RThumbstickRight; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.DpadUp; buttonMap.DpadDown = RawButton.DpadDown; buttonMap.DpadLeft = RawButton.DpadLeft; buttonMap.DpadRight = RawButton.DpadRight; buttonMap.Up = RawButton.LThumbstickUp; buttonMap.Down = RawButton.LThumbstickDown; buttonMap.Left = RawButton.LThumbstickLeft; buttonMap.Right = RawButton.LThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.LIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.RIndexTrigger; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.LThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.RThumbstick; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } public override void SetControllerVibration(float frequency, float amplitude) { int gpcNode = 0; float gpcFrequency = frequency * 200.0f; //Map frequency from 0-1 CAPI range to 0-200 GPC range float gpcStrength = amplitude; OVR_GamepadController_SetVibration(gpcNode, gpcStrength, gpcFrequency); } private const string DllName = "OVRGamepad"; [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern bool OVR_GamepadController_Initialize(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern bool OVR_GamepadController_Destroy(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern bool OVR_GamepadController_Update(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern float OVR_GamepadController_GetAxis(int axis); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern bool OVR_GamepadController_GetButton(int button); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern bool OVR_GamepadController_SetVibration(int node, float strength, float frequency); } private class OVRControllerGamepadAndroid : OVRControllerBase { public OVRControllerGamepadAndroid() { controllerType = Controller.Gamepad; } public override void ConfigureButtonMap() { buttonMap.None = RawButton.None; buttonMap.One = RawButton.A; buttonMap.Two = RawButton.B; buttonMap.Three = RawButton.X; buttonMap.Four = RawButton.Y; buttonMap.Start = RawButton.Start; buttonMap.Back = RawButton.Back; buttonMap.PrimaryShoulder = RawButton.LShoulder; buttonMap.PrimaryIndexTrigger = RawButton.LIndexTrigger; buttonMap.PrimaryHandTrigger = RawButton.None; buttonMap.PrimaryThumbstick = RawButton.LThumbstick; buttonMap.PrimaryThumbstickUp = RawButton.LThumbstickUp; buttonMap.PrimaryThumbstickDown = RawButton.LThumbstickDown; buttonMap.PrimaryThumbstickLeft = RawButton.LThumbstickLeft; buttonMap.PrimaryThumbstickRight = RawButton.LThumbstickRight; buttonMap.PrimaryTouchpad = RawButton.None; buttonMap.SecondaryShoulder = RawButton.RShoulder; buttonMap.SecondaryIndexTrigger = RawButton.RIndexTrigger; buttonMap.SecondaryHandTrigger = RawButton.None; buttonMap.SecondaryThumbstick = RawButton.RThumbstick; buttonMap.SecondaryThumbstickUp = RawButton.RThumbstickUp; buttonMap.SecondaryThumbstickDown = RawButton.RThumbstickDown; buttonMap.SecondaryThumbstickLeft = RawButton.RThumbstickLeft; buttonMap.SecondaryThumbstickRight = RawButton.RThumbstickRight; buttonMap.SecondaryTouchpad = RawButton.None; buttonMap.DpadUp = RawButton.DpadUp; buttonMap.DpadDown = RawButton.DpadDown; buttonMap.DpadLeft = RawButton.DpadLeft; buttonMap.DpadRight = RawButton.DpadRight; buttonMap.Up = RawButton.LThumbstickUp; buttonMap.Down = RawButton.LThumbstickDown; buttonMap.Left = RawButton.LThumbstickLeft; buttonMap.Right = RawButton.LThumbstickRight; } public override void ConfigureTouchMap() { touchMap.None = RawTouch.None; touchMap.One = RawTouch.None; touchMap.Two = RawTouch.None; touchMap.Three = RawTouch.None; touchMap.Four = RawTouch.None; touchMap.PrimaryIndexTrigger = RawTouch.None; touchMap.PrimaryThumbstick = RawTouch.None; touchMap.PrimaryThumbRest = RawTouch.None; touchMap.PrimaryTouchpad = RawTouch.None; touchMap.SecondaryIndexTrigger = RawTouch.None; touchMap.SecondaryThumbstick = RawTouch.None; touchMap.SecondaryThumbRest = RawTouch.None; touchMap.SecondaryTouchpad = RawTouch.None; } public override void ConfigureNearTouchMap() { nearTouchMap.None = RawNearTouch.None; nearTouchMap.PrimaryIndexTrigger = RawNearTouch.None; nearTouchMap.PrimaryThumbButtons = RawNearTouch.None; nearTouchMap.SecondaryIndexTrigger = RawNearTouch.None; nearTouchMap.SecondaryThumbButtons = RawNearTouch.None; } public override void ConfigureAxis1DMap() { axis1DMap.None = RawAxis1D.None; axis1DMap.PrimaryIndexTrigger = RawAxis1D.LIndexTrigger; axis1DMap.PrimaryHandTrigger = RawAxis1D.None; axis1DMap.SecondaryIndexTrigger = RawAxis1D.RIndexTrigger; axis1DMap.SecondaryHandTrigger = RawAxis1D.None; } public override void ConfigureAxis2DMap() { axis2DMap.None = RawAxis2D.None; axis2DMap.PrimaryThumbstick = RawAxis2D.LThumbstick; axis2DMap.PrimaryTouchpad = RawAxis2D.None; axis2DMap.SecondaryThumbstick = RawAxis2D.RThumbstick; axis2DMap.SecondaryTouchpad = RawAxis2D.None; } } }