#if !UNITY_2018_OR_NEWER && UNITY_EDITOR #define AGGRESIVE_CURSOR_LOCK #endif using UnityEngine; using UnityEngine.Events; using System.Collections.Generic; #if UNITY_EDITOR using NeoFPS.ScriptGeneration; using System; #endif namespace NeoFPS { [CreateAssetMenu(fileName = "FpsManager_Input", menuName = "NeoFPS/Managers/Input Manager", order = NeoFpsMenuPriorities.manager_input)] [HelpURL("https://docs.neofps.com/manual/inputref-so-neofpsinputmanager.html")] public class NeoFpsInputManager : NeoFpsInputManagerBase { protected override void Initialise() { s_CastInstance = this; InitialiseKeyboardLayouts(); InitialiseGamepads(); base.Initialise(); m_GamepadRuntime = GetBehaviourProxy(); } private static NeoFpsInputManager s_CastInstance = null; #region INPUT AXES [SerializeField, Tooltip("The horizontal mouse axis in the Unity input settings.")] private string m_MouseXAxis = "Mouse X"; [SerializeField, Tooltip("The vertical mouse axis in the Unity input settings.")] private string m_MouseYAxis = "Mouse Y"; [SerializeField, Tooltip("The mouse scroll wheel axis in the Unity input settings.")] private string m_MouseScrollAxis = "Mouse ScrollWheel"; public static string mouseXAxis { get { return s_CastInstance.m_MouseXAxis; } } public static string mouseYAxis { get { return s_CastInstance.m_MouseYAxis; } } public static string mouseScrollAxis { get { return s_CastInstance.m_MouseScrollAxis; } } #endregion #region INPUT BUTTONS #if UNITY_WEBGL private const KeyCode k_MenuKey = KeyCode.Tab; #else private const KeyCode k_MenuKey = KeyCode.Escape; #endif public static readonly string[] fixedInputButtons = { "None", "Menu", "Back", "Cancel" }; // Fixed buttons include: None (0), Menu (1), Back (2), Cancel (3) [SerializeField, Tooltip("The input buttons the game should use.")] private InputButtonInfo[] m_InputButtons = { }; [SerializeField, Tooltip("The keyboard layout for the default input buttons.")] private KeyboardLayout m_DefaultKeyboardLayout = KeyboardLayout.Qwerty; public static string GetButtonDisplayName(FpsInputButton button) { if (s_CastInstance == null) return "No Input"; else { if (button < fixedInputButtons.Length) return fixedInputButtons[button]; else return s_CastInstance.m_InputButtons[button - fixedInputButtons.Length].displayName; } } public static InputCategory GetButtonCategory(FpsInputButton button) { if (s_CastInstance == null || button < fixedInputButtons.Length) return InputCategory.Miscellaneous; else return s_CastInstance.m_InputButtons[button - fixedInputButtons.Length].category; } public static KeyBindingContext GetKeyBindingContext(FpsInputButton button) { if (s_CastInstance == null || button < fixedInputButtons.Length) return KeyBindingContext.Default; else return s_CastInstance.m_InputButtons[button - fixedInputButtons.Length].context; } public static KeyCode GetDefaultPrimaryKey(FpsInputButton button, KeyboardLayout layout) { if (s_CastInstance == null || button < fixedInputButtons.Length) return KeyCode.None; else { var result = s_CastInstance.m_InputButtons[button - fixedInputButtons.Length].defaultPrimary; if (layout != s_CastInstance.m_DefaultKeyboardLayout) result = GetTranslatedKey(result, layout); return result; } } public static KeyCode GetDefaultSecondaryKey(FpsInputButton button, KeyboardLayout layout) { if (s_CastInstance == null || button < fixedInputButtons.Length) return KeyCode.None; else { var result = s_CastInstance.m_InputButtons[button - fixedInputButtons.Length].defaultSecondary; if (layout != s_CastInstance.m_DefaultKeyboardLayout) result = GetTranslatedKey(result, layout); return result; } } protected override bool CheckForEscapeInput() { return Input.GetKeyDown(k_MenuKey) || gamepad.GetButtonDown(FpsInputButton.Menu); } protected override bool CheckForCancelInput() { return gamepad.GetButtonDown(FpsInputButton.Cancel) || gamepad.GetButtonDown(FpsInputButton.Back); } #endregion #region KEYBOARD LAYOUTS // s_Layouts is from qwerty, s_ReverseLayouts is to qwerty static Dictionary[] s_Layouts = null; static Dictionary[] s_ReverseLayouts = null; static KeyCode GetTranslatedKey(KeyCode key, KeyboardLayout layout) { var defaultLayout = s_CastInstance.m_DefaultKeyboardLayout; if (layout != defaultLayout) { // Get qwerty key var qwerty = key; if (defaultLayout != KeyboardLayout.Qwerty) { var map = s_ReverseLayouts[(int)defaultLayout - 1]; if (map.ContainsKey(key)) qwerty = map[key]; } // Get translated from qwerty to layout if (layout == KeyboardLayout.Qwerty) return qwerty; else { var map = s_Layouts[(int)layout - 1]; if (map.ContainsKey(qwerty)) return map[qwerty]; else return qwerty; } } else return key; } static void InitialiseKeyboardLayouts() { s_Layouts = new Dictionary[4]; s_Layouts[0] = GetLayoutAzerty(); s_Layouts[1] = GetLayoutQwertz(); s_Layouts[2] = GetLayoutDvorak(); s_Layouts[3] = GetLayoutColemak(); // Create reverse maps s_ReverseLayouts = new Dictionary[s_Layouts.Length]; for (int i = 0; i < s_Layouts.Length; ++i) { s_ReverseLayouts[i] = new Dictionary(); foreach (var pair in s_Layouts[i]) s_ReverseLayouts[i].Add(pair.Value, pair.Key); } } static Dictionary GetLayoutAzerty() { var layout = new Dictionary(); layout.Add(KeyCode.Q, KeyCode.A); layout.Add(KeyCode.W, KeyCode.Z); layout.Add(KeyCode.E, KeyCode.E); layout.Add(KeyCode.R, KeyCode.R); layout.Add(KeyCode.T, KeyCode.T); layout.Add(KeyCode.Y, KeyCode.Y); layout.Add(KeyCode.U, KeyCode.U); layout.Add(KeyCode.I, KeyCode.I); layout.Add(KeyCode.O, KeyCode.O); layout.Add(KeyCode.P, KeyCode.P); layout.Add(KeyCode.A, KeyCode.Q); layout.Add(KeyCode.S, KeyCode.S); layout.Add(KeyCode.D, KeyCode.D); layout.Add(KeyCode.F, KeyCode.F); layout.Add(KeyCode.G, KeyCode.G); layout.Add(KeyCode.H, KeyCode.H); layout.Add(KeyCode.J, KeyCode.J); layout.Add(KeyCode.K, KeyCode.K); layout.Add(KeyCode.L, KeyCode.L); layout.Add(KeyCode.Semicolon, KeyCode.M); layout.Add(KeyCode.Z, KeyCode.W); layout.Add(KeyCode.X, KeyCode.X); layout.Add(KeyCode.C, KeyCode.C); layout.Add(KeyCode.V, KeyCode.V); layout.Add(KeyCode.B, KeyCode.B); layout.Add(KeyCode.N, KeyCode.N); layout.Add(KeyCode.M, KeyCode.Comma); return layout; } static Dictionary GetLayoutQwertz() { var layout = new Dictionary(); layout.Add(KeyCode.Q, KeyCode.Q); layout.Add(KeyCode.W, KeyCode.W); layout.Add(KeyCode.E, KeyCode.E); layout.Add(KeyCode.R, KeyCode.R); layout.Add(KeyCode.T, KeyCode.T); layout.Add(KeyCode.Y, KeyCode.Z); layout.Add(KeyCode.U, KeyCode.U); layout.Add(KeyCode.I, KeyCode.I); layout.Add(KeyCode.O, KeyCode.O); layout.Add(KeyCode.P, KeyCode.P); layout.Add(KeyCode.A, KeyCode.A); layout.Add(KeyCode.S, KeyCode.S); layout.Add(KeyCode.D, KeyCode.D); layout.Add(KeyCode.F, KeyCode.F); layout.Add(KeyCode.G, KeyCode.G); layout.Add(KeyCode.H, KeyCode.H); layout.Add(KeyCode.J, KeyCode.J); layout.Add(KeyCode.K, KeyCode.K); layout.Add(KeyCode.L, KeyCode.L); layout.Add(KeyCode.Z, KeyCode.Y); layout.Add(KeyCode.X, KeyCode.X); layout.Add(KeyCode.C, KeyCode.C); layout.Add(KeyCode.V, KeyCode.V); layout.Add(KeyCode.B, KeyCode.B); layout.Add(KeyCode.N, KeyCode.N); layout.Add(KeyCode.M, KeyCode.M); return layout; } static Dictionary GetLayoutDvorak() { var layout = new Dictionary(); layout.Add(KeyCode.Q, KeyCode.Quote); layout.Add(KeyCode.W, KeyCode.Comma); layout.Add(KeyCode.E, KeyCode.Period); layout.Add(KeyCode.R, KeyCode.P); layout.Add(KeyCode.T, KeyCode.Y); layout.Add(KeyCode.Y, KeyCode.F); layout.Add(KeyCode.U, KeyCode.G); layout.Add(KeyCode.I, KeyCode.C); layout.Add(KeyCode.O, KeyCode.R); layout.Add(KeyCode.P, KeyCode.L); layout.Add(KeyCode.A, KeyCode.A); layout.Add(KeyCode.S, KeyCode.O); layout.Add(KeyCode.D, KeyCode.E); layout.Add(KeyCode.F, KeyCode.U); layout.Add(KeyCode.G, KeyCode.I); layout.Add(KeyCode.H, KeyCode.D); layout.Add(KeyCode.J, KeyCode.H); layout.Add(KeyCode.K, KeyCode.T); layout.Add(KeyCode.L, KeyCode.N); layout.Add(KeyCode.Semicolon, KeyCode.S); layout.Add(KeyCode.Z, KeyCode.Q); layout.Add(KeyCode.X, KeyCode.J); layout.Add(KeyCode.C, KeyCode.K); layout.Add(KeyCode.V, KeyCode.X); layout.Add(KeyCode.B, KeyCode.B); layout.Add(KeyCode.N, KeyCode.M); layout.Add(KeyCode.M, KeyCode.W); layout.Add(KeyCode.Comma, KeyCode.V); layout.Add(KeyCode.Period, KeyCode.Z); return layout; } static Dictionary GetLayoutColemak() { var layout = new Dictionary(); layout.Add(KeyCode.Q, KeyCode.Q); layout.Add(KeyCode.W, KeyCode.W); layout.Add(KeyCode.E, KeyCode.F); layout.Add(KeyCode.R, KeyCode.P); layout.Add(KeyCode.T, KeyCode.G); layout.Add(KeyCode.Y, KeyCode.J); layout.Add(KeyCode.U, KeyCode.L); layout.Add(KeyCode.I, KeyCode.U); layout.Add(KeyCode.O, KeyCode.Y); layout.Add(KeyCode.P, KeyCode.Semicolon); layout.Add(KeyCode.A, KeyCode.A); layout.Add(KeyCode.S, KeyCode.R); layout.Add(KeyCode.D, KeyCode.S); layout.Add(KeyCode.F, KeyCode.T); layout.Add(KeyCode.G, KeyCode.D); layout.Add(KeyCode.H, KeyCode.H); layout.Add(KeyCode.J, KeyCode.N); layout.Add(KeyCode.K, KeyCode.E); layout.Add(KeyCode.L, KeyCode.I); layout.Add(KeyCode.Semicolon, KeyCode.O); layout.Add(KeyCode.Z, KeyCode.Z); layout.Add(KeyCode.X, KeyCode.X); layout.Add(KeyCode.C, KeyCode.C); layout.Add(KeyCode.V, KeyCode.V); layout.Add(KeyCode.B, KeyCode.B); layout.Add(KeyCode.N, KeyCode.K); layout.Add(KeyCode.M, KeyCode.M); return layout; } #endregion #region GAMEPADS [SerializeField, Tooltip("The different gamepad control layouts")] private GamepadProfile[] m_GamepadProfiles = { }; const int k_GamepadIndexXbox360 = 0; const int k_GamepadIndexXboxOne = 1; const int k_GamepadIndexPS4 = 2; const int k_NumSupportedGamepads = 3; private GamepadUnityInputs[] m_GamepadUnityInputs = { }; private int m_CurrentGamepadIndex = -1; public static GamepadProfile[] gamepadProfiles { get { return s_CastInstance.m_GamepadProfiles; } } protected override bool GetIsGamepadConnected() { return m_CurrentGamepadIndex != -1; } protected override string GetConnectedGamepad() { if (m_CurrentGamepadIndex == -1) return string.Empty; else return m_GamepadProfiles[m_CurrentGamepadIndex].name; } public static GamepadUnityInputs connectedGamepadInputs { get { if (s_CastInstance.m_CurrentGamepadIndex == -1) return null; else return s_CastInstance.m_GamepadUnityInputs[s_CastInstance.m_CurrentGamepadIndex]; } } protected override int GetNumGamepadProfiles() { return gamepadProfiles.Length; } protected override string GetGamepadProfileNameInteral(int index) { return gamepadProfiles[index].name; } private GamepadInput m_GamepadRuntime = null; public static GamepadInput gamepad { get { if (s_CastInstance != null) return s_CastInstance.m_GamepadRuntime; else return null; } } void OnValidate() { #if UNITY_EDITOR foreach (var p in m_GamepadProfiles) p.OnValidate(); #endif } void InitialiseGamepads() { m_GamepadUnityInputs = new GamepadUnityInputs[k_NumSupportedGamepads]; // Mappings based on information from: https://wiki.unity3d.com/index.php?title=Xbox360Controller // Annoyingly, axes and buttons aren't consistent across platforms so we need per-platform profiles // More will be added if requested (eg. consoles) #if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX var xbox360 = new GamepadUnityInputs( "XBox 360", // Name "Gamepad Axis 1", "Gamepad Axis 2", // Left analogue "Gamepad Axis 3", "Gamepad Axis 4", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 16", //ButtonAorX "Gamepad Button 17", //ButtonBorCircle "Gamepad Button 18", //ButtonXorSquare "Gamepad Button 19", //ButtonYorTriangle "Gamepad Button 13", //LBumper "Gamepad AxisBtn 5", //LTrigger "Gamepad Button 14", //RBumper "Gamepad AxisBtn 6", //RTrigger "Gamepad Button 5", //DPad_Up "Gamepad Button 6", //DPad_Down "Gamepad Button 7", //DPad_Left "Gamepad Button 8", //DPad_Right "Gamepad Button 11", //AnaloguePressL "Gamepad Button 12", //AnaloguePressR "Gamepad Button 9", //Start "Gamepad Button 10" //Select }); var xboxOne = new GamepadUnityInputs( "XBox One", // Name "Gamepad Axis 1", "Gamepad Axis 2", // Left analogue "Gamepad Axis 3", "Gamepad Axis 4", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 16", //ButtonAorX "Gamepad Button 17", //ButtonBorCircle "Gamepad Button 18", //ButtonXorSquare "Gamepad Button 19", //ButtonYorTriangle "Gamepad Button 13", //LBumper "Gamepad AxisBtn 5", //LTrigger "Gamepad Button 14", //RBumper "Gamepad AxisBtn 6", //RTrigger "Gamepad Button 5", //DPad_Up "Gamepad Button 6", //DPad_Down "Gamepad Button 7", //DPad_Left "Gamepad Button 8", //DPad_Right "Gamepad Button 11", //AnaloguePressL "Gamepad Button 12", //AnaloguePressR "Gamepad Button 9", //Start "Gamepad Button 10" //Select }); var ps4 = new GamepadUnityInputs( "Playstation Dualshock 4", // Name "Gamepad Axis 1", "Gamepad AxisInv 2", // Left analogue "Gamepad Axis 3", "Gamepad AxisInv 4", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 1", //ButtonAorX "Gamepad Button 2", //ButtonBorCircle "Gamepad Button 0", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad Button 6", //LTrigger "Gamepad Button 5", //RBumper "Gamepad Button 7", //RTrigger "Gamepad AxisBtn 8", //DPad_Up "Gamepad AxisBtnInv 8", //DPad_Down "Gamepad AxisBtnInv 7", //DPad_Left "Gamepad AxisBtn 7", //DPad_Right "Gamepad Button 10", //AnaloguePressL "Gamepad Button 11", //AnaloguePressR "Gamepad Button 9", //Start "Gamepad Button 13" //Select }); #elif UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX var xbox360 = new GamepadUnityInputs( "XBox 360", // Name "Gamepad Axis 1", "Gamepad Axis 2", // Left analogue "Gamepad Axis 4", "Gamepad Axis 5", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 0", //ButtonAorX "Gamepad Button 1", //ButtonBorCircle "Gamepad Button 2", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad AxisBtn 3", //LTrigger "Gamepad Button 5", //RBumper "Gamepad AxisBtn 6", //RTrigger "Gamepad Button 13", //DPad_Up "Gamepad Button 14", //DPad_Down "Gamepad Button 11", //DPad_Left "Gamepad Button 12", //DPad_Right "Gamepad Button 9", //AnaloguePressL "Gamepad Button 10", //AnaloguePressR "Gamepad Button 7", //Start "Gamepad Button 6" //Select }); var xboxOne = new GamepadUnityInputs( "XBox One", // Name "Gamepad Axis 1", "Gamepad Axis 2", // Left analogue "Gamepad Axis 4", "Gamepad Axis 5", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 0", //ButtonAorX "Gamepad Button 1", //ButtonBorCircle "Gamepad Button 2", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad AxisBtn 3", //LTrigger "Gamepad Button 5", //RBumper "Gamepad AxisBtn 6", //RTrigger "Gamepad Button 13", //DPad_Up "Gamepad Button 14", //DPad_Down "Gamepad Button 11", //DPad_Left "Gamepad Button 12", //DPad_Right "Gamepad Button 9", //AnaloguePressL "Gamepad Button 10", //AnaloguePressR "Gamepad Button 7", //Start "Gamepad Button 6" //Select }); var ps4 = new GamepadUnityInputs( "Playstation Dualshock 4", // Name "Gamepad Axis 1", "Gamepad AxisInv 2", // Left analogue "Gamepad Axis 3", "Gamepad AxisInv 6", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 1", //ButtonAorX "Gamepad Button 2", //ButtonBorCircle "Gamepad Button 0", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad Button 6", //LTrigger "Gamepad Button 5", //RBumper "Gamepad Button 7", //RTrigger "Gamepad AxisBtn 8", //DPad_Up "Gamepad AxisBtnInv 8", //DPad_Down "Gamepad AxisBtnInv 7", //DPad_Left "Gamepad AxisBtn 7", //DPad_Right "Gamepad Button 10", //AnaloguePressL "Gamepad Button 11", //AnaloguePressR "Gamepad Button 9", //Start "Gamepad Button 13" //Select }); #else // WINDOWS (default) var xbox360 = new GamepadUnityInputs( "XBox 360", // Name "Gamepad Axis 1", "Gamepad AxisInv 2", // Left analogue "Gamepad Axis 4", "Gamepad AxisInv 5", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 0", //ButtonAorCross "Gamepad Button 1", //ButtonBorCircle "Gamepad Button 2", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad AxisBtn 9", //LTrigger "Gamepad Button 5", //RBumper "Gamepad AxisBtn 10", //RTrigger "Gamepad AxisBtn 7", //DPad_Up "Gamepad AxisBtnInv 7", //DPad_Down "Gamepad AxisBtnInv 6", //DPad_Left "Gamepad AxisBtn 6", //DPad_Right "Gamepad Button 8", //AnaloguePressL "Gamepad Button 9", //AnaloguePressR "Gamepad Button 7", //Start "Gamepad Button 6" //Select }); var xboxOne = new GamepadUnityInputs( "XBox One", // Name "Gamepad Axis 1", "Gamepad AxisInv 2", // Left analogue "Gamepad Axis 4", "Gamepad AxisInv 5", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 0", //ButtonAorCross "Gamepad Button 1", //ButtonBorCircle "Gamepad Button 2", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad AxisBtn 9", //LTrigger "Gamepad Button 5", //RBumper "Gamepad AxisBtn 10", //RTrigger "Gamepad AxisBtn 7", //DPad_Up "Gamepad AxisBtnInv 7", //DPad_Down "Gamepad AxisBtnInv 6", //DPad_Left "Gamepad AxisBtn 6", //DPad_Right "Gamepad Button 8", //AnaloguePressL "Gamepad Button 9", //AnaloguePressR "Gamepad Button 7", //Start "Gamepad Button 6" //Select }); var ps4 = new GamepadUnityInputs( "Playstation Dualshock 4", // Name "Gamepad Axis 1", "Gamepad AxisInv 2", // Left analogue "Gamepad Axis 3", "Gamepad AxisInv 6", // Right analogue "", "", // Gyro new string[] { "Gamepad Button 1", //ButtonAorCross "Gamepad Button 2", //ButtonBorCircle "Gamepad Button 0", //ButtonXorSquare "Gamepad Button 3", //ButtonYorTriangle "Gamepad Button 4", //LBumper "Gamepad Button 6", //LTrigger "Gamepad Button 5", //RBumper "Gamepad Button 7", //RTrigger "Gamepad AxisBtn 8", //DPad_Up "Gamepad AxisBtnInv 8", //DPad_Down "Gamepad AxisBtnInv 7", //DPad_Left "Gamepad AxisBtn 7", //DPad_Right "Gamepad Button 10", //AnaloguePressL "Gamepad Button 11", //AnaloguePressR "Gamepad Button 9", //Start "Gamepad Button 13" //Select }); #endif // Apply the profiles m_GamepadUnityInputs[k_GamepadIndexXbox360] = xbox360; m_GamepadUnityInputs[k_GamepadIndexXboxOne] = xboxOne; m_GamepadUnityInputs[k_GamepadIndexPS4] = ps4; } void CheckGamepads() { int oldIndex = m_CurrentGamepadIndex; m_CurrentGamepadIndex = -1; var joystickNames = Input.GetJoystickNames(); for (int i = 0; i < joystickNames.Length; ++i) { if (string.IsNullOrEmpty(joystickNames[i])) continue; string lower = joystickNames[i].ToLower(); // Check if PS4 controller if (joystickNames[i] == "Wireless Controller" || joystickNames[i] == "Sony Interactive Entertainment Wireless Controller" || joystickNames[i] == "Sony Computer Entertainment Wireless Controller" || joystickNames[i] == "Sony Interactive Entertainment DUALSHOCK®4 USB Wireless Adaptor") { m_CurrentGamepadIndex = k_GamepadIndexPS4; break; } // Check if XBox controller if (lower.Contains("xbox")) { if (lower.Contains("xbox one")) m_CurrentGamepadIndex = k_GamepadIndexXboxOne; else m_CurrentGamepadIndex = k_GamepadIndexXbox360; break; } // Check if XBox Series controller (wireless) if (joystickNames[i] == "Ű" || joystickNames[i] == "耀") { m_CurrentGamepadIndex = k_GamepadIndexXboxOne; break; } } // Fire changed event if relevant if (m_CurrentGamepadIndex != oldIndex) OnGamepadConnectedChanged(m_CurrentGamepadIndex != -1); } protected override void OnDestroy() { base.OnDestroy(); if (m_GamepadRuntime != null) { Destroy(m_GamepadRuntime); m_GamepadRuntime = null; } } public class GamepadInput : MonoBehaviour { private ButtonState[] m_States = null; private bool m_UseGamepad = false; private int m_ProfileIndex = 0; private enum ButtonState { Up, Pressed, Down, Released } private void Start() { // Allocate button states array m_States = new ButtonState[FpsInputButton.count]; // Add controller disconnect handler (reset button states) onIsGamepadConnectedChanged += OnIsGamepadConnectedChanged; // Track settings use gamepad property FpsSettings.gamepad.onSettingsChanged += OnGamepadSettingsChanged; OnGamepadSettingsChanged(); } void Update() { if (!isGamepadConnected || !m_UseGamepad) return; // Track axes for current profile GamepadProfile p = gamepadProfiles[m_ProfileIndex]; GamepadUnityInputs g = connectedGamepadInputs; // Check for gamepad connect/disconnect s_CastInstance.CheckGamepads(); // Updated button states for (int i = 0; i < (int)GamepadButton.Count; ++i) { var gamepadButton = (GamepadButton)i; // Check if button is down bool down = g.GetButton(gamepadButton); var buttons = p.GetInputButtonsForGamepadButton(gamepadButton); for (int j = 0; j < buttons.Length; ++j) { var button = buttons[j]; #if UNITY_EDITOR // Error check if (button >= m_States.Length) { Debug.Log("Button out of range: " + (GamepadButton)i); return; } #endif // Update state switch (m_States[button]) { case ButtonState.Up: { if (down) m_States[button] = ButtonState.Pressed; break; } case ButtonState.Pressed: { if (down) m_States[button] = ButtonState.Down; else m_States[button] = ButtonState.Released; break; } case ButtonState.Down: { if (!down) m_States[button] = ButtonState.Released; break; } case ButtonState.Released: { if (!down) m_States[button] = ButtonState.Up; else m_States[button] = ButtonState.Pressed; break; } } } } } public float GetAxis(FpsInputAxis axis) { if (!isGamepadConnected || !m_UseGamepad) return 0f; GamepadProfile p = gamepadProfiles[m_ProfileIndex]; GamepadUnityInputs g = connectedGamepadInputs; if (p.analogueSetup == GamepadProfile.AnalogueSetup.LeftMoveRightLook) { switch (axis) { case FpsInputAxis.MoveX: return g.GetLeftAnalogH(); case FpsInputAxis.MoveY: return g.GetLeftAnalogV(); case FpsInputAxis.LookX: return g.GetRightAnalogH(); case FpsInputAxis.LookY: return g.GetRightAnalogV(); } } else { switch (axis) { case FpsInputAxis.MoveX: return g.GetRightAnalogH(); case FpsInputAxis.MoveY: return g.GetRightAnalogV(); case FpsInputAxis.LookX: return g.GetLeftAnalogH(); case FpsInputAxis.LookY: return g.GetLeftAnalogV(); } } return 0f; } public float GetAxisRaw(FpsInputAxis axis) { if (!isGamepadConnected || !m_UseGamepad) return 0f; GamepadProfile p = gamepadProfiles[m_ProfileIndex]; GamepadUnityInputs g = connectedGamepadInputs; if (p.analogueSetup == GamepadProfile.AnalogueSetup.LeftMoveRightLook) { switch (axis) { case FpsInputAxis.MoveX: return g.GetLeftAnalogRawH(); case FpsInputAxis.MoveY: return g.GetLeftAnalogRawV(); case FpsInputAxis.LookX: return g.GetRightAnalogRawH(); case FpsInputAxis.LookY: return g.GetRightAnalogRawV(); } } else { switch (axis) { case FpsInputAxis.MoveX: return g.GetRightAnalogRawH(); case FpsInputAxis.MoveY: return g.GetRightAnalogRawV(); case FpsInputAxis.LookX: return g.GetLeftAnalogRawH(); case FpsInputAxis.LookY: return g.GetLeftAnalogRawV(); } } return 0f; } public bool GetButton(FpsInputButton button) { if (!m_UseGamepad || !isGamepadConnected) return false; return m_States[button] == ButtonState.Down || m_States[button] == ButtonState.Pressed; } public bool GetButtonDown(FpsInputButton button) { if (!m_UseGamepad || !isGamepadConnected) return false; return m_States[button] == ButtonState.Pressed; } public bool GetButtonUp(FpsInputButton button) { if (!m_UseGamepad || !isGamepadConnected) return false; return m_States[button] == ButtonState.Released; } void ResetButtonStates() { for (int i = 0; i < m_States.Length; ++i) m_States[i] = ButtonState.Up; } void OnIsGamepadConnectedChanged(bool connected) { ResetButtonStates(); } void OnGamepadSettingsChanged() { bool reset = false; // Check if use gamepad has changed var useGamepad = FpsSettings.gamepad.useGamepad; if (useGamepad != m_UseGamepad) { m_UseGamepad = useGamepad; reset = true; } // Check if gamepad profile index has changed var profile = FpsSettings.gamepad.profile; if (profile != m_ProfileIndex) { m_ProfileIndex = profile; reset = true; } // Reset button states if required if (reset) ResetButtonStates(); } } #endregion #region CODE GENERATION (BUTTONS, AXES, CONTEXTS) #if UNITY_EDITOR #pragma warning disable 0414 // Script templates [SerializeField] private UnityEngine.Object m_ScriptFolder = null; [SerializeField] private TextAsset m_ScriptTemplate = null; // Editor foldouts [SerializeField] private bool m_ExpandInputButtons = false; [SerializeField] private bool m_ExpandInputAxes = false; [SerializeField] private bool m_ExpandInputContexts = false; // Copies of the button setup to revert to. Copied from m_InputButtons when the FpsInputButton constants are generated [SerializeField] private InputButtonInfo[] m_Revert = { }; [SerializeField] private InputButtonInfo[] m_Snapshot = { }; // Dirty flags for buttons (requires code generation) and button props (display name, default keys, etc) [SerializeField] private bool m_ButtonsRequireRebuild = true; [SerializeField] private bool m_InputButtonsDirty = true; [SerializeField] private int m_InputButtonsError = 0; // Input axes [SerializeField] private GeneratorConstantsEntry[] m_InputAxisInfo = null; [SerializeField] private bool m_InputAxisDirty = false; [SerializeField] private int m_InputAxisError = 1; public override bool showError { get { return base.showError || m_InputAxisError > 0 || m_InputButtonsError > 0; } } #pragma warning restore 0414 #endif #endregion } }