A game about forced loneliness, made by TACStudios
1using System;
2using UnityEngine.InputSystem.Controls;
3using UnityEngine.InputSystem.Layouts;
4
5////TODO: expose user index
6
7////TODO: set displayNames of the controls according to Xbox controller standards
8
9namespace UnityEngine.InputSystem.XInput
10{
11 /// <summary>
12 /// An XInput-compatible game controller.
13 /// </summary>
14 /// <remarks>
15 /// Note that on non-Microsoft platforms, XInput controllers will not actually use the XInput interface
16 /// but will rather be interfaced with through different APIs -- on OSX, for example, HID is used to
17 /// interface with Xbox controlllers. In those cases, XInput-specific functionality (like <see cref="Capabilities"/>)
18 /// will not be available.
19 ///
20 /// On Windows, XInput controllers will be reported with <see cref="InputDeviceDescription.interfaceName"/>
21 /// set to <c>"XInput"</c> and with a JSON representation of <a
22 /// href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">XINPUT_CAPABILITIES</a>
23 /// available in <see cref="InputDeviceDescription.capabilities"/>. This means that you match on those
24 /// <c>subType</c> and/or <c>flags</c> for example.
25 ///
26 /// <example>
27 /// <code>
28 /// // Create an XInput-specific guitar layout subtype.
29 /// // NOTE: Works only on Windows.
30 /// InputSystem.RegisterLayout(@"
31 /// {
32 /// ""name"" : ""XInputGuitar"",
33 /// ""displayName"" : ""Guitar"",
34 /// ""extend"" : ""XInputController"",
35 /// ""device"" : {
36 /// ""interface"" : ""XInput"",
37 /// ""capabilities"" : [
38 /// { ""path"" : ""subType"", ""value"" : ""6"" }
39 /// ]
40 /// }
41 /// }
42 /// ");
43 /// </code>
44 /// </example>
45 ///
46 /// Now, when an XInput controller is connected and reports itself with the
47 /// subtype "Guitar", it is turned into an "XInputGuitar" instead of an
48 /// "XInputController".
49 /// </remarks>
50 [InputControlLayout(displayName = "Xbox Controller")]
51 public class XInputController : Gamepad
52 {
53 /// <summary>
54 /// Same as <see cref="Gamepad.startButton"/>.
55 /// </summary>
56 /// <value>Same control as <see cref="Gamepad.startButton"/>.</value>
57 // Change the display names for the buttons to conform to Xbox conventions.
58 [InputControl(name = "buttonSouth", displayName = "A")]
59 [InputControl(name = "buttonEast", displayName = "B")]
60 [InputControl(name = "buttonWest", displayName = "X")]
61 [InputControl(name = "buttonNorth", displayName = "Y")]
62 [InputControl(name = "leftShoulder", displayName = "Left Bumper", shortDisplayName = "LB")]
63 [InputControl(name = "rightShoulder", displayName = "Right Bumper", shortDisplayName = "RB")]
64 [InputControl(name = "leftTrigger", shortDisplayName = "LT")]
65 [InputControl(name = "rightTrigger", shortDisplayName = "RT")]
66 // This follows Xbox One conventions; on Xbox 360, this is start=start and select=back.
67 [InputControl(name = "start", displayName = "Menu", alias = "menu")]
68 [InputControl(name = "select", displayName = "View", alias = "view")]
69 public ButtonControl menu { get; protected set; }
70
71 /// <summary>
72 /// Same as <see cref="Gamepad.selectButton"/>
73 /// </summary>
74 /// <value>Same control as <see cref="Gamepad.selectButton"/>.</value>
75 public ButtonControl view { get; protected set; }
76
77 /// <summary>
78 /// What specific kind of XInput controller this is.
79 /// </summary>
80 /// <value>XInput device subtype.</value>
81 /// <remarks>
82 /// When the controller is picked up through interfaces other than XInput or through old versions of
83 /// XInput, this will always be <see cref="DeviceSubType.Unknown"/>. Put another way, this value is
84 /// meaningful only on recent Microsoft platforms.
85 /// </remarks>
86 /// <seealso href="https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes"/>
87 public DeviceSubType subType
88 {
89 get
90 {
91 if (!m_HaveParsedCapabilities)
92 ParseCapabilities();
93 return m_SubType;
94 }
95 }
96
97 /// <summary>
98 /// Return the device flags as reported by XInput.
99 /// </summary>
100 /// <value>XInput device flags.</value>
101 /// <seealso href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities"/>
102 public DeviceFlags flags
103 {
104 get
105 {
106 if (!m_HaveParsedCapabilities)
107 ParseCapabilities();
108 return m_Flags;
109 }
110 }
111
112 /// <inheritdoc />
113 protected override void FinishSetup()
114 {
115 base.FinishSetup();
116
117 menu = startButton;
118 view = selectButton;
119 }
120
121 private bool m_HaveParsedCapabilities;
122 private DeviceSubType m_SubType;
123 private DeviceFlags m_Flags;
124
125 private void ParseCapabilities()
126 {
127 if (!string.IsNullOrEmpty(description.capabilities))
128 {
129 var capabilities = JsonUtility.FromJson<Capabilities>(description.capabilities);
130 m_SubType = capabilities.subType;
131 m_Flags = capabilities.flags;
132 }
133 m_HaveParsedCapabilities = true;
134 }
135
136 /// <summary>
137 /// Controller type enumeration in <c>Type</c> field of <c>XINPUT_CAPABILITIES</c>.
138 /// </summary>
139 /// <remarks>
140 /// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">MSDN</a>.
141 /// </remarks>
142 internal enum DeviceType
143 {
144 Gamepad = 0x00
145 }
146
147 /// <summary>
148 /// Controller subtype enumeration in <c>SubType</c> field of <c>XINPUT_CAPABILITIES</c>.
149 /// </summary>
150 /// <remarks>
151 /// See <a href="https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes">MSDN</a>.
152 /// </remarks>
153 public enum DeviceSubType
154 {
155 Unknown = 0x00,
156 Gamepad = 0x01,
157 Wheel = 0x02,
158 ArcadeStick = 0x03,
159 FlightStick = 0x04,
160 DancePad = 0x05,
161 Guitar = 0x06,
162 GuitarAlternate = 0x07,
163 DrumKit = 0x08,
164 GuitarBass = 0x0B,
165 ArcadePad = 0x13
166 }
167
168 /// <summary>
169 /// Controller flags in <c>Flags</c> field of <c>XINPUT_CAPABILITIES</c>.
170 /// </summary>
171 /// <remarks>
172 /// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">MSDN</a>.
173 /// </remarks>
174 [Flags]
175 public new enum DeviceFlags
176 {
177 ForceFeedbackSupported = 0x01,
178 Wireless = 0x02,
179 VoiceSupported = 0x04,
180 PluginModulesSupported = 0x08,
181 NoNavigation = 0x10,
182 }
183
184 [Serializable]
185 internal struct Capabilities
186 {
187 public DeviceType type;
188 public DeviceSubType subType;
189 public DeviceFlags flags;
190 }
191 }
192}