using UnityEngine; using UnityEngine.SceneManagement; #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN using XInputDotNetPure; #endif namespace XboxCtrlrInput { // ================= Enumerations ==================== // /// <summary> /// List of enumerated identifiers for Xbox controllers. /// </summary> /// <remarks> /// Do NOT change enum values /// </remarks> public enum XboxController { /// <summary> /// "All" Controllers is deprecated! Use "Any" instead. /// </summary> [System.Obsolete("Instead use XboxController.Any")] All = 0, Any = 0, First = 1, Second = 2, Third = 3, Fourth = 4 } /// <summary> /// List of enumerated identifiers for Xbox buttons. /// </summary> public enum XboxButton { A, B, X, Y, Start, Back, LeftStick, RightStick, LeftBumper, RightBumper, DPadUp, DPadDown, DPadLeft, DPadRight } /// <summary> /// List of enumerated identifiers for Xbox D-Pad directions. /// </summary> public enum XboxDPad { Up, Down, Left, Right } /// <summary> /// List of enumerated identifiers for Xbox axis. /// </summary> public enum XboxAxis { LeftStickX, LeftStickY, RightStickX, RightStickY, LeftTrigger, RightTrigger } // ================ Classes =================== // public static class XCI { // ------------ Public Methods --------------- // public static bool SetVibration(XboxController controller, float left, float right) { int controllerNumber = (int)controller; if (OnWindowsNative()) { GamePad.SetVibration((PlayerIndex)(controllerNumber - 1), left, right); } else { } return false; } // >>> For Buttons <<< // /// <summary> /// Returns <c>true</c> if the specified button is held down by any controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> public static bool GetButton(XboxButton button) { if (button.IsDPad()) return GetDPad(button.ToDPad()); if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); if( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Pressed ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, 0); if(Input.GetKey(btnCode)) { return true; } } return false; } /// <summary> /// Returns <c>true</c> if the specified button is held down by a specified controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the button. /// </param> public static bool GetButton(XboxButton button, XboxController controller) { if (button.IsDPad()) return GetDPad(button.ToDPad(), controller); if (controller == XboxController.Any) return GetButton(button); int controllerNumber = (int)controller; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); if( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Pressed ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, controllerNumber); if(Input.GetKey(btnCode)) { return true; } } return false; } /// <summary> /// Returns <c>true</c> at the frame the specified button starts to press down (not held down) by any controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> public static bool GetButtonDown(XboxButton button) { if (button.IsDPad()) return GetDPadDown(button.ToDPad()); if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); GamePadState ctrlrStatePrev = XInputGetSingleStatePrev(); if( ( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Pressed ) && ( XInputGetButtonState(ctrlrStatePrev.Buttons, button) == ButtonState.Released ) ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, 0); if(Input.GetKeyDown(btnCode)) { return true; } } return false; } /// <summary> /// Returns <c>true</c> at the frame the specified button starts to press down (not held down) by a specified controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the button. /// </param> public static bool GetButtonDown(XboxButton button, XboxController controller) { if (button.IsDPad()) return GetDPadDown(button.ToDPad(), controller); if (controller == XboxController.Any) return GetButtonDown(button); int controllerNumber = (int)controller; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); GamePadState ctrlrStatePrev = XInputGetPaticularStatePrev(controllerNumber); if( ( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Pressed ) && ( XInputGetButtonState(ctrlrStatePrev.Buttons, button) == ButtonState.Released ) ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, controllerNumber); if(Input.GetKeyDown(btnCode)) { return true; } } return false; } /// <summary> /// Returns <c>true</c> at the frame the specified button is released by any controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> public static bool GetButtonUp(XboxButton button) { if (button.IsDPad()) return GetDPadUp(button.ToDPad()); if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); GamePadState ctrlrStatePrev = XInputGetSingleStatePrev(); if( ( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Released ) && ( XInputGetButtonState(ctrlrStatePrev.Buttons, button) == ButtonState.Pressed ) ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, 0); if(Input.GetKeyUp(btnCode)) { return true; } } return false; } /// <summary> /// Returns <c>true</c> at the frame the specified button is released by a specified controller. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the button. /// </param> public static bool GetButtonUp(XboxButton button, XboxController controller) { if (button.IsDPad()) return GetDPadUp(button.ToDPad(), controller); if (controller == XboxController.Any) return GetButtonUp(button); int controllerNumber = (int)controller; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); GamePadState ctrlrStatePrev = XInputGetPaticularStatePrev(controllerNumber); if( ( XInputGetButtonState(ctrlrState.Buttons, button) == ButtonState.Released ) && ( XInputGetButtonState(ctrlrStatePrev.Buttons, button) == ButtonState.Pressed ) ) { return true; } #endif } else { string btnCode = DetermineButtonCode(button, controllerNumber); if(Input.GetKeyUp(btnCode)) { return true; } } return false; } // >>> For D-Pad <<< // /// <summary> /// Returns <c>true</c> if the specified D-Pad direction is pressed down by any controller. /// </summary> /// <param name='padDirection'> /// An identifier for the specified D-Pad direction to be tested. /// </param> public static bool GetDPad(XboxDPad padDirection) { bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); if( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Pressed ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, 0); r = Input.GetKey(inputCode); } else if(OnLinux() && IsControllerWireless()) { inputCode = DetermineDPadWirelessLinux(padDirection, 0); r = Input.GetKey(inputCode); } else // Windows Web Player and Linux Wired Controller { inputCode = DetermineDPad(padDirection, 0); switch(padDirection) { case XboxDPad.Up: r = Input.GetAxis(inputCode) > 0; break; case XboxDPad.Down: r = Input.GetAxis(inputCode) < 0; break; case XboxDPad.Left: r = Input.GetAxis(inputCode) < 0; break; case XboxDPad.Right: r = Input.GetAxis(inputCode) > 0; break; default: r = false; break; } } } return r; } /// <summary> /// Returns <c>true</c> if the specified D-Pad direction is pressed down by a specified controller. /// </summary> /// <param name='padDirection'> /// An identifier for the specified D-Pad direction to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the D-Pad. /// </param> public static bool GetDPad(XboxDPad padDirection, XboxController controller) { if (controller == XboxController.Any) return GetDPad(padDirection); int controllerNumber = (int)controller; bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); if( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Pressed ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, controllerNumber); r = Input.GetKey(inputCode); } else if(OnLinux() && IsControllerWireless(controllerNumber)) { inputCode = DetermineDPadWirelessLinux(padDirection, controllerNumber); r = Input.GetKey(inputCode); } else // Windows Web Player and Linux Wired Controller { inputCode = DetermineDPad(padDirection, controllerNumber); switch(padDirection) { case XboxDPad.Up: r = Input.GetAxis(inputCode) > 0; break; case XboxDPad.Down: r = Input.GetAxis(inputCode) < 0; break; case XboxDPad.Left: r = Input.GetAxis(inputCode) < 0; break; case XboxDPad.Right: r = Input.GetAxis(inputCode) > 0; break; default: r = false; break; } } } return r; } // From @ProjectEnder /// <summary> /// Returns <c>true</c> at the frame the specified button is released. /// Does NOT work on Linux with Wired Controllers. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> public static bool GetDPadUp(XboxDPad padDirection) { bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); GamePadState ctrlrStatePrev = XInputGetSingleStatePrev(); if( ( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Released ) && ( XInputGetDPadState(ctrlrStatePrev.DPad, padDirection) == ButtonState.Pressed ) ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, 0); r = Input.GetKeyUp(inputCode); } else if(OnLinux() && IsControllerWireless()) { inputCode = DetermineDPadWirelessLinux(padDirection, 0); r = Input.GetKeyUp(inputCode); } else { //Place Holder for Wired Linux r = false; } } return r; } // From @ProjectEnder /// <summary> /// Returns <c>true</c> at the frame the specified button is released by a specified controller. /// Does NOT work on Linux with Wired Controllers. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the button. /// </param> public static bool GetDPadUp(XboxDPad padDirection, XboxController controller) { if (controller == XboxController.Any) return GetDPadUp(padDirection); int controllerNumber = (int)controller; bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); GamePadState ctrlrStatePrev = XInputGetPaticularStatePrev(controllerNumber); if( ( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Released ) && ( XInputGetDPadState(ctrlrStatePrev.DPad, padDirection) == ButtonState.Pressed ) ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, controllerNumber); r = Input.GetKeyUp(inputCode); } else if(OnLinux() && IsControllerWireless(controllerNumber)) { inputCode = DetermineDPadWirelessLinux(padDirection, controllerNumber); r = Input.GetKeyUp(inputCode); } else { //Place Holder for Wired Linux r = false; } } return r; } // From @ProjectEnder /// <summary> /// Returns <c>true</c> at the frame the specified button is Pressed. /// Does NOT work on Linux with Wired Controllers. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> public static bool GetDPadDown(XboxDPad padDirection) { bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); GamePadState ctrlrStatePrev = XInputGetSingleStatePrev(); if( ( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Pressed ) && ( XInputGetDPadState(ctrlrStatePrev.DPad, padDirection) == ButtonState.Released ) ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, 0); r = Input.GetKeyDown(inputCode); } else if(OnLinux() && IsControllerWireless()) { inputCode = DetermineDPadWirelessLinux(padDirection, 0); r = Input.GetKeyDown(inputCode); } else { //Place Holder for Wired Linux r = false; } } return r; } // From @ProjectEnder /// <summary> /// Returns <c>true</c> at the frame the specified button is Pressed by a specified controller. /// Does NOT work on Linux with Wired Controllers. /// </summary> /// <param name='button'> /// Identifier for the Xbox button to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the button. /// </param> public static bool GetDPadDown(XboxDPad padDirection, XboxController controller) { if (controller == XboxController.Any) return GetDPadDown(padDirection); int controllerNumber = (int)controller; bool r = false; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(Time.frameCount < 2) { return false; } if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); GamePadState ctrlrStatePrev = XInputGetPaticularStatePrev(controllerNumber); if( ( XInputGetDPadState(ctrlrState.DPad, padDirection) == ButtonState.Pressed ) && ( XInputGetDPadState(ctrlrStatePrev.DPad, padDirection) == ButtonState.Released ) ) { return true; } #endif } else { string inputCode = ""; if(OnMac()) { inputCode = DetermineDPadMac(padDirection, controllerNumber); r = Input.GetKeyDown(inputCode); } else if(OnLinux() && IsControllerWireless(controllerNumber)) { inputCode = DetermineDPadWirelessLinux(padDirection, controllerNumber); r = Input.GetKeyDown(inputCode); } else { //Place Holder for Wired Linux r = false; } } return r; } // >>> For Axis <<< // /// <summary> /// Returns the analog number of the specified axis from any controller. /// </summary> /// <param name='axis'> /// An identifier for the specified Xbox axis to be tested. /// </param> public static float GetAxis(XboxAxis axis) { float r = 0.0f; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); if(axis == XboxAxis.LeftTrigger || axis == XboxAxis.RightTrigger) { r = XInputGetAxisState(ctrlrState.Triggers, axis); } else { r = XInputGetAxisState(ctrlrState.ThumbSticks, axis); } #endif } else { string axisCode = DetermineAxisCode(axis, 0); r = Input.GetAxis(axisCode); r = AdjustAxisValues(r, axis, 0); } return r; } /// <summary> /// Returns the float number of the specified axis from a specified controller. /// </summary> /// <param name='axis'> /// An identifier for the specified Xbox axis to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the axis. /// </param> public static float GetAxis(XboxAxis axis, XboxController controller) { if (controller == XboxController.Any) return GetAxis(axis); int controllerNumber = (int)controller; float r = 0.0f; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); if(axis == XboxAxis.LeftTrigger || axis == XboxAxis.RightTrigger) { r = XInputGetAxisState(ctrlrState.Triggers, axis); } else { r = XInputGetAxisState(ctrlrState.ThumbSticks, axis); } #endif } else { string axisCode = DetermineAxisCode(axis, controllerNumber); r = Input.GetAxis(axisCode); r = AdjustAxisValues(r, axis, controllerNumber); } return r; } /// <summary> /// Returns the float number of the specified axis from any controller without Unity's smoothing filter. /// </summary> /// <param name='axis'> /// An identifier for the specified Xbox axis to be tested. /// </param> public static float GetAxisRaw(XboxAxis axis) { float r = 0.0f; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetSingleState(); if(axis == XboxAxis.LeftTrigger || axis == XboxAxis.RightTrigger) { r = XInputGetAxisState(ctrlrState.Triggers, axis); } else { r = XInputGetAxisState(ctrlrState.ThumbSticks, axis); } #endif } else { string axisCode = DetermineAxisCode(axis, 0); r = Input.GetAxisRaw(axisCode); r = AdjustAxisValues(r, axis, 0); } return r; } /// <summary> /// Returns the float number of the specified axis from a specified controller without Unity's smoothing filter. /// </summary> /// <param name='axis'> /// An identifier for the specified Xbox axis to be tested. /// </param> /// <param name='controller'> /// An identifier for the specific controller on which to test the axis. /// </param> public static float GetAxisRaw(XboxAxis axis, XboxController controller) { if (controller == XboxController.Any) return GetAxisRaw(axis); int controllerNumber = (int)controller; float r = 0.0f; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); if(axis == XboxAxis.LeftTrigger || axis == XboxAxis.RightTrigger) { r = XInputGetAxisState(ctrlrState.Triggers, axis); } else { r = XInputGetAxisState(ctrlrState.ThumbSticks, axis); } #endif } else { string axisCode = DetermineAxisCode(axis, controllerNumber); r = Input.GetAxisRaw(axisCode); r = AdjustAxisValues(r, axis, controllerNumber); } return r; } // >>> Other important functions <<< // /// <summary> /// Returns the number of Xbox controllers plugged to the computer. /// </summary> public static int GetNumPluggedCtrlrs() { int r = 0; if(OnWindowsNative()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(!xiNumOfCtrlrsQueried || !XInputStillInCurrFrame()) { xiNumOfCtrlrsQueried = true; XInputUpdateAllStates(); } for(int i = 0; i < 4; i++) { if(xInputCtrlrs[i].IsConnected) { r++; } } #endif } else { string[] ctrlrNames = Input.GetJoystickNames(); for(int i = 0; i < ctrlrNames.Length; i++) { if(ctrlrNames[i].Contains("Xbox") || ctrlrNames[i].Contains("XBOX") || ctrlrNames[i].Contains("Microsoft")) { r++; } } } return r; } /// <summary> /// DEBUG function. Log all controller names to Unity's console. /// </summary> public static void DEBUG_LogControllerNames() { string[] cNames = Input.GetJoystickNames(); for(int i = 0; i < cNames.Length; i++) { Debug.Log("Ctrlr " + i.ToString() + ": " + cNames[i]); } } // From @xoorath /// <summary> /// DEPRECATED: /// Determines if the controller is plugged in the specified controllerNumber. /// CAUTION: Only works on Windows Native (Desktop and Editor)! /// </summary> /// <param name="controllerNumber"> /// An identifier for the specific controller on which to test the axis. An int between 1 and 4. /// </param> [System.Obsolete("Instead use IsPluggedIn(XboxController)")] public static bool IsPluggedIn(int controllerNumber) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN if(OnWindowsNative()) { if (!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState = XInputGetPaticularState(controllerNumber); return ctrlrState.IsConnected; } #endif // NOT IMPLEMENTED for other platforms return false; } // Based off @xoorath 's implementation /// <summary> /// Determines if the controller is plugged in the specified controllerNumber. /// Passing Any will evaluate if any controller is connected. /// CAUTION: Only works on Windows Native (Desktop and Editor)! /// </summary> /// <param name="controllerNumber"> /// An identifier for the specific controller on which to test the axis. /// Passing Any will evaluate if any controller is connected. /// </param> public static bool IsPluggedIn(XboxController controllerNumber) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN { if (OnWindowsNative()) { if (!XInputStillInCurrFrame()) { XInputUpdateAllStates(); } GamePadState ctrlrState; // If inquiring about any controller // TODO: Remove condition for XboxController.All when the time comes // Users of XCI: Feel free to remove XboxController.All if you like having no warnings if(controllerNumber == XboxController.Any || controllerNumber == XboxController.All) { // Examine all controllers it see if any are connected for(int i = 1; i <= 4; i++) { ctrlrState = XInputGetPaticularState(i); if(ctrlrState.IsConnected) { return true; } } } // If specifying a specific controller // Note: Casting only works if XboxController enums are values 1 to 4 (First, Second, Third, Fourth) ctrlrState = XInputGetPaticularState((int)controllerNumber); return ctrlrState.IsConnected; } } #endif // NOT IMPLEMENTED for other platforms return false; } //// // ------------- Private -------------- // //// // ------------ Methods --------------- // private static bool OnMac() { // All Mac mappings are based off TattieBogle Xbox Controller drivers // http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver // http://wiki.unity3d.com/index.php?title=Xbox360Controller return (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer ); } private static bool OnWindows() { return (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer ); } private static bool OnWindowsNative() { return (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer ); } private static bool OnLinux() { // Linux mapping based on observation of mapping from default drivers on Ubuntu 13.04 return Application.platform == RuntimePlatform.LinuxPlayer; } private static bool IsControllerWireless() { // 0 means for any controller return IsControllerWireless(0); } private static bool IsControllerWireless(int ctrlNum) { if (ctrlNum < 0 || ctrlNum > 4) return false; // If 0 is passed in, that assumes that only 1 controller is plugged in. if(ctrlNum == 0) { return ( (string) Input.GetJoystickNames()[0]).Contains("Wireless"); } return ( (string) Input.GetJoystickNames()[ctrlNum-1]).Contains("Wireless"); } private static bool IsControllerNumberValid(int ctrlrNum) { if(ctrlrNum > 0 && ctrlrNum <= 4) { return true; } else { Debug.LogError("XCI.IsControllerNumberValid(): " + "Invalid contoller number! Should be between 1 and 4."); } return false; } private static float RefactorRange(float oldRangeValue, int ctrlrNum, XboxAxis axis) { // HACK: On OS X, Left and right trigger under OSX return 0.5 until touched // Issue #16 on Github: https://github.com/JISyed/Unity-XboxCtrlrInput/issues/16 if(XCI.OnMac()) { if(axis == XboxAxis.LeftTrigger) { switch(ctrlrNum) { case 0: { if(!XCI.XciHandler.Instance.u3dTrigger0LeftIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger0LeftIsTouched = true; } else { return 0.0f; } } break; } case 1: { if(!XCI.XciHandler.Instance.u3dTrigger1LeftIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger1LeftIsTouched = true; } else { return 0.0f; } } break; } case 2: { if(!XCI.XciHandler.Instance.u3dTrigger2LeftIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger2LeftIsTouched = true; } else { return 0.0f; } } break; } case 3: { if(!XCI.XciHandler.Instance.u3dTrigger3LeftIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger3LeftIsTouched = true; } else { return 0.0f; } } break; } case 4: { if(!XCI.XciHandler.Instance.u3dTrigger4LeftIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger4LeftIsTouched = true; } else { return 0.0f; } } break; } default: break; } } else if(axis == XboxAxis.RightTrigger) { switch(ctrlrNum) { case 0: { if(!XCI.XciHandler.Instance.u3dTrigger0RightIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger0RightIsTouched = true; } else { return 0.0f; } } break; } case 1: { if(!XCI.XciHandler.Instance.u3dTrigger1RightIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger1RightIsTouched = true; } else { return 0.0f; } } break; } case 2: { if(!XCI.XciHandler.Instance.u3dTrigger2RightIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger2RightIsTouched = true; } else { return 0.0f; } } break; } case 3: { if(!XCI.XciHandler.Instance.u3dTrigger3RightIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger3RightIsTouched = true; } else { return 0.0f; } } break; } case 4: { if(!XCI.XciHandler.Instance.u3dTrigger4RightIsTouched) { if(oldRangeValue != 0.0f) { XCI.XciHandler.Instance.u3dTrigger4RightIsTouched = true; } else { return 0.0f; } } break; } default: break; } } } // Assumes you want to take a number from -1 to 1 range // And turn it into a number from a 0 to 1 range return ((oldRangeValue + 1.0f) / 2.0f ); } private static string DetermineButtonCode(XboxButton btn, int ctrlrNum) { string r = ""; string sJoyCode = ""; string sKeyCode = ""; bool invalidCode = false; if(ctrlrNum == 0) { sJoyCode = ""; } else { sJoyCode = " " + ctrlrNum.ToString(); } if(OnMac()) { switch(btn) { case XboxButton.A: sKeyCode = "16"; break; case XboxButton.B: sKeyCode = "17"; break; case XboxButton.X: sKeyCode = "18"; break; case XboxButton.Y: sKeyCode = "19"; break; case XboxButton.Start: sKeyCode = "9"; break; case XboxButton.Back: sKeyCode = "10"; break; case XboxButton.LeftStick: sKeyCode = "11"; break; case XboxButton.RightStick: sKeyCode = "12"; break; case XboxButton.LeftBumper: sKeyCode = "13"; break; case XboxButton.RightBumper: sKeyCode = "14"; break; default: invalidCode = true; break; } } else if (OnLinux()) { switch(btn) { case XboxButton.A: sKeyCode = "0"; break; case XboxButton.B: sKeyCode = "1"; break; case XboxButton.X: sKeyCode = "2"; break; case XboxButton.Y: sKeyCode = "3"; break; case XboxButton.Start: sKeyCode = "7"; break; case XboxButton.Back: sKeyCode = "6"; break; case XboxButton.LeftStick: sKeyCode = "9"; break; case XboxButton.RightStick: sKeyCode = "10"; break; case XboxButton.LeftBumper: sKeyCode = "4"; break; case XboxButton.RightBumper: sKeyCode = "5"; break; default: invalidCode = true; break; } } else // Windows Web Player { switch(btn) { case XboxButton.A: sKeyCode = "0"; break; case XboxButton.B: sKeyCode = "1"; break; case XboxButton.X: sKeyCode = "2"; break; case XboxButton.Y: sKeyCode = "3"; break; case XboxButton.Start: sKeyCode = "7"; break; case XboxButton.Back: sKeyCode = "6"; break; case XboxButton.LeftStick: sKeyCode = "8"; break; case XboxButton.RightStick: sKeyCode = "9"; break; case XboxButton.LeftBumper: sKeyCode = "4"; break; case XboxButton.RightBumper: sKeyCode = "5"; break; default: invalidCode = true; break; } } r = "joystick" + sJoyCode + " button " + sKeyCode; if(invalidCode) { r = ""; } return r; } private static string DetermineAxisCode(XboxAxis axs, int ctrlrNum) { string r = ""; string sJoyCode = ctrlrNum.ToString(); string sAxisCode = ""; bool invalidCode = false; if(OnMac()) { switch(axs) { case XboxAxis.LeftStickX: sAxisCode = "X"; break; case XboxAxis.LeftStickY: sAxisCode = "Y"; break; case XboxAxis.RightStickX: sAxisCode = "3"; break; case XboxAxis.RightStickY: sAxisCode = "4"; break; case XboxAxis.LeftTrigger: sAxisCode = "5"; break; case XboxAxis.RightTrigger: sAxisCode = "6"; break; default: invalidCode = true; break; } } else if(OnLinux()) { switch(axs) { case XboxAxis.LeftStickX: sAxisCode = "X"; break; case XboxAxis.LeftStickY: sAxisCode = "Y"; break; case XboxAxis.RightStickX: sAxisCode = "4"; break; case XboxAxis.RightStickY: sAxisCode = "5"; break; case XboxAxis.LeftTrigger: sAxisCode = "3"; break; case XboxAxis.RightTrigger: sAxisCode = "6"; break; default: invalidCode = true; break; } } else // Windows Web Player { switch(axs) { case XboxAxis.LeftStickX: sAxisCode = "X"; break; case XboxAxis.LeftStickY: sAxisCode = "Y"; break; case XboxAxis.RightStickX: sAxisCode = "4"; break; case XboxAxis.RightStickY: sAxisCode = "5"; break; case XboxAxis.LeftTrigger: sAxisCode = "9"; break; case XboxAxis.RightTrigger: sAxisCode = "10"; break; default: invalidCode = true; break; } } r = "XboxAxis" + sAxisCode + "Joy" + sJoyCode; if(invalidCode) { r = ""; } return r; } private static float AdjustAxisValues(float axisValue, XboxAxis axis, int ctrlrNum) { float newAxisValue = axisValue; if(OnMac()) { if(axis == XboxAxis.LeftTrigger) { newAxisValue = -newAxisValue; newAxisValue = RefactorRange(newAxisValue, ctrlrNum, axis); } else if(axis == XboxAxis.RightTrigger) { newAxisValue = RefactorRange(newAxisValue, ctrlrNum, axis); } else if(axis == XboxAxis.RightStickY) { newAxisValue = -newAxisValue; } } else if(OnLinux()) { if(axis == XboxAxis.RightTrigger) { newAxisValue = RefactorRange(newAxisValue, ctrlrNum, axis); } else if(axis == XboxAxis.LeftTrigger) { newAxisValue = RefactorRange(newAxisValue, ctrlrNum, axis); } } return newAxisValue; } private static string DetermineDPad(XboxDPad padDir, int ctrlrNum) { string r = ""; string sJoyCode = ctrlrNum.ToString(); string sPadCode = ""; bool invalidCode = false; if(OnLinux()) { switch(padDir) { case XboxDPad.Up: sPadCode = "8"; break; case XboxDPad.Down: sPadCode = "8"; break; case XboxDPad.Left: sPadCode = "7"; break; case XboxDPad.Right: sPadCode = "7"; break; default: invalidCode = true; break; } } else // Windows Web Player { switch(padDir) { case XboxDPad.Up: sPadCode = "7"; break; case XboxDPad.Down: sPadCode = "7"; break; case XboxDPad.Left: sPadCode = "6"; break; case XboxDPad.Right: sPadCode = "6"; break; default: invalidCode = true; break; } } r = "XboxAxis" + sPadCode + "Joy" + sJoyCode; if(invalidCode) { r = ""; } return r; } private static string DetermineDPadMac(XboxDPad padDir, int ctrlrNum) { string r = ""; string sJoyCode = ""; string sPadCode = ""; bool invalidCode = false; if(ctrlrNum == 0) { sJoyCode = ""; } else { sJoyCode = " " + ctrlrNum.ToString(); } switch(padDir) { case XboxDPad.Up: sPadCode = "5"; break; case XboxDPad.Down: sPadCode = "6"; break; case XboxDPad.Left: sPadCode = "7"; break; case XboxDPad.Right: sPadCode = "8"; break; default: invalidCode = true; break; } r = "joystick" + sJoyCode + " button " + sPadCode; if(invalidCode) { r = ""; } return r; } private static string DetermineDPadWirelessLinux(XboxDPad padDir, int ctrlrNum) { string r = ""; string sJoyCode = ""; string sPadCode = ""; bool invalidCode = false; if(ctrlrNum == 0) { sJoyCode = ""; } else { sJoyCode = " " + ctrlrNum.ToString(); } switch(padDir) { case XboxDPad.Up: sPadCode = "13"; break; case XboxDPad.Down: sPadCode = "14"; break; case XboxDPad.Left: sPadCode = "11"; break; case XboxDPad.Right: sPadCode = "12"; break; default: invalidCode = true; break; } r = "joystick" + sJoyCode + " button " + sPadCode; if(invalidCode) { r = ""; } return r; } // ------------- Private XInput Wrappers (for Windows Native player and editor only) -------------- // #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN // ------------ Inner Class ------------// // Used to setup XInput for Windows class XciXInputInitializer { // Ctor public XciXInputInitializer() { // Only runs once. // Setup XInput here... // Call input states twice in order to make sure that // the previous states and current states are the same. // This is needed to prevent errors where GetButtonUp will trigger unexpectledly for (int i = 0; i < 4; i++) { PlayerIndex plyNum = (PlayerIndex)i; xInputCtrlrsPrev[i] = xInputCtrlrs[i]; xInputCtrlrs[i] = GamePad.GetState(plyNum, XCI.WindowsDeadzoneMethod); } for (int i = 0; i < 4; i++) { PlayerIndex plyNum = (PlayerIndex)i; xInputCtrlrsPrev[i] = xInputCtrlrs[i]; xInputCtrlrs[i] = GamePad.GetState(plyNum, XCI.WindowsDeadzoneMethod); } } public void Dummy() { // Intentionally does nothing to prevent warnings } } // ------------ Members --------------- // // Windows variables private static GamePadState[] xInputCtrlrs = new GamePadState[4]; private static GamePadState[] xInputCtrlrsPrev = new GamePadState[4]; private static int xiPrevFrameCount = -1; private static bool xiUpdateAlreadyCalled = false; private static bool xiNumOfCtrlrsQueried = false; private static XciXInputInitializer xinputInitalizer = new XCI.XciXInputInitializer(); // This can be set to something different if you want private const GamePadDeadZone WindowsDeadzoneMethod = GamePadDeadZone.Circular; // ------------ Methods --------------- // //>> For updating states << private static void XInputUpdateAllStates() { if(xiUpdateAlreadyCalled) return; for(int i = 0; i < 4; i++) { PlayerIndex plyNum = (PlayerIndex) i; xInputCtrlrsPrev[i] = xInputCtrlrs[i]; xInputCtrlrs[i] = GamePad.GetState(plyNum, XCI.WindowsDeadzoneMethod); } xiUpdateAlreadyCalled = true; } //>> For getting states << private static GamePadState XInputGetSingleState() { return xInputCtrlrs[0]; } private static GamePadState XInputGetPaticularState(int ctrlNum) { if (!IsControllerNumberValid(ctrlNum)) return xInputCtrlrs[0]; return xInputCtrlrs[ctrlNum-1]; } private static GamePadState XInputGetSingleStatePrev() { return xInputCtrlrsPrev[0]; } private static GamePadState XInputGetPaticularStatePrev(int ctrlNum) { if (!IsControllerNumberValid(ctrlNum)) return xInputCtrlrsPrev[0]; return xInputCtrlrsPrev[ctrlNum-1]; } //>> For getting input << private static ButtonState XInputGetButtonState(GamePadButtons xiButtons, XboxButton xciBtn) { ButtonState stateToReturn = ButtonState.Pressed; switch(xciBtn) { case XboxButton.A: stateToReturn = xiButtons.A; break; case XboxButton.B: stateToReturn = xiButtons.B; break; case XboxButton.X: stateToReturn = xiButtons.X; break; case XboxButton.Y: stateToReturn = xiButtons.Y; break; case XboxButton.Start: stateToReturn = xiButtons.Start; break; case XboxButton.Back: stateToReturn = xiButtons.Back; break; case XboxButton.LeftBumper: stateToReturn = xiButtons.LeftShoulder; break; case XboxButton.RightBumper: stateToReturn = xiButtons.RightShoulder; break; case XboxButton.LeftStick: stateToReturn = xiButtons.LeftStick; break; case XboxButton.RightStick: stateToReturn = xiButtons.RightStick; break; } return stateToReturn; } private static ButtonState XInputGetDPadState(GamePadDPad xiDPad, XboxDPad xciDPad) { ButtonState stateToReturn = ButtonState.Released; switch(xciDPad) { case XboxDPad.Up: stateToReturn = xiDPad.Up; break; case XboxDPad.Down: stateToReturn = xiDPad.Down; break; case XboxDPad.Left: stateToReturn = xiDPad.Left; break; case XboxDPad.Right: stateToReturn = xiDPad.Right; break; } return stateToReturn; } private static float XInputGetAxisState(GamePadTriggers xiTriggers, XboxAxis xciAxis) { float stateToReturn = 0.0f; switch(xciAxis) { case XboxAxis.LeftTrigger: stateToReturn = xiTriggers.Left; break; case XboxAxis.RightTrigger: stateToReturn = xiTriggers.Right; break; default: stateToReturn = 0.0f; break; } return stateToReturn; } private static float XInputGetAxisState(GamePadThumbSticks xiThumbSticks, XboxAxis xciAxis) { float stateToReturn = 0.0f; switch(xciAxis) { case XboxAxis.LeftStickX: stateToReturn = xiThumbSticks.Left.X; break; case XboxAxis.LeftStickY: stateToReturn = xiThumbSticks.Left.Y; break; case XboxAxis.RightStickX: stateToReturn = xiThumbSticks.Right.X; break; case XboxAxis.RightStickY: stateToReturn = xiThumbSticks.Right.Y; break; default: stateToReturn = 0.0f; break; } return stateToReturn; } private static bool XInputStillInCurrFrame() { bool r = false; xinputInitalizer.Dummy(); // Stop warnings about not using the initilaizer // Get the current frame int currFrame = Time.frameCount; // Are we still in the current frame? if(xiPrevFrameCount == currFrame) { r = true; } else { r = false; xiUpdateAlreadyCalled = false; } // Assign the previous frame count regardless of whether it's the same or not. xiPrevFrameCount = currFrame; return r; } #endif // END of Windows only subsystem ========================================== // -------------------------- Handler Script ------------------- // Secret Private Script that does some maintainace work for XCI states. User should not use this script at all. private class XciHandler : MonoBehaviour { private static XciHandler instance = null; public bool u3dTrigger0LeftIsTouched = false; public bool u3dTrigger0RightIsTouched = false; public bool u3dTrigger1LeftIsTouched = false; public bool u3dTrigger1RightIsTouched = false; public bool u3dTrigger2LeftIsTouched = false; public bool u3dTrigger2RightIsTouched = false; public bool u3dTrigger3LeftIsTouched = false; public bool u3dTrigger3RightIsTouched = false; public bool u3dTrigger4LeftIsTouched = false; public bool u3dTrigger4RightIsTouched = false; void Awake() { if(XciHandler.instance != null) { GameObject.Destroy(this.gameObject); } XciHandler.instance = this; // Lives for the life of the game DontDestroyOnLoad(this.gameObject); } void OnEnable() { SceneManager.sceneLoaded += OnSceneFinishedLoading; } void OnDisable() { SceneManager.sceneLoaded -= OnSceneFinishedLoading; } // Callback made to replace obsolete method OnLevelWasLoaded(int) void OnSceneFinishedLoading(Scene currentScene, LoadSceneMode mode) { this.ResetTriggerTouches(); } void OnApplicationFocus(bool isWindowInFocusNow) { if(!isWindowInFocusNow) { this.ResetTriggerTouches(); } } private void ResetTriggerTouches() { this.u3dTrigger0LeftIsTouched = false; this.u3dTrigger0RightIsTouched = false; this.u3dTrigger1LeftIsTouched = false; this.u3dTrigger1RightIsTouched = false; this.u3dTrigger2LeftIsTouched = false; this.u3dTrigger2RightIsTouched = false; this.u3dTrigger3LeftIsTouched = false; this.u3dTrigger3RightIsTouched = false; this.u3dTrigger4LeftIsTouched = false; this.u3dTrigger4RightIsTouched = false; } public static XciHandler Instance { get { if(XciHandler.instance == null) { GameObject xciHandleObj = new GameObject("XboxCtrlrInput Handler Object"); xciHandleObj.AddComponent<XciHandler>(); } return XciHandler.instance; } } } // end of XciHandler } // end of XCI public static class XboxButtonExtensions { public static bool IsDPad(this XboxButton button) { return (button == XboxButton.DPadUp || button == XboxButton.DPadDown || button == XboxButton.DPadLeft || button == XboxButton.DPadRight); } public static XboxDPad ToDPad(this XboxButton button) { if (button == XboxButton.DPadUp) return XboxDPad.Up; if (button == XboxButton.DPadDown) return XboxDPad.Down; if (button == XboxButton.DPadLeft) return XboxDPad.Left; if (button == XboxButton.DPadRight) return XboxDPad.Right; return default(XboxDPad); } } }