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;