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. "<Gamepad>/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<float>
/// {
/// // 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; }
}
}
|