File size: 15,328 Bytes
18a519f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
using System;
using UnityEngine.InputSystem.Composites;
using UnityEngine.InputSystem.LowLevel;

namespace UnityEngine.InputSystem.Layouts
{
    /// <summary>
    /// Mark a field or property as representing/identifying an input control in some form.
    /// </summary>
    /// <remarks>
    /// This attribute is used in different places for different purposes.
    ///
    /// When creating input control layouts (<see cref="InputControlLayout"/>) in C#, applying the
    /// attribute to fields in a state struct (see <see cref="IInputStateTypeInfo"/> or <see cref="GamepadState"/>
    /// for an example) or to properties in an input device (<see cref="InputDevice"/>), will cause an
    /// <see cref="InputControl"/> to be created from the field or property at runtime. The attribute
    /// can be applied multiple times to create multiple input controls (e.g. when having an int field
    /// that represents a bitfield where each bit is a separate button).
    ///
    /// <example>
    /// <code>
    /// public class MyDevice : InputDevice
    /// {
    ///     // Adds an InputControl with name=myButton and layout=Button to the device.
    ///     [InputControl]
    ///     public ButtonControl myButton { get; set; }
    /// }
    /// </code>
    /// </example>
    ///
    /// Another use is for marking <c>string</c> type fields that represent input control paths. Applying
    /// the attribute to them will cause them to automatically use a custom inspector similar to the one
    /// found in the action editor. For this use, only the <see cref="layout"/> property is taken into
    /// account.
    ///
    /// <example>
    /// <code>
    /// public class MyBehavior : MonoBehaviour
    /// {
    ///     // In the inspector, shows a control selector that is restricted to
    ///     // selecting buttons. As a result, controlPath will be set to path
    ///     // representing the control that was picked (e.g. "&lt;Gamepad&gt;/buttonSouth").
    ///     [InputControl(layout = "Button")]
    ///     public string controlPath;
    ///
    ///     protected void OnEnable()
    ///     {
    ///         // Find controls by path.
    ///         var controls = InputSystem.FindControl(controlPath);
    ///         //...
    ///     }
    /// }
    /// </code>
    /// </example>
    ///
    /// Finally, the attribute is also used in composite bindings (<see cref="InputBindingComposite"/>)
    /// to mark fields that reference parts of the composite. An example for this is <see cref="AxisComposite.negative"/>.
    /// In this use, also only the <see cref="layout"/> property is taken into account while other properties
    /// are ignored.
    ///
    /// <example>
    /// <code>
    /// public class MyComposite : InputBindingComposite&lt;float&gt;
    /// {
    ///     // Add a part to the composite called 'firstControl' which expects
    ///     // AxisControls.
    ///     [InputControl(layout = "Axis")]
    ///     public int firstControl;
    ///
    ///     // Add a part to the composite called 'secondControl' which expects
    ///     // Vector3Controls.
    ///     [InputControl(layout = "Vector3")]
    ///     public int secondControl;
    ///
    ///     //...
    /// }
    /// </code>
    /// </example>
    /// </remarks>
    /// <seealso cref="InputControlLayout"/>
    /// <seealso cref="InputBindingComposite"/>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
    public sealed class InputControlAttribute : PropertyAttribute
    {
        /// <summary>
        /// Layout to use for the control.
        /// </summary>
        /// <value>Layout to use for the control.</value>
        /// <remarks>
        /// If this is not set, the system tries to infer the layout type from the value type of
        /// the field or property. If the value type is itself registered as a layout, that layout
        /// will be used (e.g. when you have a property of type <see cref="Controls.ButtonControl"/>, the layout
        /// will be inferred to be "Button"). Otherwise, if a layout with the same name as the type is registered,
        /// that layout will be used (e.g. when you have a field of type <see cref="Vector3"/>, the layout
        /// will be inferred to be "Vector3").
        /// </remarks>
        /// <seealso cref="InputControlLayout"/>
        public string layout { get; set; }

        /// <summary>
        /// Layout variant to use for the control.
        /// </summary>
        /// <value>Layout variant to use for the control.</value>
        public string variants { get; set; }

        /// <summary>
        /// Name to give to the name. If null or empty, the name of the property or
        /// field the attribute is applied to will be used.
        /// </summary>
        /// <value>Name to give to the control.</value>
        /// <seealso cref="InputControl.name"/>
        public string name { get; set; }

