Add a layout from C#
In its most basic form, a layout can be expressed by a C# class derived from:
InputControlfor a Control layout.InputDevicefor a Device layout.
// The InputControlLayout attribute is not strictly necessary here.
// However, you can use it to set additional properties (such as
// a custom display name for the layout).
[InputControlLayout]
public class MyDevice : InputDevice
{
public AxisControl axis { get; private set; }
public ButtonControl button { get; private set; }
protected override void FinishSetup(InputDeviceBuilder builder)
{
base.FinishSetup(builder);
axis = builder.GetControl<AxisControl>("axis");
button = builder.GetControl<ButtonControl>("button");
}
}
You can then register the layout with InputSystem.RegisterLayout. This works the same for Control and for Device layouts.
// Note: This should generally be done from InitializeOnLoad/
// RuntimeInitializeOnLoad code.
InputSystem.RegisterLayout<MyDevice>();
When the layout is instantiated, the system looks at every field and property defined directly in the type to potentially turn it into one or more Control items.
- If the field or property is annotated with
InputControlAttribute, the system applies the attribute's properties to the Control item. Some special defaults apply in this case: - If the field or property has a struct type which implements
IInputStateTypeInfo, the field is considered to be an embedded state struct and the system recurses into the field or property to gather Controls from it. - Otherwise, if the type of the field or property is based on
InputControl, the system adds a Control item similar to case 1, where the member is annotated withInputControlAttribute.
Using a state structure
When you implement support for a new Input Device, there's usually an existing data format in which the Input System receives input for the Device. The easiest way to add support for the data format is to describe it with a C# struct annotated with InputControlAttribute.
public struct MyDeviceState : IInputStateTypeInfo
{
public FourCC format => new FourCC('M', 'D', 'E', 'V');
[InputControl(name = "button1", layout = "Button", bit = 0)]
[InputControl(name = "button2", layout = "Button", bit = 1)]
[InputControl(name = "dpad", layout = "Dpad", bit = 2, sizeInBits = 4)]
[InputControl(name = "dpad/up", bit = 2)]
[InputControl(name = "dpad/down", bit = 3)]
[InputControl(name = "dpad/left", bit = 4)]
[InputControl(name = "dpad/right", bit = 5)]
public int buttons;
[InputControl(layout = "Stick")]
public Vector2 stick;
[InputControl(layout = "Axis")] // Automatically converts from byte to float.
public byte trigger;
}
// The Device must be directed to the state struct we have created.
[InputControlLayout(stateType = typeof(MyDeviceState)]
public class MyDevice : InputDevice
{
}