diff --git a/Packages/com.unity.inputsystem/DocCodeSamples.Tests/DocCodeSamples.asmdef b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/DocCodeSamples.asmdef
index 180bbcadf0..6e8b6248e1 100644
--- a/Packages/com.unity.inputsystem/DocCodeSamples.Tests/DocCodeSamples.asmdef
+++ b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/DocCodeSamples.asmdef
@@ -4,7 +4,9 @@
"references": [
"GUID:75469ad4d38634e559750d17036d5f7c"
],
- "includePlatforms": [],
+ "includePlatforms": [
+ "Editor"
+ ],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
diff --git a/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs
new file mode 100644
index 0000000000..886f1d61e8
--- /dev/null
+++ b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs
@@ -0,0 +1,42 @@
+#if UNITY_INPUT_SYSTEM_ENABLE_UI
+
+using UnityEngine;
+using UnityEngine.InputSystem.UI;
+
+namespace DocCodeSamples.Tests
+{
+ internal class InputSystemUIInputModuleAssignActionsExample : MonoBehaviour
+ {
+ // Reference to the InputSystemUIInputModule component, needs to be provided in the Inspector
+ public InputSystemUIInputModule uiModule;
+
+ void Start()
+ {
+ // Assign default actions
+ AssignActions();
+ }
+
+ void AssignActions()
+ {
+ if (uiModule != null)
+ uiModule.AssignDefaultActions();
+ else
+ Debug.LogError("InputSystemUIInputModule not found.");
+ }
+
+ void UnassignActions()
+ {
+ if (uiModule != null)
+ uiModule.UnassignActions();
+ else
+ Debug.LogError("InputSystemUIInputModule not found.");
+ }
+
+ void OnDestroy()
+ {
+ // Unassign actions when the object is destroyed
+ UnassignActions();
+ }
+ }
+}
+#endif
diff --git a/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs.meta b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs.meta
new file mode 100644
index 0000000000..0dfa4a76f7
--- /dev/null
+++ b/Packages/com.unity.inputsystem/DocCodeSamples.Tests/InputSystemUIInputModuleAssignActionsExample.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 026e1117180341c1bf7847a2cc61f75b
+timeCreated: 1733488542
\ No newline at end of file
diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs
index c72e043c71..4d80420a8f 100644
--- a/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs
+++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs
@@ -39,22 +39,83 @@ namespace UnityEngine.InputSystem.UI
/// Input module that takes its input from input actions.
///
///
+ ///
+ /// This module processes all UI input based on the Input System. It is the "glue" between UI systems (UGUI, UITK)
+ /// and the Input System.
+ ///
+ ///
+ /// When adding this component from code (such as through GameObject.AddComponent), the
+ /// resulting module will automatically have assigned to it.
+ /// If you want to use your own actions, you should create an with the necessary
+ /// UI actions. You can copy the default actions and edit them as you need. To have editable Input Actions
+ /// out-of-the box you can use the project-wide actions through InputSystem.actions. More information about this
+ /// can be read in the manual documentation.
+ ///
+ ///
+ /// This module can be configured in the Editor > Inspector when added as a component to a GameObject.
+ ///
+ ///
/// This UI input module has the advantage over other such modules that it doesn't have to know
/// what devices and types of devices input is coming from. Instead, the actions hide the actual
/// sources of input from the module.
- ///
- /// When adding this component from code (such as through GameObject.AddComponent), the
- /// resulting module will automatically have a set of default input actions assigned to it
- /// (see ).
+ ///
///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// using UnityEngine;
+ /// using UnityEngine.InputSystem;
+ /// using UnityEngine.InputSystem.UI;
+ /// using UnityEngine.EventSystems;
+ ///
+ /// class InputSystemUIInputModuleExample : MonoBehaviour
+ /// {
+ /// private InputSystemUIInputModule uiModule;
+ ///
+ /// // Configure the InputSystemUIInputModule component programmatically on Start()
+ /// // But a lot of this could be done at runtime as well.
+ /// void Start()
+ /// {
+ /// // Find the EventSystem in the scene
+ /// var eventSystem = EventSystem.current;
+ ///
+ /// // Get the InputSystemUIInputModule component
+ /// uiModule = eventSystem.GetComponent<InputSystemUIInputModule>();
+ ///
+ /// // Using the default input actions just as an example. Another InputActionAsset can be used.
+ /// DefaultInputActions defaultInputActions = new DefaultInputActions();
+ /// // Example on how to assign individual actions programmatically
+ /// uiModule.actionsAsset = defaultInputActions.asset;
+ /// uiModule.leftClick = InputActionReference.Create(defaultInputActions.UI.Click);
+ /// uiModule.scrollWheel = InputActionReference.Create(defaultInputActions.UI.ScrollWheel);
+ ///
+ /// // Set other fields programmatically
+ /// uiModule.deselectOnBackgroundClick = true;
+ /// uiModule.pointerBehavior = UIPointerBehavior.SingleMouseOrPenButMultiTouchAndTrack;
+ /// uiModule.cursorLockBehavior = InputSystemUIInputModule.CursorLockBehavior.ScreenCenter;
+ /// }
+ ///
+ /// // Example on how programmatically set the move repeat delay based on the move repeat rate
+ /// void SetMoveRepeat(float value)
+ /// {
+ /// uiModule.moveRepeatRate = value;
+ /// uiModule.moveRepeatDelay = value * (1.2f);
+ /// }
+ /// }
+ ///
+ ///
[HelpURL(InputSystem.kDocUrl + "/manual/UISupport.html#setting-up-ui-input")]
public class InputSystemUIInputModule : BaseInputModule
{
///
/// Whether to clear the current selection when a click happens that does not hit any GameObject.
///
- /// If true (default), clicking outside of any GameObject will reset the current selection.
///
+ /// If true (default), clicking outside of any GameObject will reset the current selection
/// By toggling this behavior off, background clicks will keep the current selection. I.e.
/// EventSystem.currentSelectedGameObject will not be changed.
///
@@ -137,6 +198,35 @@ public float scrollDeltaPerTick
///
/// Called by EventSystem when the input module is made current.
///
+ ///
+ /// There's no need to call this method directly unless for specific reasons.
+ /// It is called by EventSystem when the input module is made current.
+ /// It sets to
+ /// if nothing is selected.
+ ///
+ ///
+ ///
+ /// using UnityEngine;
+ /// using UnityEngine.EventSystems;
+ /// using UnityEngine.InputSystem.UI;
+ ///
+ /// public class ActivateModuleExample : MonoBehaviour
+ /// {
+ /// private InputSystemUIInputModule uiModule;
+ /// void Start()
+ /// {
+ /// // Find the EventSystem in the scene
+ /// var eventSystem = EventSystem.current;
+ ///
+ /// // Get the InputSystemUIInputModule component
+ /// uiModule = eventSystem.GetComponent<InputSystemUIInputModule>();
+ ///
+ /// // Manually activate the module
+ /// uiModule.ActivateModule();
+ /// }
+ /// }
+ ///
+ ///
public override void ActivateModule()
{
base.ActivateModule();
@@ -177,7 +267,7 @@ public override void ActivateModule()
/// Calling this method from within an callback (such as )
/// will result in a warning. See the "UI vs Game Input" sample shipped with the Input System package for
/// how to deal with this fact.
- ///
+ ///
///
///
/// // In general, the pointer ID corresponds to the device ID:
@@ -197,7 +287,6 @@ public override void ActivateModule()
/// EventSystem.current.IsPointerOverGameObject(); // Equivalent.
///
///
- ///
///
///
public override bool IsPointerOverGameObject(int pointerOrTouchId)
@@ -252,6 +341,44 @@ public override bool IsPointerOverGameObject(int pointerOrTouchId)
///
///
///
+ ///
+ ///
+ /// using UnityEngine;
+ /// using UnityEngine.EventSystems;
+ /// using UnityEngine.InputSystem;
+ /// using UnityEngine.InputSystem.UI;
+ ///
+ /// public class GetLastRaycastResultExample : MonoBehaviour
+ /// {
+ /// public InputSystemUIInputModule uiModule;
+ ///
+ /// void PrintLastRaycastResult(int pointerId)
+ /// {
+ /// if (uiModule)
+ /// {
+ /// // Retrieve the last raycast result for the given pointer ID
+ /// RaycastResult raycastResult = uiModule.GetLastRaycastResult(pointerId);
+ ///
+ /// // Check if the raycast result is valid
+ /// if (raycastResult.isValid)
+ /// {
+ /// // Print details about the raycast result
+ /// Debug.Log($"Pointer ID: {pointerId}");
+ /// Debug.Log($"Hit GameObject: {raycastResult.gameObject.name}");
+ /// Debug.Log($"Distance: {raycastResult.distance}");
+ /// Debug.Log($"World Position: {raycastResult.worldPosition}");
+ /// }
+ /// }
+ ///
+ /// }
+ ///
+ /// void Update()
+ /// {
+ /// PrintLastRaycastResult(Mouse.current.deviceId);
+ /// }
+ /// }
+ ///
+ ///
public RaycastResult GetLastRaycastResult(int pointerOrTouchId)
{
var stateIndex = GetPointerStateIndexFor(pointerOrTouchId);
@@ -850,7 +977,6 @@ private bool IsMoveAllowed(AxisEventData eventData)
///
///
///
- ///
public float moveRepeatDelay
{
get => m_MoveRepeatDelay;
@@ -867,9 +993,6 @@ public float moveRepeatDelay
/// Note that a maximum of one will be sent per frame. This means that even if multiple time
/// increments of the repeat delay have passed since the last update, only one move repeat event will be generated.
///
- ///
- ///
- ///
public float moveRepeatRate
{
get => m_MoveRepeatRate;
@@ -887,6 +1010,9 @@ private bool shouldIgnoreFocus
get => explictlyIgnoreFocus || InputRuntime.s_Instance.runInBackground;
}
+ ///
+ /// (Obsolete)
+ ///
[Obsolete("'repeatRate' has been obsoleted; use 'moveRepeatRate' instead. (UnityUpgradable) -> moveRepeatRate", false)]
public float repeatRate
{
@@ -894,6 +1020,9 @@ public float repeatRate
set => moveRepeatRate = value;
}
+ ///
+ /// (Obsolete)
+ ///
[Obsolete("'repeatDelay' has been obsoleted; use 'moveRepeatDelay' instead. (UnityUpgradable) -> moveRepeatDelay", false)]
public float repeatDelay
{
@@ -903,10 +1032,14 @@ public float repeatDelay
///
/// A representing the real world origin for tracking devices.
- /// This is used to convert real world positions and rotations for pointers into Unity's global space.
- /// When using the XR Interaction Toolkit, this should be pointing to the XR Rig's Transform.
///
- /// This will transform all tracked pointers. If unset, or set to null, the Unity world origin will be used as the basis for all tracked positions and rotations.
+ ///
+ /// This is used to convert real world positions and rotations for all
+ /// pointers into Unity's global space.
+ /// When using the XR Interaction Toolkit, this should be pointing to the XR Rig's Transform.
+ /// If unset, or set to null, the Unity world origin will be used as the basis for all tracked positions and
+ /// rotations.
+ ///
public Transform xrTrackingOrigin
{
get => m_XRTrackingOrigin;
@@ -999,10 +1132,6 @@ private bool IsNavigationAction(InputActionReference reference)
///
///
///
- ///
- ///
- ///
- ///
public InputActionReference point
{
get => m_PointAction;
@@ -1044,10 +1173,6 @@ public InputActionReference point
///
///
///
- ///
- ///
- ///
- ///
public InputActionReference scrollWheel
{
get => m_ScrollWheelAction;
@@ -1090,10 +1215,6 @@ public InputActionReference scrollWheel
///
///
///
- ///
- ///
- ///
- ///
public InputActionReference leftClick
{
get => m_LeftClickAction;
@@ -1141,10 +1262,6 @@ public InputActionReference leftClick
///
///
///
- ///
- ///
- ///
- ///
public InputActionReference middleClick
{
get => m_MiddleClickAction;
@@ -1192,10 +1309,6 @@ public InputActionReference middleClick
///
///
///
- ///
- ///
- ///
- ///
public InputActionReference rightClick
{
get => m_RightClickAction;
@@ -1237,8 +1350,6 @@ public InputActionReference rightClick
///
///
///
- ///
- ///
public InputActionReference move
{
get => m_MoveAction;
@@ -1279,8 +1390,6 @@ public InputActionReference move
///
///
///
- ///
- ///
public InputActionReference submit
{
get => m_SubmitAction;
@@ -1321,8 +1430,6 @@ public InputActionReference submit
///
///
///
- ///
- ///
public InputActionReference cancel
{
get => m_CancelAction;
@@ -1364,7 +1471,6 @@ public InputActionReference cancel
///
///
///
- ///
public InputActionReference trackedDeviceOrientation
{
get => m_TrackedDeviceOrientationAction;
@@ -1406,7 +1512,6 @@ public InputActionReference trackedDeviceOrientation
///
///
///
- ///
public InputActionReference trackedDevicePosition
{
get => m_TrackedDevicePositionAction;
@@ -1424,26 +1529,10 @@ public InputActionReference trackedDevicePosition
/// Note that if an InputSystemUIInputModule component is programmatically added to a GameObject,
/// it will automatically receive the default actions as part of its OnEnable method. Use
/// to remove these assignments.
- ///
+ ///
///
- ///
- /// var go = new GameObject();
- /// go.AddComponent<EventSystem>();
- ///
- /// // Adding the UI module like this will implicitly enable it and thus lead to
- /// // automatic assignment of the default input actions.
- /// var uiModule = go.AddComponent<InputSystemUIInputModule>();
- ///
- /// // Manually remove the default input actions.
- /// uiModule.UnassignActions();
- ///
+ ///
///
- ///
- ///
- ///
-
- private static DefaultInputActions defaultActions;
-
public void AssignDefaultActions()
{
if (defaultActions == null)
@@ -1463,14 +1552,24 @@ public void AssignDefaultActions()
trackedDevicePosition = InputActionReference.Create(defaultActions.UI.TrackedDevicePosition);
}
+ private static DefaultInputActions defaultActions;
+
///
- /// Remove all action assignments, that is as well as all individual
- /// actions such as .
+ /// Remove all action assignments.
///
///
+ /// Resets reference as well as all individual
+ /// actions references, such as , and removes the correspondent callbacks hooked for
+ /// and
+ ///
+ /// It also disposes .
+ ///
/// If the current actions were enabled by the UI input module, they will be disabled in the process.
///
///
+ ///
+ ///
+ ///
public void UnassignActions()
{
defaultActions?.Dispose();
@@ -1488,6 +1587,10 @@ public void UnassignActions()
trackedDevicePosition = default;
}
+ ///
+ /// (Obsolete) This API has been obsoleted; use instead.
+ ///
+ ///
[Obsolete("'trackedDeviceSelect' has been obsoleted; use 'leftClick' instead.", true)]
public InputActionReference trackedDeviceSelect
{
@@ -1496,6 +1599,7 @@ public InputActionReference trackedDeviceSelect
}
#if UNITY_EDITOR
+ ///
protected override void Reset()
{
base.Reset();
@@ -1509,6 +1613,7 @@ protected override void Reset()
#endif
+ ///
protected override void Awake()
{
base.Awake();
@@ -1516,6 +1621,7 @@ protected override void Awake()
m_NavigationState.Reset();
}
+ ///
protected override void OnDestroy()
{
base.OnDestroy();
@@ -1523,6 +1629,7 @@ protected override void OnDestroy()
UnhookActions();
}
+ ///
protected override void OnEnable()
{
base.OnEnable();
@@ -1540,6 +1647,7 @@ protected override void OnEnable()
EnableAllActions();
}
+ ///
protected override void OnDisable()
{
ResetPointers();
@@ -2222,6 +2330,49 @@ private void FilterPointerStatesByType()
}
}
+ ///
+ ///
+ /// This method is automatically called by once per frame.
+ /// There is no need to call it manually. Unless for specific use cases.
+ ///
+ /// It processes all and pointer types,
+ /// as well as navigation input state from and .
+ /// These fields hold state based on the actions set up for the UI action map of .
+ /// The InputAction callbacks are responsible for updating their state, which means state can change multiple
+ /// times during a frame, even though it will only be processed once per frame. For example, in case there are
+ /// multiple clicks or touches in a single frame, they can allocate multiple pointers in the same frame, which
+ /// will all then be processed by frame when calls this method.
+ ///
+ /// Also, this method is responsible for purging stale pointers when a device is removed, and for filtering
+ /// pointer states
+ ///
+ ///
+ ///
+ ///
+ /// using UnityEngine;
+ /// using UnityEngine.InputSystem.UI;
+ ///
+ /// public class CustomInputModuleProcessor : MonoBehaviour
+ /// {
+ /// // Reference to the InputSystemUIInputModule, set in the Inspector
+ /// public InputSystemUIInputModule uiModule;
+ ///
+ /// void Update()
+ /// {
+ /// // Process the input module in the Update loop for a specific case
+ /// // if this needs to be called outside the EventSystem.Update() event
+ /// if (uiModule != null)
+ /// {
+ /// uiModule.Process();
+ /// }
+ /// }
+ /// }
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public override void Process()
{
if (m_NeedToPurgeStalePointers)
@@ -2380,6 +2531,9 @@ private InputActionReference UpdateReferenceForNewAsset(InputActionReference act
return InputActionReference.Create(newAction);
}
+ ///
+ /// The that contains the necessary UI actions used by the UI module.
+ ///
public InputActionAsset actionsAsset
{
get => m_ActionsAsset;