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);
}
}
}