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