353 lines
15 KiB
C#
353 lines
15 KiB
C#
|
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; }
|
||
|
}
|
||
|
}
|