InputControlAttribute.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. using System;
  2. using UnityEngine.InputSystem.Composites;
  3. using UnityEngine.InputSystem.LowLevel;
  4. namespace UnityEngine.InputSystem.Layouts
  5. {
  6. /// <summary>
  7. /// Mark a field or property as representing/identifying an input control in some form.
  8. /// </summary>
  9. /// <remarks>
  10. /// This attribute is used in different places for different purposes.
  11. ///
  12. /// When creating input control layouts (<see cref="InputControlLayout"/>) in C#, applying the
  13. /// attribute to fields in a state struct (see <see cref="IInputStateTypeInfo"/> or <see cref="GamepadState"/>
  14. /// for an example) or to properties in an input device (<see cref="InputDevice"/>), will cause an
  15. /// <see cref="InputControl"/> to be created from the field or property at runtime. The attribute
  16. /// can be applied multiple times to create multiple input controls (e.g. when having an int field
  17. /// that represents a bitfield where each bit is a separate button).
  18. ///
  19. /// <example>
  20. /// <code>
  21. /// public class MyDevice : InputDevice
  22. /// {
  23. /// // Adds an InputControl with name=myButton and layout=Button to the device.
  24. /// [InputControl]
  25. /// public ButtonControl myButton { get; set; }
  26. /// }
  27. /// </code>
  28. /// </example>
  29. ///
  30. /// Another use is for marking <c>string</c> type fields that represent input control paths. Applying
  31. /// the attribute to them will cause them to automatically use a custom inspector similar to the one
  32. /// found in the action editor. For this use, only the <see cref="layout"/> property is taken into
  33. /// account.
  34. ///
  35. /// <example>
  36. /// <code>
  37. /// public class MyBehavior : MonoBehaviour
  38. /// {
  39. /// // In the inspector, shows a control selector that is restricted to
  40. /// // selecting buttons. As a result, controlPath will be set to path
  41. /// // representing the control that was picked (e.g. "&lt;Gamepad&gt;/buttonSouth").
  42. /// [InputControl(layout = "Button")]
  43. /// public string controlPath;
  44. ///
  45. /// protected void OnEnable()
  46. /// {
  47. /// // Find controls by path.
  48. /// var controls = InputSystem.FindControl(controlPath);
  49. /// //...
  50. /// }
  51. /// }
  52. /// </code>
  53. /// </example>
  54. ///
  55. /// Finally, the attribute is also used in composite bindings (<see cref="InputBindingComposite"/>)
  56. /// to mark fields that reference parts of the composite. An example for this is <see cref="AxisComposite.negative"/>.
  57. /// In this use, also only the <see cref="layout"/> property is taken into account while other properties
  58. /// are ignored.
  59. ///
  60. /// <example>
  61. /// <code>
  62. /// public class MyComposite : InputBindingComposite&lt;float&gt;
  63. /// {
  64. /// // Add a part to the composite called 'firstControl' which expects
  65. /// // AxisControls.
  66. /// [InputControl(layout = "Axis")]
  67. /// public int firstControl;
  68. ///
  69. /// // Add a part to the composite called 'secondControl' which expects
  70. /// // Vector3Controls.
  71. /// [InputControl(layout = "Vector3")]
  72. /// public int secondControl;
  73. ///
  74. /// //...
  75. /// }
  76. /// </code>
  77. /// </example>
  78. /// </remarks>
  79. /// <seealso cref="InputControlLayout"/>
  80. /// <seealso cref="InputBindingComposite"/>
  81. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
  82. public sealed class InputControlAttribute : PropertyAttribute
  83. {
  84. /// <summary>
  85. /// Layout to use for the control.
  86. /// </summary>
  87. /// <value>Layout to use for the control.</value>
  88. /// <remarks>
  89. /// If this is not set, the system tries to infer the layout type from the value type of
  90. /// the field or property. If the value type is itself registered as a layout, that layout
  91. /// will be used (e.g. when you have a property of type <see cref="Controls.ButtonControl"/>, the layout
  92. /// will be inferred to be "Button"). Otherwise, if a layout with the same name as the type is registered,
  93. /// that layout will be used (e.g. when you have a field of type <see cref="Vector3"/>, the layout
  94. /// will be inferred to be "Vector3").
  95. /// </remarks>
  96. /// <seealso cref="InputControlLayout"/>
  97. public string layout { get; set; }
  98. /// <summary>
  99. /// Layout variant to use for the control.
  100. /// </summary>
  101. /// <value>Layout variant to use for the control.</value>
  102. public string variants { get; set; }
  103. /// <summary>
  104. /// Name to give to the name. If null or empty, the name of the property or
  105. /// field the attribute is applied to will be used.
  106. /// </summary>
  107. /// <value>Name to give to the control.</value>
  108. /// <seealso cref="InputControl.name"/>
  109. public string name { get; set; }
  110. /// <summary>
  111. /// Storage format to use for the control. If not set, default storage format
  112. /// for the given <see cref="layout"/> is used.
  113. /// </summary>
  114. /// <value>Memory storage format to use for the control.</value>
  115. /// <seealso cref="InputStateBlock.format"/>
  116. public string format { get; set; }
  117. /// <summary>
  118. /// Usage to apply to the control.
  119. /// </summary>
  120. /// <value>Usage for the control.</value>
  121. /// <remarks>
  122. /// This property can be used in place of <see cref="usages"/> to set just a single
  123. /// usage on the control.
  124. /// </remarks>
  125. /// <seealso cref="InputControl.usages"/>
  126. /// <seealso cref="InputControlLayout.ControlItem.usages"/>
  127. /// <seealso cref="CommonUsages"/>
  128. public string usage { get; set; }
  129. /// <summary>
  130. /// Usages to apply to the control.
  131. /// </summary>
  132. /// <value>Usages for the control.</value>
  133. /// <remarks>
  134. /// This property should be used instead of <see cref="usage"/> when a control has multiple usages.
  135. /// </remarks>
  136. /// <seealso cref="InputControl.usages"/>
  137. /// <seealso cref="InputControlLayout.ControlItem.usages"/>
  138. /// <seealso cref="CommonUsages"/>
  139. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "According to MSDN, this message can be ignored for attribute parameters, as there are no better alternatives.")]
  140. public string[] usages { get; set; }
  141. /// <summary>
  142. /// Optional list of parameters to apply to the control.
  143. /// </summary>
  144. /// <value>Parameters to apply to the control.</value>
  145. /// <remarks>
  146. /// An <see cref="InputControl"/> may expose public fields which can be set as
  147. /// parameters. An example of this is <see cref="Controls.AxisControl.clamp"/>.
  148. ///
  149. /// <example>
  150. /// <code>
  151. /// public struct MyStateStruct : IInputStateTypeInfo
  152. /// {
  153. /// [InputControl(parameters = "clamp,clampMin=-0.5,clampMax=0.5")]
  154. /// public float axis;
  155. /// }
  156. /// </code>
  157. /// </example>
  158. /// </remarks>
  159. /// <seealso cref="InputControlLayout.ControlItem.parameters"/>
  160. public string parameters { get; set; }
  161. /// <summary>
  162. /// Optional list of processors to add to the control.
  163. /// </summary>
  164. /// <value>Processors to apply to the control.</value>
  165. /// <remarks>
  166. /// Each element in the list is a name of a processor (as registered with
  167. /// <see cref="InputSystem.RegisterProcessor{T}"/>) followed by an optional
  168. /// list of parameters.
  169. ///
  170. /// For example, <c>"normalize(min=0,max=256)"</c> is one element that puts
  171. /// a <c>NormalizeProcessor</c> on the control and sets its <c>min</c> field
  172. /// to 0 and its its <c>max</c> field to 256.
  173. ///
  174. /// Multiple processors can be put on a control by separating them with a comma.
  175. /// For example, <c>"normalize(max=256),scale(factor=2)"</c> puts both a <c>NormalizeProcessor</c>
  176. /// and a <c>ScaleProcessor</c> on the control. Processors are applied in the
  177. /// order they are listed.
  178. /// </remarks>
  179. /// <seealso cref="InputControlLayout.ControlItem.processors"/>
  180. /// <seealso cref="InputBinding.processors"/>
  181. public string processors { get; set; }
  182. /// <summary>
  183. /// An alternative name that can be used in place of <see cref="name"/> to find
  184. /// the control.
  185. /// </summary>
  186. /// <value>Alternative name for the control.</value>
  187. /// <remarks>
  188. /// This property can be used instead of <see cref="aliases"/> when there is only a
  189. /// single alias for the control.
  190. ///
  191. /// Aliases, like names, are case-insensitive. Any control may have arbitrary many
  192. /// aliases.
  193. /// </remarks>
  194. /// <seealso cref="InputControl.aliases"/>
  195. /// <seealso cref="InputControlLayout.ControlItem.aliases"/>
  196. public string alias { get; set; }
  197. /// <summary>
  198. /// A list of alternative names that can be used in place of <see cref="name"/> to
  199. /// find the control.
  200. /// </summary>
  201. /// <value>Alternative names for the control.</value>
  202. /// <remarks>
  203. /// This property should be used instead of <see cref="alias"/> when a control has
  204. /// multiple aliases.
  205. ///
  206. /// Aliases, like names, are case-insensitive. Any control may have arbitrary many
  207. /// aliases.
  208. /// </remarks>
  209. /// <seealso cref="InputControl.aliases"/>
  210. /// <seealso cref="InputControlLayout.ControlItem.aliases"/>
  211. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "According to MSDN, this message can be ignored for attribute parameters, as there are no better alternatives.")]
  212. public string[] aliases { get; set; }
  213. public string useStateFrom { get; set; }
  214. public uint bit { get; set; } = InputStateBlock.InvalidOffset;
  215. /// <summary>
  216. /// Offset in bytes to where the memory of the control starts. Relative to
  217. /// the offset of the parent control (which may be the device itself).
  218. /// </summary>
  219. /// <value>Byte offset of the control.</value>
  220. /// <remarks>
  221. /// If the attribute is applied to fields in an <see cref="InputControlLayout"/> and
  222. /// this property is not set, the offset of the field is used instead.
  223. ///
  224. /// <example>
  225. /// <code>
  226. /// public struct MyStateStruct : IInputStateTypeInfo
  227. /// {
  228. /// public int buttons;
  229. ///
  230. /// [InputControl] // Automatically uses the offset of 'axis'.
  231. /// public float axis;
  232. /// }
  233. ///
  234. /// [InputControlLayout(stateType = typeof(MyStateStruct))]
  235. /// public class MyDevice : InputDevice
  236. /// {
  237. /// }
  238. /// </code>
  239. /// </example>
  240. /// </remarks>
  241. /// <seealso cref="InputControlLayout.ControlItem.offset"/>
  242. public uint offset { get; set; } = InputStateBlock.InvalidOffset;
  243. /// <summary>
  244. /// Size of the memory storage for the control in bits.
  245. /// </summary>
  246. /// <value>Size of the control in bits.</value>
  247. /// <remarks>
  248. /// If the attribute is applied to fields in an <see cref="InputControlLayout"/> and
  249. /// this property is not set, the size is taken from the field.
  250. ///
  251. /// <example>
  252. /// <code>
  253. /// public struct MyStateStruct : IInputStateTypeInfo
  254. /// {
  255. /// public int buttons;
  256. ///
  257. /// [InputControl] // Automatically uses sizeof(float).
  258. /// public float axis;
  259. /// }
  260. ///
  261. /// [InputControlLayout(stateType = typeof(MyStateStruct))]
  262. /// public class MyDevice : InputDevice
  263. /// {
  264. /// }
  265. /// </code>
  266. /// </example>
  267. /// </remarks>
  268. /// <seealso cref="InputControlLayout.ControlItem.sizeInBits"/>
  269. /// <seealso cref="InputStateBlock.sizeInBits"/>
  270. public uint sizeInBits { get; set; }
  271. public int arraySize { get; set; }
  272. /// <summary>
  273. /// Display name to assign to the control.
  274. /// </summary>
  275. /// <value>Display name for the control.</value>
  276. /// <seealso cref="InputControl.displayName"/>
  277. /// <seealso cref="InputControlLayout.ControlItem.displayName"/>
  278. public string displayName { get; set; }
  279. /// <summary>
  280. /// Short display name to assign to the control.
  281. /// </summary>
  282. /// <value>Short display name for the control.</value>
  283. /// <seealso cref="InputControl.shortDisplayName"/>
  284. /// <seealso cref="InputControlLayout.ControlItem.shortDisplayName"/>
  285. public string shortDisplayName { get; set; }
  286. /// <summary>
  287. /// Whether the control is noisy. Off by default.
  288. /// </summary>
  289. /// <value>Whether control is noisy.</value>
  290. /// <seealso cref="InputControl.noisy"/>
  291. /// <seealso cref="InputControlLayout.ControlItem.isNoisy"/>
  292. public bool noisy { get; set; }
  293. /// <summary>
  294. /// Whether the control is synthetic. Off by default.
  295. /// </summary>
  296. /// <value>Whether control is synthetic.</value>
  297. /// <seealso cref="InputControl.synthetic"/>
  298. /// <seealso cref="InputControlLayout.ControlItem.isSynthetic"/>
  299. public bool synthetic { get; set; }
  300. /// <summary>
  301. /// Default state to write into the control's memory.
  302. /// </summary>
  303. /// <value>Default memory state for the control.</value>
  304. /// <remarks>
  305. /// This is not the default <em>value</em> but rather the default memory state, i.e.
  306. /// the raw memory value read and the processed and returned as a value. By default
  307. /// this is <c>null</c> and result in a control's memory to be initialized with all
  308. /// zeroes.
  309. /// </remarks>
  310. /// <seealso cref="InputControlLayout.ControlItem.defaultState"/>
  311. public object defaultState { get; set; }
  312. /// <summary>
  313. /// Lower limit for values of the control.
  314. /// </summary>
  315. /// <value>Lower limit for values of the control.</value>
  316. /// <remarks>
  317. /// This is null by default in which case no lower bound is applied to the TODO
  318. /// </remarks>
  319. public object minValue { get; set; }
  320. public object maxValue { get; set; }
  321. }
  322. }