using System; using UnityEngine.InputSystem.Composites; using UnityEngine.InputSystem.LowLevel; namespace UnityEngine.InputSystem.Layouts { /// /// Mark a field or property as representing/identifying an input control in some form. /// /// /// This attribute is used in different places for different purposes. /// /// When creating input control layouts () in C#, applying the /// attribute to fields in a state struct (see or /// for an example) or to properties in an input device (), will cause an /// 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). /// /// /// /// public class MyDevice : InputDevice /// { /// // Adds an InputControl with name=myButton and layout=Button to the device. /// [InputControl] /// public ButtonControl myButton { get; set; } /// } /// /// /// /// Another use is for marking string 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 property is taken into /// account. /// /// /// /// 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); /// //... /// } /// } /// /// /// /// Finally, the attribute is also used in composite bindings () /// to mark fields that reference parts of the composite. An example for this is . /// In this use, also only the property is taken into account while other properties /// are ignored. /// /// /// /// 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; /// /// //... /// } /// /// /// /// /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] public sealed class InputControlAttribute : PropertyAttribute { /// /// Layout to use for the control. /// /// Layout to use for the control. /// /// 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 , 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 , the layout /// will be inferred to be "Vector3"). /// /// public string layout { get; set; } /// /// Layout variant to use for the control. /// /// Layout variant to use for the control. public string variants { get; set; } /// /// 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. /// /// Name to give to the control. /// public string name { get; set; } /// /// Storage format to use for the control. If not set, default storage format /// for the given is used. /// /// Memory storage format to use for the control. /// public string format { get; set; } /// /// Usage to apply to the control. /// /// Usage for the control. /// /// This property can be used in place of to set just a single /// usage on the control. /// /// /// /// public string usage { get; set; } /// /// Usages to apply to the control. /// /// Usages for the control. /// /// This property should be used instead of when a control has multiple usages. /// /// /// /// [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; } /// /// Optional list of parameters to apply to the control. /// /// Parameters to apply to the control. /// /// An may expose public fields which can be set as /// parameters. An example of this is . /// /// /// /// public struct MyStateStruct : IInputStateTypeInfo /// { /// [InputControl(parameters = "clamp,clampMin=-0.5,clampMax=0.5")] /// public float axis; /// } /// /// /// /// public string parameters { get; set; } /// /// Optional list of processors to add to the control. /// /// Processors to apply to the control. /// /// Each element in the list is a name of a processor (as registered with /// ) followed by an optional /// list of parameters. /// /// For example, "normalize(min=0,max=256)" is one element that puts /// a NormalizeProcessor on the control and sets its min field /// to 0 and its its max field to 256. /// /// Multiple processors can be put on a control by separating them with a comma. /// For example, "normalize(max=256),scale(factor=2)" puts both a NormalizeProcessor /// and a ScaleProcessor on the control. Processors are applied in the /// order they are listed. /// /// /// public string processors { get; set; } /// /// An alternative name that can be used in place of to find /// the control. /// /// Alternative name for the control. /// /// This property can be used instead of when there is only a /// single alias for the control. /// /// Aliases, like names, are case-insensitive. Any control may have arbitrary many /// aliases. /// /// /// public string alias { get; set; } /// /// A list of alternative names that can be used in place of to /// find the control. /// /// Alternative names for the control. /// /// This property should be used instead of when a control has /// multiple aliases. /// /// Aliases, like names, are case-insensitive. Any control may have arbitrary many /// 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; /// /// 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). /// /// Byte offset of the control. /// /// If the attribute is applied to fields in an and /// this property is not set, the offset of the field is used instead. /// /// /// /// 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 /// { /// } /// /// /// /// public uint offset { get; set; } = InputStateBlock.InvalidOffset; /// /// Size of the memory storage for the control in bits. /// /// Size of the control in bits. /// /// If the attribute is applied to fields in an and /// this property is not set, the size is taken from the field. /// /// /// /// public struct MyStateStruct : IInputStateTypeInfo /// { /// public int buttons; /// /// [InputControl] // Automatically uses sizeof(float). /// public float axis; /// } /// /// [InputControlLayout(stateType = typeof(MyStateStruct))] /// public class MyDevice : InputDevice /// { /// } /// /// /// /// /// public uint sizeInBits { get; set; } public int arraySize { get; set; } /// /// Display name to assign to the control. /// /// Display name for the control. /// /// public string displayName { get; set; } /// /// Short display name to assign to the control. /// /// Short display name for the control. /// /// public string shortDisplayName { get; set; } /// /// Whether the control is noisy. Off by default. /// /// Whether control is noisy. /// /// public bool noisy { get; set; } /// /// Whether the control is synthetic. Off by default. /// /// Whether control is synthetic. /// /// public bool synthetic { get; set; } /// /// Default state to write into the control's memory. /// /// Default memory state for the control. /// /// This is not the default value 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 null and result in a control's memory to be initialized with all /// zeroes. /// /// public object defaultState { get; set; } /// /// Lower limit for values of the control. /// /// Lower limit for values of the control. /// /// This is null by default in which case no lower bound is applied to the TODO /// public object minValue { get; set; } public object maxValue { get; set; } } }