using UnityEngine; // Users don't have to use this directly, so there is no need to have this in global namespace namespace CarbonInput { /// /// Describes a mapping for a specific controller. This mapping is independend of the PlayerIndex. /// Each CarbonController defines how buttons and axes are mapped correctly to the Unity Input. /// [CreateAssetMenu(fileName = "NewCarbonMapping", menuName = "Carbon Input/GamePad Mapping")] public class CarbonController : ScriptableObject { /// /// Number of buttons defined in the enumeration. /// public const int ButtonCount = 10; // Must match the CButton enum! /// /// Number of axes defined in the enumeration. /// public const int AxisCount = 8; // Must match the CAxis enum! /// /// Number of generated axes, /// public const int InputAxisCount = 16; // Must match the number of generated Input axes! /// /// Number of joystick buttons supported by unity. /// public const int JoystickButtonCount = 20; // Number of joystick buttons supported by Unity /// /// Number of entries in enumeration. /// public const int PlayerIndices = 9; // Any, One, ..., Eight /// /// Prefix of all generated axes. /// public const string Tag = "cin_Axis"; /// /// Mapping of [, JoystickAxis] to its name. /// private static readonly string[,] AxisNames; static CarbonController() { // construct all strings beforehand AxisNames = new string[PlayerIndices, InputAxisCount]; for(int id = 0; id < PlayerIndices; id++) { for(int axis = 0; axis < InputAxisCount; axis++) { AxisNames[id, axis] = CreateName(id, axis); } } } /// /// Create the input axis name for and axis. /// /// /// /// public static string CreateName(int id, int axis) { return Tag + id + "_" + axis.ToString("D2"); } /// /// Regular expression used to check if this mapping can be used for a controller. /// public string RegEx; /// /// Platforms supported by this mapping. /// public CPlatform Platform; /// /// Priority of this mapping. On startup the system will try to find a correct mapping for all controller. Lower priority mappings will be tester earlier. /// public int Priority = 1000; /// /// If true, this mapping will only be used once, even if it could be used multiple times. /// public bool UseOnce; /// /// If true, this mapping can be replaced by touch mappings. /// public bool Replacable; /// /// All mappings for all possible . This array must have exactly many entries. /// public AxisMapping[] Axes = new AxisMapping[AxisCount]; /// /// All mappings for all possible s. This array must have exactly many entries. /// public ButtonMapping[] Buttons = new ButtonMapping[ButtonCount]; /// /// Returns true if this mapping is a fallback mapping. /// A mapping is considered a fallback, if it doesn't have a proper . /// By default, the keyboard is considered a fallback mapping. /// /// public bool IsFallback() { return string.IsNullOrEmpty(RegEx); } public CarbonController() { for(int i = 0; i < Buttons.Length; i++) Buttons[i] = new ButtonMapping(); for(int i = 0; i < Axes.Length; i++) Axes[i] = new AxisMapping(); } /// /// Checks if controller button btn of player id is pressed. /// /// GamePad button /// Index of player /// public virtual bool GetButton(CButton btn, int id) { ButtonMapping key = Buttons[(int)btn]; if(key.Type == ButtonMapping.ButtonType.Wrapper) { if(key.Key != KeyCode.None) return Input.GetKey(key.Key); } else { //JoystickButton0 = 330 ... JoystickButton19 = 349 //Joystick1Button0 = 350 ... Joystick1Button19 = 369 // ... //Joystick8Button0 = 490 ... Joystick8Button19 = 509 return Input.GetKey(KeyCode.JoystickButton0 + id * JoystickButtonCount + key.Button); } return false; } /// /// Returns the value of the virtual axis of player identified by the parameter; /// /// /// /// public virtual float GetAxis(CAxis axis, int id) { AxisMapping mapping = Axes[(int)axis]; float result = 0; switch(mapping.Type) { case AxisMapping.AxisType.Default: result = Input.GetAxis(AxisNames[id, mapping.Axis]); break; case AxisMapping.AxisType.ButtonWrapper: result = Input.GetKey(KeyCode.JoystickButton0 + id * JoystickButtonCount + mapping.Axis) ? mapping.Max : mapping.Min; break; case AxisMapping.AxisType.KeyWrapper: bool key1 = Input.GetKey(mapping.Key1); bool key2 = Input.GetKey(mapping.Key2); if(key1 && !key2) result = -1; else if(!key1 && key2) result = 1; else result = 0; break; case AxisMapping.AxisType.Clamped: result = Mathf.Clamp(Input.GetAxis(AxisNames[id, mapping.Axis]), mapping.Min, mapping.Max); break; case AxisMapping.AxisType.ButtonWrapper2: key1 = Input.GetKey(KeyCode.JoystickButton0 + id * JoystickButtonCount + mapping.Axis); key2 = Input.GetKey(KeyCode.JoystickButton0 + id * JoystickButtonCount + mapping.Alternative); if(key1 && !key2) result = -1; else if(!key1 && key2) result = 1; else result = 0; break; case AxisMapping.AxisType.TriggerLimiter: result = (Input.GetAxis(AxisNames[id, mapping.Axis]) + 1f) / 2f; break; } if(mapping.Invert) return -result; return result; } /// /// Returns true if this mapping is supported on the execution platform. /// /// public bool SupportedOnThisPlatform() { switch(Application.platform) { case RuntimePlatform.WebGLPlayer: return Has(CPlatform.WebGL); case RuntimePlatform.Android: return Has(CPlatform.Android); case RuntimePlatform.IPhonePlayer: return Has(CPlatform.IOS); case RuntimePlatform.LinuxEditor: case RuntimePlatform.LinuxPlayer: return Has(CPlatform.Linux); case RuntimePlatform.OSXEditor: case RuntimePlatform.OSXPlayer: return Has(CPlatform.OSX); case RuntimePlatform.PS4: return Has(CPlatform.PS4); #if !UNITY_2018_3_OR_NEWER case RuntimePlatform.PSP2: return Has(CPlatform.PSP2); #endif #if !UNITY_2018_1_OR_NEWER case RuntimePlatform.WiiU: return Has(CPlatform.Wii); #endif case RuntimePlatform.WindowsEditor: case RuntimePlatform.WindowsPlayer: return Has(CPlatform.Windows); case RuntimePlatform.WSAPlayerARM: case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerX86: return Has(CPlatform.WSA); case RuntimePlatform.XboxOne: return Has(CPlatform.XBoxOne); } return false; } /// /// Checks if the given is set in . /// /// /// private bool Has(CPlatform flag) { return (Platform & flag) == flag; } /// /// This will return a fallback instance, using the keyboard. /// /// public static CarbonController CreateFallback() { CarbonController cc = CreateInstance(); cc.Platform = (CPlatform)(-1); MakeKeyWrapper(cc.Buttons[0], KeyCode.RightShift); MakeKeyWrapper(cc.Buttons[1], KeyCode.RightControl); MakeKeyWrapper(cc.Buttons[2], KeyCode.LeftShift); MakeKeyWrapper(cc.Buttons[3], KeyCode.Space); MakeKeyWrapper(cc.Buttons[4], KeyCode.Escape); MakeKeyWrapper(cc.Buttons[5], KeyCode.Return); MakeKeyWrapper(cc.Buttons[6], KeyCode.Q); MakeKeyWrapper(cc.Buttons[7], KeyCode.E); MakeKeyWrapper(cc.Buttons[8]); MakeKeyWrapper(cc.Buttons[9]); MakeKeyWrapper(cc.Axes[0], KeyCode.A, KeyCode.D); MakeKeyWrapper(cc.Axes[1], KeyCode.W, KeyCode.S); for(int i = 2; i < AxisCount; i++) MakeKeyWrapper(cc.Axes[i]); return cc; } /// /// This will return a fallback instance, which doesn't respond to any key. /// /// public static CarbonController CreateDisabledInput() { var cc = CreateInstance(); cc.name = "DisabledInput"; cc.Platform = (CPlatform)(-1); cc.Replacable = true; for(int i = 0; i < ButtonCount; i++) MakeKeyWrapper(cc.Buttons[i]); for(int i = 0; i < AxisCount; i++) MakeKeyWrapper(cc.Axes[i]); return cc; } /// /// Sets the given to be a /// /// /// /// private static void MakeKeyWrapper(AxisMapping mapping, KeyCode key1 = KeyCode.None, KeyCode key2 = KeyCode.None) { mapping.Type = AxisMapping.AxisType.KeyWrapper; mapping.Key1 = key1; mapping.Min = key1 != KeyCode.None ? -1 : 0; mapping.Key2 = key2; mapping.Max = key2 != KeyCode.None ? 1 : 0; } /// /// Sets the given to be a . /// /// /// private static void MakeKeyWrapper(ButtonMapping mapping, KeyCode key = KeyCode.None) { mapping.Type = ButtonMapping.ButtonType.Wrapper; mapping.Key = key; } } }