        /// <summary>
        /// Storage format to use for the control. If not set, default storage format
        /// for the given <see cref="layout"/> is used.
        /// </summary>
        /// <value>Memory storage format to use for the control.</value>
        /// <seealso cref="InputStateBlock.format"/>
        public string format { get; set; }

        /// <summary>
        /// Usage to apply to the control.
        /// </summary>
        /// <value>Usage for the control.</value>
        /// <remarks>
        /// This property can be used in place of <see cref="usages"/> to set just a single
        /// usage on the control.
        /// </remarks>
        /// <seealso cref="InputControl.usages"/>
        /// <seealso cref="InputControlLayout.ControlItem.usages"/>
        /// <seealso cref="CommonUsages"/>
        public string usage { get; set; }

        /// <summary>
        /// Usages to apply to the control.
        /// </summary>
        /// <value>Usages for the control.</value>
        /// <remarks>
        /// This property should be used instead of <see cref="usage"/> when a control has multiple usages.
        /// </remarks>
        /// <seealso cref="InputControl.usages"/>
        /// <seealso cref="InputControlLayout.ControlItem.usages"/>
        /// <seealso cref="CommonUsages"/>
        [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.")]
        public string[] usages { get; set; }

        /// <summary>
        /// Optional list of parameters to apply to the control.
        /// </summary>
        /// <value>Parameters to apply to the control.</value>
        /// <remarks>
        /// An <see cref="InputControl"/> may expose public fields which can be set as
        /// parameters. An example of this is <see cref="Controls.AxisControl.clamp"/>.
        ///
        /// <example>
        /// <code>
        /// public struct MyStateStruct : IInputStateTypeInfo
        /// {
        ///     [InputControl(parameters = "clamp,clampMin=-0.5,clampMax=0.5")]
        ///     public float axis;
        /// }
        /// </code>
        /// </example>
        /// </remarks>
        /// <seealso cref="InputControlLayout.ControlItem.parameters"/>
        public string parameters { get; set; }

        /// <summary>
        /// Optional list of processors to add to the control.
        /// </summary>
        /// <value>Processors to apply to the control.</value>
        /// <remarks>
        /// Each element in the list is a name of a processor (as registered with
        /// <see cref="InputSystem.RegisterProcessor{T}"/>) followed by an optional
        /// list of parameters.
        ///
        /// For example, <c>"normalize(min=0,max=256)"</c> is one element that puts
        /// a <c>NormalizeProcessor</c> on the control and sets its <c>min</c> field
        /// to 0 and its its <c>max</c> field to 256.
        ///
        /// Multiple processors can be put on a control by separating them with a comma.
        /// For example, <c>"normalize(max=256),scale(factor=2)"</c> puts both a <c>NormalizeProcessor</c>
        /// and a <c>ScaleProcessor</c> on the control. Processors are applied in the
        /// order they are listed.
        /// </remarks>
        /// <seealso cref="InputControlLayout.ControlItem.processors"/>
        /// <seealso cref="InputBinding.processors"/>
        public string processors { get; set; }

        /// <summary>
        /// An alternative name that can be used in place of <see cref="name"/> to find
        /// the control.
        /// </summary>
        /// <value>Alternative name for the control.</value>
        /// <remarks>
        /// This property can be used instead of <see cref="aliases"/> when there is only a
        /// single alias for the control.
        ///
        /// Aliases, like names, are case-insensitive. Any control may have arbitrary many
        /// aliases.
        /// </remarks>
        /// <seealso cref="InputControl.aliases"/>
        /// <seealso cref="InputControlLayout.ControlItem.aliases"/>
        public string alias { get; set; }

        /// <summary>
        /// A list of alternative names that can be used in place of <see cref="name"/> to
        /// find the control.
        /// </summary>
        /// <value>Alternative names for the control.</value>
        /// <remarks>
        /// This property should be used instead of <see cref="alias"/> when a control has
        /// multiple aliases.
        ///
        /// Aliases, like names, are case-insensitive. Any control may have arbitrary many
        /// aliases.
        /// </remarks>
        /// <seealso cref="InputControl.aliases"/>
        /// <seealso cref="InputControlLayout.ControlItem.aliases"/>
        [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.")]
        public string[] aliases { get; set; }

        public string useStateFrom { get; set; }

        public uint bit { get; set; } = InputStateBlock.InvalidOffset;

        /// <summary>
        /// Offset in bytes to where the memory of the control starts. Relative to
        /// the offset of the parent control (which may be the device itself).
        /// </summary>
        /// <value>Byte offset of the control.</value>
        /// <remarks>
        /// If the attribute is applied to fields in an <see cref="InputControlLayout"/> and
        /// this property is not set, the offset of the field is used instead.
        ///
        /// <example>
        /// <code>
        /// public struct MyStateStruct : IInputStateTypeInfo
        /// {
        ///     public int buttons;
        ///
        ///     [InputControl] // Automatically uses the offset of 'axis'.
        ///     public float axis;
        /// }
        ///
        /// [InputControlLayout(stateType = typeof(MyStateStruct))]
        /// public class MyDevice : InputDevice
        /// {
        /// }
        /// </code>
        /// </example>
        /// </remarks>
        /// <seealso cref="InputControlLayout.ControlItem.offset"/>
        public uint offset { get; set; } = InputStateBlock.InvalidOffset;

        /// <summary>
        /// Size of the memory storage for the control in bits.
        /// </summary>
        /// <value>Size of the control in bits.</value>
        /// <remarks>
        /// If the attribute is applied to fields in an <see cref="InputControlLayout"/> and
        /// this property is not set, the size is taken from the field.
        ///
        /// <example>
        /// <code>
        /// public struct MyStateStruct : IInputStateTypeInfo
        /// {
        ///     public int buttons;
        ///
        ///     [InputControl] // Automatically uses sizeof(float).
        ///     public float axis;
        /// }
        ///
        /// [InputControlLayout(stateType = typeof(MyStateStruct))]
        /// public class MyDevice : InputDevice
        /// {
        /// }
        /// </code>
        /// </example>
        /// </remarks>
        /// <seealso cref="InputControlLayout.ControlItem.sizeInBits"/>
        /// <seealso cref="InputStateBlock.sizeInBits"/>
        public uint sizeInBits { get; set; }

        public int arraySize { get; set; }

        /// <summary>
        /// Display name to assign to the control.
        /// </summary>
        /// <value>Display name for the control.</value>
        /// <seealso cref="InputControl.displayName"/>
        /// <seealso cref="InputControlLayout.ControlItem.displayName"/>
        public string displayName { get; set; }

        /// <summary>
        /// Short display name to assign to the control.
        /// </summary>
        /// <value>Short display name for the control.</value>
        /// <seealso cref="InputControl.shortDisplayName"/>
        /// <seealso cref="InputControlLayout.ControlItem.shortDisplayName"/>
        public string shortDisplayName { get; set; }

        /// <summary>
        /// Whether the control is noisy. Off by default.
        /// </summary>
        /// <value>Whether control is noisy.</value>
        /// <seealso cref="InputControl.noisy"/>
        /// <seealso cref="InputControlLayout.ControlItem.isNoisy"/>
        public bool noisy { get; set; }

        /// <summary>
        /// Whether the control is synthetic. Off by default.
        /// </summary>
        /// <value>Whether control is synthetic.</value>
        /// <seealso cref="InputControl.synthetic"/>
        /// <seealso cref="InputControlLayout.ControlItem.isSynthetic"/>
        public bool synthetic { get; set; }

        /// <summary>
        /// Allows you to specify that a control should not be reset when its device is reset.
        /// </summary>
        /// <value>If true, resets of the device will leave the value of the control untouched except if a "hard" reset
        /// is explicitly enforced.</value>
        /// <seealso cref="InputSystem.ResetDevice"/>
        /// <seealso cref="InputControlLayout.ControlItem.dontReset"/>
        public bool dontReset { get; set; }

        /// <summary>
        /// Default state to write into the control's memory.
        /// </summary>
        /// <value>Default memory state for the control.</value>
        /// <remarks>
        /// This is not the default <em>value</em> but rather the default memory state, i.e.
        /// the raw memory value read and the processed and returned as a value. By default
        /// this is <c>null</c> and result in a control's memory to be initialized with all
        /// zeroes.
        /// </remarks>
        /// <seealso cref="InputControlLayout.ControlItem.defaultState"/>
        public object defaultState { get; set; }

        /// <summary>
        /// Lower limit for values of the control.
        /// </summary>
        /// <value>Lower limit for values of the control.</value>
        /// <remarks>
        /// This is null by default in which case no lower bound is applied to the TODO
        /// </remarks>
        public object minValue { get; set; }
        public object maxValue { get; set; }
    }
}