A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR || UNITY_ANDROID || PACKAGE_DOCS_GENERATION 2using System; 3using System.Linq; 4using System.Runtime.InteropServices; 5using UnityEngine.InputSystem.Layouts; 6using UnityEngine.InputSystem.LowLevel; 7using UnityEngine.InputSystem.Android.LowLevel; 8using UnityEngine.InputSystem.DualShock; 9using UnityEngine.InputSystem.Utilities; 10 11namespace UnityEngine.InputSystem.Android.LowLevel 12{ 13 /// <summary> 14 /// Default state layout for Android game controller. 15 /// </summary> 16 [StructLayout(LayoutKind.Sequential)] 17 public unsafe struct AndroidGameControllerState : IInputStateTypeInfo 18 { 19 public const int MaxAxes = 48; 20 public const int MaxButtons = 220; 21 22 public class Variants 23 { 24 public const string Gamepad = "Gamepad"; 25 public const string Joystick = "Joystick"; 26 public const string DPadAxes = "DpadAxes"; 27 public const string DPadButtons = "DpadButtons"; 28 } 29 30 internal const uint kAxisOffset = sizeof(uint) * (uint)((MaxButtons + 31) / 32); 31 32 public static FourCC kFormat = new FourCC('A', 'G', 'C', ' '); 33 34 [InputControl(name = "dpad", layout = "Dpad", bit = (uint)AndroidKeyCode.DpadUp, sizeInBits = 4, variants = Variants.DPadButtons)] 35 [InputControl(name = "dpad/up", bit = (uint)AndroidKeyCode.DpadUp, variants = Variants.DPadButtons)] 36 [InputControl(name = "dpad/down", bit = (uint)AndroidKeyCode.DpadDown, variants = Variants.DPadButtons)] 37 [InputControl(name = "dpad/left", bit = (uint)AndroidKeyCode.DpadLeft, variants = Variants.DPadButtons)] 38 [InputControl(name = "dpad/right", bit = (uint)AndroidKeyCode.DpadRight, variants = Variants.DPadButtons)] 39 [InputControl(name = "buttonSouth", bit = (uint)AndroidKeyCode.ButtonA, variants = Variants.Gamepad)] 40 [InputControl(name = "buttonWest", bit = (uint)AndroidKeyCode.ButtonX, variants = Variants.Gamepad)] 41 [InputControl(name = "buttonNorth", bit = (uint)AndroidKeyCode.ButtonY, variants = Variants.Gamepad)] 42 [InputControl(name = "buttonEast", bit = (uint)AndroidKeyCode.ButtonB, variants = Variants.Gamepad)] 43 [InputControl(name = "leftStickPress", bit = (uint)AndroidKeyCode.ButtonThumbl, variants = Variants.Gamepad)] 44 [InputControl(name = "rightStickPress", bit = (uint)AndroidKeyCode.ButtonThumbr, variants = Variants.Gamepad)] 45 [InputControl(name = "leftShoulder", bit = (uint)AndroidKeyCode.ButtonL1, variants = Variants.Gamepad)] 46 [InputControl(name = "rightShoulder", bit = (uint)AndroidKeyCode.ButtonR1, variants = Variants.Gamepad)] 47 [InputControl(name = "start", bit = (uint)AndroidKeyCode.ButtonStart, variants = Variants.Gamepad)] 48 [InputControl(name = "select", bit = (uint)AndroidKeyCode.ButtonSelect, variants = Variants.Gamepad)] 49 public fixed uint buttons[(MaxButtons + 31) / 32]; 50 51 [InputControl(name = "dpad", layout = "Dpad", offset = (uint)AndroidAxis.HatX * sizeof(float) + kAxisOffset, format = "VEC2", sizeInBits = 64, variants = Variants.DPadAxes)] 52 [InputControl(name = "dpad/right", offset = 0, bit = 0, sizeInBits = 32, format = "FLT", parameters = "clamp=3,clampConstant=0,clampMin=0,clampMax=1", variants = Variants.DPadAxes)] 53 [InputControl(name = "dpad/left", offset = 0, bit = 0, sizeInBits = 32, format = "FLT", parameters = "clamp=3,clampConstant=0,clampMin=-1,clampMax=0,invert", variants = Variants.DPadAxes)] 54 [InputControl(name = "dpad/down", offset = ((uint)AndroidAxis.HatY - (uint)AndroidAxis.HatX) * sizeof(float), bit = 0, sizeInBits = 32, format = "FLT", parameters = "clamp=3,clampConstant=0,clampMin=0,clampMax=1", variants = Variants.DPadAxes)] 55 [InputControl(name = "dpad/up", offset = ((uint)AndroidAxis.HatY - (uint)AndroidAxis.HatX) * sizeof(float), bit = 0, sizeInBits = 32, format = "FLT", parameters = "clamp=3,clampConstant=0,clampMin=-1,clampMax=0,invert", variants = Variants.DPadAxes)] 56 [InputControl(name = "leftTrigger", offset = (uint)AndroidAxis.Brake * sizeof(float) + kAxisOffset, parameters = "clamp=1,clampMin=0,clampMax=1.0", variants = Variants.Gamepad)] 57 [InputControl(name = "rightTrigger", offset = (uint)AndroidAxis.Gas * sizeof(float) + kAxisOffset, parameters = "clamp=1,clampMin=0,clampMax=1.0", variants = Variants.Gamepad)] 58 [InputControl(name = "leftStick", variants = Variants.Gamepad)] 59 [InputControl(name = "leftStick/y", variants = Variants.Gamepad, parameters = "invert")] 60 [InputControl(name = "leftStick/up", variants = Variants.Gamepad, parameters = "invert,clamp=1,clampMin=-1.0,clampMax=0.0")] 61 [InputControl(name = "leftStick/down", variants = Variants.Gamepad, parameters = "invert=false,clamp=1,clampMin=0,clampMax=1.0")] 62 ////FIXME: state for this control is not contiguous 63 [InputControl(name = "rightStick", offset = (uint)AndroidAxis.Z * sizeof(float) + kAxisOffset, sizeInBits = ((uint)AndroidAxis.Rz - (uint)AndroidAxis.Z + 1) * sizeof(float) * 8, variants = Variants.Gamepad)] 64 [InputControl(name = "rightStick/x", variants = Variants.Gamepad)] 65 [InputControl(name = "rightStick/y", offset = ((uint)AndroidAxis.Rz - (uint)AndroidAxis.Z) * sizeof(float), variants = Variants.Gamepad, parameters = "invert")] 66 [InputControl(name = "rightStick/up", offset = ((uint)AndroidAxis.Rz - (uint)AndroidAxis.Z) * sizeof(float), variants = Variants.Gamepad, parameters = "invert,clamp=1,clampMin=-1.0,clampMax=0.0")] 67 [InputControl(name = "rightStick/down", offset = ((uint)AndroidAxis.Rz - (uint)AndroidAxis.Z) * sizeof(float), variants = Variants.Gamepad, parameters = "invert=false,clamp=1,clampMin=0,clampMax=1.0")] 68 public fixed float axis[MaxAxes]; 69 70 public FourCC format 71 { 72 get { return kFormat; } 73 } 74 75 public AndroidGameControllerState WithButton(AndroidKeyCode code, bool value = true) 76 { 77 fixed(uint* buttonsPtr = buttons) 78 { 79 if (value) 80 buttonsPtr[(int)code / 32] |= 1U << ((int)code % 32); 81 else 82 buttonsPtr[(int)code / 32] &= ~(1U << ((int)code % 32)); 83 } 84 return this; 85 } 86 87 public AndroidGameControllerState WithAxis(AndroidAxis axis, float value) 88 { 89 fixed(float* axisPtr = this.axis) 90 { 91 axisPtr[(int)axis] = value; 92 } 93 return this; 94 } 95 } 96 97 // See https://developer.android.com/reference/android/view/InputDevice.html for input source values 98 internal enum AndroidInputSource 99 { 100 Keyboard = 257, 101 Dpad = 513, 102 Gamepad = 1025, 103 Touchscreen = 4098, 104 Mouse = 8194, 105 Stylus = 16386, 106 Trackball = 65540, 107 Touchpad = 1048584, 108 Joystick = 16777232 109 } 110 111 [Serializable] 112 internal struct AndroidDeviceCapabilities 113 { 114 public string deviceDescriptor; 115 public int productId; 116 public int vendorId; 117 public bool isVirtual; 118 public AndroidAxis[] motionAxes; 119 public AndroidInputSource inputSources; 120 121 public string ToJson() 122 { 123 return JsonUtility.ToJson(this); 124 } 125 126 public static AndroidDeviceCapabilities FromJson(string json) 127 { 128 if (json == null) 129 throw new ArgumentNullException(nameof(json)); 130 return JsonUtility.FromJson<AndroidDeviceCapabilities>(json); 131 } 132 133 public override string ToString() 134 { 135 return 136 $"deviceDescriptor = {deviceDescriptor}, productId = {productId}, vendorId = {vendorId}, isVirtual = {isVirtual}, motionAxes = {(motionAxes == null ? "<null>" : String.Join(",", motionAxes.Select(i => i.ToString()).ToArray()))}, inputSources = {inputSources}"; 137 } 138 } 139} 140 141namespace UnityEngine.InputSystem.Android 142{ 143 ////FIXME: This is messy! Clean up! 144 /// <summary> 145 /// Gamepad on Android. Comprises all types of gamepads supported on Android. 146 /// </summary> 147 /// <remarks> 148 /// Most of the gamepads: 149 /// - ELAN PLAYSTATION(R)3 Controller 150 /// - My-Power CO.,LTD. PS(R) Controller Adaptor 151 /// (Following tested and work with: Nvidia Shield TV (OS 9); Galaxy Note 20 Ultra (OS 11); Galaxy S9+ (OS 10.0)) 152 /// - Sony Interactive Entertainment Wireless (PS4 DualShock) (Also tested and DOES NOT WORK with Galaxy S9 (OS 8.0); Galaxy S8 (OS 7.0); Xiaomi Mi Note2 (OS 8.0)) 153 /// - Xbox Wireless Controller (Xbox One) (Also tested and works on Samsung Galaxy S8 (OS 7.0); Xiaomi Mi Note2 (OS 8.0)) 154 /// - NVIDIA Controller v01.03/v01.04 155 /// - (Add more) 156 /// map buttons in the following way: 157 /// Left Stick -> AXIS_X(0) / AXIS_Y(1) 158 /// Right Stick -> AXIS_Z (11) / AXIS_RZ(14) 159 /// Right Thumb -> KEYCODE_BUTTON_THUMBR(107) 160 /// Left Thumb -> KEYCODE_BUTTON_THUMBL(106) 161 /// L1 (Left shoulder) -> KEYCODE_BUTTON_L1(102) 162 /// R1 (Right shoulder) -> KEYCODE_BUTTON_R1(103) 163 /// L2 (Left trigger) -> AXIS_BRAKE(23) 164 /// R2 (Right trigger) -> AXIS_GAS(22) 165 /// X -> KEYCODE_BUTTON_X(99) 166 /// Y -> KEYCODE_BUTTON_Y(100) 167 /// B -> KEYCODE_BUTTON_B(97) 168 /// A -> KEYCODE_BUTTON_A(96) 169 /// DPAD -> AXIS_HAT_X(15),AXIS_HAT_Y(16) or KEYCODE_DPAD_LEFT(21), KEYCODE_DPAD_RIGHT(22), KEYCODE_DPAD_UP(19), KEYCODE_DPAD_DOWN(20), 170 /// Note: On Nvidia Shield Console, L2/R2 additionally invoke key events for AXIS_LTRIGGER, AXIS_RTRIGGER (in addition to AXIS_BRAKE, AXIS_GAS) 171 /// If you connect gamepad to a phone for L2/R2 only AXIS_BRAKE/AXIS_GAS come. AXIS_LTRIGGER, AXIS_RTRIGGER are not invoked. 172 /// That's why we map triggers only to AXIS_BRAKE/AXIS_GAS 173 /// Nvidia Shield also reports KEYCODE_BACK instead of KEYCODE_BUTTON_SELECT, so Options(XboxOne Controller)/View(DualShock)/Select buttons do not work 174 /// PS4 controller is officially supported from Android 10 and higher (https://playstation.com/en-us/support/hardware/ps4-pair-dualshock-4-wireless-with-sony-xperia-and-android) 175 /// However, some devices with older OS have fixed PS4 controller support on their drivers this leads to following situation: 176 /// Some gamepads on Android devices (with same Android number version) might have different mappings 177 /// For ex., Dualshock, on NVidia Shield Console (OS 8.0) all buttons correctly map according to rules in AndroidGameControllerState 178 /// when clicking left shoulder it will go to AndroidKeyCode.ButtonL1, rightShoulder -> AndroidKeyCode.ButtonR1, etc 179 /// But, on Samsung Galaxy S9 (OS 8.0), the mapping is different (Same for Xiaomi Mi Note2 (OS 8.0), Samsung Galaxy S8 (OS 7.0)) 180 /// when clicking left shoulder it will go to AndroidKeyCode.ButtonY, rightShoulder -> AndroidKeyCode.ButtonZ, etc 181 /// So even though Android version is 8.0 in both cases, Dualshock will only correctly work on NVidia Shield Console 182 /// It's obvious that this depends on the driver and not Android OS, thus we can only assume Samsung in this case doesn't properly support Dualshock in their drivers 183 /// While we can do custom mapping for Samsung, we can never now when will they try to update the driver for Dualshock or some other gamepad 184 /// </remarks> 185 [InputControlLayout(stateType = typeof(AndroidGameControllerState), variants = AndroidGameControllerState.Variants.Gamepad)] 186 public class AndroidGamepad : Gamepad 187 { 188 } 189 190 /// <summary> 191 /// Generic controller with Dpad axes 192 /// </summary> 193 [InputControlLayout(stateType = typeof(AndroidGameControllerState), hideInUI = true, 194 variants = AndroidGameControllerState.Variants.Gamepad + InputControlLayout.VariantSeparator + AndroidGameControllerState.Variants.DPadAxes)] 195 public class AndroidGamepadWithDpadAxes : AndroidGamepad 196 { 197 } 198 199 /// <summary> 200 /// Generic controller with Dpad buttons 201 /// </summary> 202 [InputControlLayout(stateType = typeof(AndroidGameControllerState), hideInUI = true, 203 variants = AndroidGameControllerState.Variants.Gamepad + InputControlLayout.VariantSeparator + AndroidGameControllerState.Variants.DPadButtons)] 204 public class AndroidGamepadWithDpadButtons : AndroidGamepad 205 { 206 } 207 208 /// <summary> 209 /// Joystick on Android. 210 /// </summary> 211 [InputControlLayout(stateType = typeof(AndroidGameControllerState), variants = AndroidGameControllerState.Variants.Joystick)] 212 public class AndroidJoystick : Joystick 213 { 214 } 215 216 /// <summary> 217 /// A PlayStation DualShock 4 controller connected to an Android device. 218 /// </summary> 219 [InputControlLayout(stateType = typeof(AndroidGameControllerState), displayName = "Android DualShock 4 Gamepad", 220 variants = AndroidGameControllerState.Variants.Gamepad + InputControlLayout.VariantSeparator + AndroidGameControllerState.Variants.DPadAxes)] 221 public class DualShock4GamepadAndroid : DualShockGamepad 222 { 223 } 224 225 /// <summary> 226 /// A PlayStation DualShock 4 controller connected to an Android device. 227 /// </summary> 228 [InputControlLayout(stateType = typeof(AndroidGameControllerState), displayName = "Android Xbox One Controller", 229 variants = AndroidGameControllerState.Variants.Gamepad + InputControlLayout.VariantSeparator + AndroidGameControllerState.Variants.DPadAxes)] 230 public class XboxOneGamepadAndroid : XInput.XInputController 231 { 232 } 233} 234#endif // UNITY_EDITOR || UNITY_ANDROID