using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Processors;
using UnityEngine.InputSystem.Utilities;
////TODO: make sure that alterations made to InputSystem.settings in play mode do not leak out into edit mode or the asset
////TODO: handle case of supportFixedUpdates and supportDynamicUpdates both being set to false; should it be an enum?
////TODO: figure out how this gets into a build
////TODO: allow setting up single- and multi-user configs for the project
////TODO: allow enabling/disabling plugins
////REVIEW: should the project settings include a list of action assets to use? (or to force into a build)
////REVIEW: add extra option to enable late-updates?
////REVIEW: put default sensor sampling frequency here?
////REVIEW: put default gamepad polling frequency here?
namespace UnityEngine.InputSystem
{
///
/// Project-wide input settings.
///
///
/// Several aspects of the input system can be customized to tailor how the system functions to the
/// specific needs of a project. These settings are collected in this class. There is one global
/// settings object active at any one time. It can be accessed and set through .
///
/// Changing a setting on the object takes effect immediately. It also triggers the
/// callback.
///
///
///
public class InputSettings : ScriptableObject
{
///
/// Determine how the input system updates, i.e. processes pending input events.
///
/// When to run input updates.
///
/// By default, input updates will automatically be triggered as part of the player loop.
/// If updateMode is set to
/// (the default), then right at the beginning of a dynamic update (i.e. before all
/// MonoBehaviour.Update methods are called), input is processed. And if updateMode
/// is set to , then right at the beginning
/// of each fixed update (i.e. before all MonoBehaviour.FixedUpdate methods are
/// called), input is processed.
///
/// Additionally, if there are devices that need updates right before rendering (see ), an extra update will be run right before
/// rendering. This special update will only consume input on devices that have
/// set to true.
///
/// You can run updates manually using . Doing so
/// outside of tests is only recommended, however, if updateMode is set to
/// (in which case it is actually required
/// for input to be processed at all).
///
/// Note that in the editor, input updates will also run before each editor update
/// (i.e. as part of EditorApplication.update). Player and editor input state
/// are kept separate, though, so any input consumed in editor updates will not be visible
/// in player updates and vice versa.
///
///
public UpdateMode updateMode
{
get => m_UpdateMode;
set
{
if (m_UpdateMode == value)
return;
m_UpdateMode = value;
OnChange();
}
}
///
/// If true, sensors that deliver rotation values on handheld devices will automatically adjust
/// rotations when the screen orientation changes.
///
///
/// This is enabled by default.
///
/// If enabled, rotation values will be rotated around Z. In , values
/// remain unchanged. In , they will be rotated by 180 degrees.
/// In by 90 degrees, and in
/// by 270 degrees.
///
/// Sensors affected by this setting are , , and .
///
///
public bool compensateForScreenOrientation
{
get => m_CompensateForScreenOrientation;
set
{
if (m_CompensateForScreenOrientation == value)
return;
m_CompensateForScreenOrientation = value;
OnChange();
}
}
///
/// Whether to not make a device .current (see )
/// when there is only noise in the input.
///
/// Whether to check input on devices for noise.
///
/// This is disabled by default.
///
/// When toggled on, this property adds extra processing every time input is
/// received on a device that is considered noisy. These devices are those that
/// have at least one control that is marked as .
/// A good example is the PS4 controller which has a gyroscope sensor built into
/// the device. Whereas sticks and buttons on the device require user interaction
/// to produce non-default values, the gyro will produce varying values even if
/// the device just sits there without user interaction.
///
/// Without noise filtering, a PS4 controller will thus continually make itself
/// current as it will send a continuous stream of input even when not actively
/// used by the player. By toggling this property on, each input event will be
/// run through a noise mask. Only if state has changed outside of memory areas
/// marked as noise will the input be considered valid user interaction and the
/// device will be made current. Note that in this process, the system does
/// not determine whether non-noisy controls on the device have actually
/// changed value. All the system establishes is whether such controls have changed
/// state. However, processing such as for deadzones may cause values
/// to not effectively change even though the non-noisy state of the device has
/// changed.
///
///
///
public bool filterNoiseOnCurrent
{
get => m_FilterNoiseOnCurrent;
set
{
if (m_FilterNoiseOnCurrent == value)
return;
m_FilterNoiseOnCurrent = value;
OnChange();
}
}
///
/// Default value used when nothing is set explicitly on
/// or .
///
/// Default lower limit for deadzones.
///
/// "Deadzones" refer to limits established for the range of values accepted as input
/// on a control. If the value for the control falls outside the range, i.e. below the
/// given minimum or above the given maximum, the value is clamped to the respective
/// limit.
///
/// This property configures the default lower bound of the value range.
///
/// Note that deadzones will by default re-normalize values after clamping. This means that
/// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
/// to [0..1].
///
/// Note that deadzones preserve the sign of inputs. This means that both the upper and
/// the lower deadzone bound extend to both the positive and the negative range. For example,
/// a deadzone min of 0.1 will clamp values between -0.1 and +0.1.
///
/// The most common example of where deadzones are used are the sticks on gamepads, i.e.
/// and . Sticks will
/// usually be wobbly to some extent (just how wobbly varies greatly between different
/// types of controllers -- which means that often deadzones need to be configured on a
/// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
/// can be filtered out and noise in these areas can effectively be eliminated this way.
///
/// The default value for this property is 0.125.
///
///
///
public float defaultDeadzoneMin
{
get => m_DefaultDeadzoneMin;
set
{
if (m_DefaultDeadzoneMin == value)
return;
m_DefaultDeadzoneMin = value;
OnChange();
}
}
///
/// Default value used when nothing is set explicitly on
/// or .
///
/// Default upper limit for deadzones.
///
/// "Deadzones" refer to limits established for the range of values accepted as input
/// on a control. If the value for the control falls outside the range, i.e. below the
/// given minimum or above the given maximum, the value is clamped to the respective
/// limit.
///
/// This property configures the default upper bound of the value range.
///
/// Note that deadzones will by default re-normalize values after clamping. This means that
/// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
/// to [0..1].
///
/// Note that deadzones preserve the sign of inputs. This means that both the upper and
/// the lower deadzone bound extend to both the positive and the negative range. For example,
/// a deadzone max of 0.95 will clamp values of >0.95 and <-0.95.
///
/// The most common example of where deadzones are used are the sticks on gamepads, i.e.
/// and . Sticks will
/// usually be wobbly to some extent (just how wobbly varies greatly between different
/// types of controllers -- which means that often deadzones need to be configured on a
/// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
/// can be filtered out and noise in these areas can effectively be eliminated this way.
///
/// The default value for this property is 0.925.
///
///
///
public float defaultDeadzoneMax
{
get => m_DefaultDeadzoneMax;
set
{
if (m_DefaultDeadzoneMax == value)
return;
m_DefaultDeadzoneMax = value;
OnChange();
}
}
///
/// The default value threshold for when a button is considered pressed. Used if
/// no explicit thresholds are set on parameters such as
/// or .
///
/// Default button press threshold.
///
/// In the input system, each button constitutes a full floating-point value. Pure
/// toggle buttons, such as for example, will simply
/// alternate between 0 (not pressed) and 1 (pressed). However, buttons may also have
/// ranges, such as for example. When used in a context
/// where a clear distinction between pressed and not pressed is required, we need a value
/// beyond which we consider the button pressed.
///
/// By setting this property, the default value for this can be configured. If a button
/// has a value equal to or greater than the button press point, it is considered pressed.
///
/// The default value is 0.5.
///
/// Lowering the button press point will make triggers feel more like hair-triggers (akin
/// to using the hair-trigger feature on Xbox Elite controllers). However, it may make using
/// the directional buttons (i.e. etc) be fickle as
/// solely moving in only one direction with sticks isn't easy. To counteract that, the button
/// press points on the stick buttons can be raised.
///
/// Another solution is to simply lower the press points on the triggers specifically.
///
///
///
/// InputSystem.RegisterLayoutOverride(@"
/// {
/// ""name"" : ""HairTriggers"",
/// ""extend"" : ""Gamepad"",
/// ""controls"" [
/// { ""name"" : ""leftTrigger"", ""parameters"" : ""pressPoint=0.1"" },
/// { ""name"" : ""rightTrigger"", ""parameters"" : ""pressPoint=0.1"" }
/// ]
/// }
/// ");
///
///
///
///
///
///
///
///
///
public float defaultButtonPressPoint
{
get => m_DefaultButtonPressPoint;
set
{
if (m_DefaultButtonPressPoint == value)
return;
m_DefaultButtonPressPoint = value;
OnChange();
}
}
///
/// Default time (in seconds) within which a press and release has to occur for it
/// to be registered as a "tap".
///
/// Default upper limit on press durations for them to register as taps.
///
/// A tap is considered as a quick press-and-release on a button-like input control.
/// This property determines just how quick the press-and-release has to be, i.e. what
/// the maximum time is that can elapse between the button being pressed and released
/// again. If the delay between press and release is greater than this time, the
/// input does not qualify as a tap.
///
/// The default tap time is 0.2 seconds.
///
///
public float defaultTapTime
{
get => m_DefaultTapTime;
set
{
if (m_DefaultTapTime == value)
return;
m_DefaultTapTime = value;
OnChange();
}
}
public float defaultSlowTapTime
{
get => m_DefaultSlowTapTime;
set
{
if (m_DefaultSlowTapTime == value)
return;
m_DefaultSlowTapTime = value;
OnChange();
}
}
public float defaultHoldTime
{
get => m_DefaultHoldTime;
set
{
if (m_DefaultHoldTime == value)
return;
m_DefaultHoldTime = value;
OnChange();
}
}
public float tapRadius
{
get => m_TapRadius;
set
{
if (m_TapRadius == value)
return;
m_TapRadius = value;
OnChange();
}
}
public float multiTapDelayTime
{
get => m_MultiTapDelayTime;
set
{
if (m_MultiTapDelayTime == value)
return;
m_MultiTapDelayTime = value;
OnChange();
}
}
///
/// List of device layouts used by the project.
///
///
/// This would usually be one of the high-level abstract device layouts. For example, for
/// a game that supports touch, gamepad, and keyboard&mouse, the list would be
/// { "Touchscreen", "Gamepad", "Mouse", "Keyboard" }. However, nothing prevents the
/// the user from adding something a lot more specific. A game that can only be played
/// with a DualShock controller could make this list just be { "DualShockGamepad" },
/// for example.
///
/// In the editor, we use the information to filter what we display to the user by automatically
/// filtering out irrelevant controls in the control picker and such.
///
/// The information is also used when a new device is discovered. If the device is not listed
/// as supported by the project, it is ignored.
///
/// The list is empty by default. An empty list indicates that no restrictions are placed on what
/// devices are supported. In this editor, this means that all possible devices and controls are
/// shown.
///
///
public ReadOnlyArray supportedDevices
{
get => new ReadOnlyArray(m_SupportedDevices);
set
{
// Detect if there was a change.
if (supportedDevices.Count == value.Count)
{
var hasChanged = false;
for (var i = 0; i < supportedDevices.Count; ++i)
if (m_SupportedDevices[i] != value[i])
{
hasChanged = true;
break;
}
if (!hasChanged)
return;
}
m_SupportedDevices = value.ToArray();
OnChange();
}
}
[Tooltip("Determine which type of devices are used by the application. By default, this is empty meaning that all devices recognized "
+ "by Unity will be used. Restricting the set of supported devices will make only those devices appear in the input system.")]
[SerializeField] private string[] m_SupportedDevices;
[Tooltip("Determine when Unity processes events. By default, accumulated input events are flushed out before each fixed update and "
+ "before each dynamic update. This setting can be used to restrict event processing to only where the application needs it.")]
[SerializeField] private UpdateMode m_UpdateMode = UpdateMode.ProcessEventsInDynamicUpdate;
[SerializeField] private bool m_CompensateForScreenOrientation = true;
[SerializeField] private bool m_FilterNoiseOnCurrent = false;
[SerializeField] private float m_DefaultDeadzoneMin = 0.125f;
[SerializeField] private float m_DefaultDeadzoneMax = 0.925f;
// A setting of 0.5 seems to roughly be what games generally use on the gamepad triggers.
// Having a higher value here also obsoletes the need for custom press points on stick buttons
// (the up/down/left/right ones).
[SerializeField] private float m_DefaultButtonPressPoint = 0.5f;
[SerializeField] private float m_DefaultTapTime = 0.2f;
[SerializeField] private float m_DefaultSlowTapTime = 0.5f;
[SerializeField] private float m_DefaultHoldTime = 0.4f;
[SerializeField] private float m_TapRadius = 5;
[SerializeField] private float m_MultiTapDelayTime = 0.75f;
internal void OnChange()
{
if (InputSystem.settings == this)
InputSystem.s_Manager.ApplySettings();
}
internal const int s_OldUnsupportedFixedAndDynamicUpdateSetting = 0;
///
/// How the input system should update.
///
///
/// By default, the input system will run event processing as part of the player loop. In the default configuration,
/// the processing will happens once before every every dynamic update (), i.e.
/// is the default behavior.
///
/// There are two types of updates not governed by UpdateMode. One is which
/// will always be enabled in the editor and govern input updates for s in
/// sync to .
///
/// The other update type is . This type of update is enabled and disabled
/// automatically in response to whether devices are present requiring this type of update (). This update does not consume extra state.
///
///
///
///
///
public enum UpdateMode
{
// Removed: ProcessEventsInBothFixedAndDynamicUpdate=0
///
/// Automatically run input updates right before every .
///
///
/// In this mode, no processing happens specifically for fixed updates. Querying input state in
/// will result in errors being logged in the editor and in
/// development builds. In release player builds, the value of the dynamic update state is returned.
///
ProcessEventsInDynamicUpdate = 1,
///
/// Automatically input run updates right before every .
///
///
/// In this mode, no processing happens specifically for dynamic updates. Querying input state in
/// will result in errors being logged in the editor and in
/// development builds. In release player builds, the value of the fixed update state is returned.
///
ProcessEventsInFixedUpdate,
///
/// Do not run updates automatically. In this mode, must be called
/// manually to update input.
///
///
/// This mode is most useful for placing input updates in the frame explicitly at an exact location.
///
/// Note that failing to call may result in a lot of events
/// accumulating or some input getting lost.
///
ProcessEventsManually,
}
}
}