using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
namespace UnityEngine.InputSystem.LowLevel
{
internal struct JoystickState : IInputStateTypeInfo
{
public static FourCC kFormat => new FourCC('J', 'O', 'Y');
[InputControl(name = "trigger", displayName = "Trigger", layout = "Button", usages = new[] { "PrimaryTrigger", "PrimaryAction", "Submit" }, bit = (int)Button.Trigger)]
public int buttons;
[InputControl(displayName = "Stick", layout = "Stick", usage = "Primary2DMotion", processors = "stickDeadzone")]
public Vector2 stick;
public enum Button
{
// IMPORTANT: Order has to match what is expected by DpadControl.
HatSwitchUp,
HatSwitchDown,
HatSwitchLeft,
HatSwitchRight,
Trigger
}
public FourCC format => kFormat;
}
}
namespace UnityEngine.InputSystem
{
///
/// A joystick with an arbitrary number of buttons and axes.
///
///
/// Joysticks are somewhat hard to classify as there is little commonality other
/// than that there is one main stick 2D control and at least one button. From the
/// input system perspective, everything that is not a and
/// that has at least one and one control
/// is considered a candidate for being a joystick.
///
/// Optionally, a joystick may also have the ability to , i.e.
/// for the stick to rotate around its own axis, and at least one .
///
/// Note that devices based on Joystick may have many more controls. Joystick
/// itself only defines a minimum required to separate joysticks as a concept
/// from other types of devices.
///
[InputControlLayout(stateType = typeof(JoystickState), isGenericTypeOfDevice = true)]
public class Joystick : InputDevice
{
///
/// The primary trigger button of the joystick.
///
/// Control representing the primary trigger button.
///
/// This is the type control on the joystick
/// that has the usage.
///
public ButtonControl trigger { get; protected set; }
///
/// The 2D axis of the stick itself.
///
/// Control representing the main joystick axis.
///
/// This is the type control on the joystick
/// that has the usage.
///
public StickControl stick { get; protected set; }
///
/// An optional control representing the rotation of the stick around its
/// own axis (i.e. side-to-side circular motion). If not supported, will be
/// null.
///
/// Control representing the twist motion of the joystick.
///
/// This is the type control on the joystick
/// that has the usage.
///
public AxisControl twist { get; protected set; }
///
/// An optional control representing a four-way "hat switch" on the
/// joystick. If not supported, will be null.
///
/// Control representing a hatswitch on the joystick.
///
/// Hat switches are usually thumb-operated four-way switches that operate
/// much like the "d-pad" on a gamepad (see ).
/// If present, this is the type control on the
/// joystick that has the usage.
///
public Vector2Control hatswitch { get; protected set; }
///
/// The joystick that was added or used last. Null if there is none.
///
/// Joystick that was added or used last.
///
/// See for details about when a device
/// is made current.
///
///
public static Joystick current { get; private set; }
///
/// A list of joysticks currently connected to the system.
///
/// All currently connected joystick.
///
/// Does not cause GC allocation.
///
/// Do not hold on to the value returned by this getter but rather query it whenever
/// you need it. Whenever the joystick setup changes, the value returned by this getter
/// is invalidated.
///
///
public new static ReadOnlyArray all => new ReadOnlyArray(s_Joysticks, 0, s_JoystickCount);
///
/// Called when the joystick has been created but before it is added
/// to the system.
///
protected override void FinishSetup()
{
// Mandatory controls.
trigger = GetChildControl("{PrimaryTrigger}");
stick = GetChildControl("{Primary2DMotion}");
// Optional controls.
twist = TryGetChildControl("{Twist}");
hatswitch = TryGetChildControl("{Hatswitch}");
base.FinishSetup();
}
///
/// Make the joystick the one.
///
///
/// This is called automatically by the input system when a device
/// receives input or is added to the system. See
/// for details.
///
public override void MakeCurrent()
{
base.MakeCurrent();
current = this;
}
///
/// Called when the joystick is added to the system.
///
protected override void OnAdded()
{
ArrayHelpers.AppendWithCapacity(ref s_Joysticks, ref s_JoystickCount, this);
}
///
/// Called when the joystick is removed from the system.
///
protected override void OnRemoved()
{
base.OnRemoved();
if (current == this)
current = null;
// Remove from `all`.
var index = ArrayHelpers.IndexOfReference(s_Joysticks, this, s_JoystickCount);
if (index != -1)
ArrayHelpers.EraseAtWithCapacity(s_Joysticks, ref s_JoystickCount, index);
else
{
Debug.Assert(false,
$"Joystick {this} seems to not have been added but is being removed (joystick list: {string.Join(", ", all)})"); // Put in else to not allocate on normal path.
}
}
private static int s_JoystickCount;
private static Joystick[] s_Joysticks;
}
}