diff --git a/Assets/Samples/InGameHints/InGameHintsActions.cs b/Assets/Samples/InGameHints/InGameHintsActions.cs index 43e50d0c9a..8ee2cd9fe4 100644 --- a/Assets/Samples/InGameHints/InGameHintsActions.cs +++ b/Assets/Samples/InGameHints/InGameHintsActions.cs @@ -17,9 +17,73 @@ namespace UnityEngine.InputSystem.Samples.InGameHints { + /// + /// Provides programmatic access to , , and instances defined in asset "Assets/Samples/InGameHints/InGameHintsActions.inputactions". + /// + /// + /// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. + /// + /// + /// + /// using namespace UnityEngine; + /// using UnityEngine.InputSystem; + /// + /// // Example of using an InputActionMap named "Player" from a UnityEngine.MonoBehaviour implementing callback interface. + /// public class Example : MonoBehaviour, MyActions.IPlayerActions + /// { + /// private MyActions_Actions m_Actions; // Source code representation of asset. + /// private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map. + /// + /// void Awake() + /// { + /// m_Actions = new MyActions_Actions(); // Create asset object. + /// m_Player = m_Actions.Player; // Extract action map object. + /// m_Player.AddCallbacks(this); // Register callback interface IPlayerActions. + /// } + /// + /// void OnDestroy() + /// { + /// m_Actions.Dispose(); // Destroy asset object. + /// } + /// + /// void OnEnable() + /// { + /// m_Player.Enable(); // Enable all actions within map. + /// } + /// + /// void OnDisable() + /// { + /// m_Player.Disable(); // Disable all actions within map. + /// } + /// + /// #region Interface implementation of MyActions.IPlayerActions + /// + /// // Invoked when "Move" action is either started, performed or canceled. + /// public void OnMove(InputAction.CallbackContext context) + /// { + /// Debug.Log($"OnMove: {context.ReadValue<Vector2>()}"); + /// } + /// + /// // Invoked when "Attack" action is either started, performed or canceled. + /// public void OnAttack(InputAction.CallbackContext context) + /// { + /// Debug.Log($"OnAttack: {context.ReadValue<float>()}"); + /// } + /// + /// #endregion + /// } + /// + /// public partial class @InGameHintsActions: IInputActionCollection2, IDisposable { + /// + /// Provides access to the underlying asset instance. + /// public InputActionAsset asset { get; } + + /// + /// Constructs a new instance. + /// public @InGameHintsActions() { asset = InputActionAsset.FromJson(@"{ @@ -277,57 +341,71 @@ public @InGameHintsActions() UnityEngine.Debug.Assert(!m_Gameplay.enabled, "This will cause a leak and performance issues, InGameHintsActions.Gameplay.Disable() has not been called."); } + /// + /// Destroys this asset and all associated instances. + /// public void Dispose() { UnityEngine.Object.Destroy(asset); } + /// public InputBinding? bindingMask { get => asset.bindingMask; set => asset.bindingMask = value; } + /// public ReadOnlyArray? devices { get => asset.devices; set => asset.devices = value; } + /// public ReadOnlyArray controlSchemes => asset.controlSchemes; + /// public bool Contains(InputAction action) { return asset.Contains(action); } + /// public IEnumerator GetEnumerator() { return asset.GetEnumerator(); } + /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + /// public void Enable() { asset.Enable(); } + /// public void Disable() { asset.Disable(); } + /// public IEnumerable bindings => asset.bindings; + /// public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) { return asset.FindAction(actionNameOrId, throwIfNotFound); } + /// public int FindBinding(InputBinding bindingMask, out InputAction action) { return asset.FindBinding(bindingMask, out action); @@ -341,20 +419,59 @@ public int FindBinding(InputBinding bindingMask, out InputAction action) private readonly InputAction m_Gameplay_PickUp; private readonly InputAction m_Gameplay_Drop; private readonly InputAction m_Gameplay_Throw; + /// + /// Provides access to input actions defined in input action map "Gameplay". + /// public struct GameplayActions { private @InGameHintsActions m_Wrapper; + + /// + /// Construct a new instance of the input action map wrapper class. + /// public GameplayActions(@InGameHintsActions wrapper) { m_Wrapper = wrapper; } + /// + /// Provides access to the underlying input action "Gameplay/Move". + /// public InputAction @Move => m_Wrapper.m_Gameplay_Move; + /// + /// Provides access to the underlying input action "Gameplay/Look". + /// public InputAction @Look => m_Wrapper.m_Gameplay_Look; + /// + /// Provides access to the underlying input action "Gameplay/PickUp". + /// public InputAction @PickUp => m_Wrapper.m_Gameplay_PickUp; + /// + /// Provides access to the underlying input action "Gameplay/Drop". + /// public InputAction @Drop => m_Wrapper.m_Gameplay_Drop; + /// + /// Provides access to the underlying input action "Gameplay/Throw". + /// public InputAction @Throw => m_Wrapper.m_Gameplay_Throw; + /// + /// Provides access to the underlying input action map instance. + /// public InputActionMap Get() { return m_Wrapper.m_Gameplay; } + /// public void Enable() { Get().Enable(); } + /// public void Disable() { Get().Disable(); } + /// public bool enabled => Get().enabled; + /// + /// Implicitly converts an to an instance. + /// public static implicit operator InputActionMap(GameplayActions set) { return set.Get(); } + /// + /// Adds , and callbacks provided via on all input actions contained in this map. + /// + /// Callback instance. + /// + /// If is null or have already been added this method does nothing. + /// + /// public void AddCallbacks(IGameplayActions instance) { if (instance == null || m_Wrapper.m_GameplayActionsCallbackInterfaces.Contains(instance)) return; @@ -376,6 +493,13 @@ public void AddCallbacks(IGameplayActions instance) @Throw.canceled += instance.OnThrow; } + /// + /// Removes , and callbacks provided via on all input actions contained in this map. + /// + /// + /// Calling this method when have not previously been registered has no side-effects. + /// + /// private void UnregisterCallbacks(IGameplayActions instance) { @Move.started -= instance.OnMove; @@ -395,12 +519,25 @@ private void UnregisterCallbacks(IGameplayActions instance) @Throw.canceled -= instance.OnThrow; } + /// + /// Unregisters and unregisters all input action callbacks via . + /// + /// public void RemoveCallbacks(IGameplayActions instance) { if (m_Wrapper.m_GameplayActionsCallbackInterfaces.Remove(instance)) UnregisterCallbacks(instance); } + /// + /// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via . + /// + /// + /// If is null, calling this method will only unregister all existing callbacks but not register any new callbacks. + /// + /// + /// + /// public void SetCallbacks(IGameplayActions instance) { foreach (var item in m_Wrapper.m_GameplayActionsCallbackInterfaces) @@ -409,8 +546,15 @@ public void SetCallbacks(IGameplayActions instance) AddCallbacks(instance); } } + /// + /// Provides a new instance referencing this action map. + /// public GameplayActions @Gameplay => new GameplayActions(this); private int m_GamepadSchemeIndex = -1; + /// + /// Provides access to the input control scheme. + /// + /// public InputControlScheme GamepadScheme { get @@ -420,6 +564,10 @@ public InputControlScheme GamepadScheme } } private int m_KeyboardMouseSchemeIndex = -1; + /// + /// Provides access to the input control scheme. + /// + /// public InputControlScheme KeyboardMouseScheme { get @@ -428,12 +576,47 @@ public InputControlScheme KeyboardMouseScheme return asset.controlSchemes[m_KeyboardMouseSchemeIndex]; } } + /// + /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "Gameplay" which allows adding and removing callbacks. + /// + /// + /// public interface IGameplayActions { + /// + /// Method invoked when associated input action "Move" is either , or . + /// + /// + /// + /// void OnMove(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "Look" is either , or . + /// + /// + /// + /// void OnLook(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "PickUp" is either , or . + /// + /// + /// + /// void OnPickUp(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "Drop" is either , or . + /// + /// + /// + /// void OnDrop(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "Throw" is either , or . + /// + /// + /// + /// void OnThrow(InputAction.CallbackContext context); } } diff --git a/Assets/Samples/SimpleDemo/SimpleControls.cs b/Assets/Samples/SimpleDemo/SimpleControls.cs index 54be0187b6..7499985262 100644 --- a/Assets/Samples/SimpleDemo/SimpleControls.cs +++ b/Assets/Samples/SimpleDemo/SimpleControls.cs @@ -15,9 +15,73 @@ using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; +/// +/// Provides programmatic access to , , and instances defined in asset "Assets/Samples/SimpleDemo/SimpleControls.inputactions". +/// +/// +/// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. +/// +/// +/// +/// using namespace UnityEngine; +/// using UnityEngine.InputSystem; +/// +/// // Example of using an InputActionMap named "Player" from a UnityEngine.MonoBehaviour implementing callback interface. +/// public class Example : MonoBehaviour, MyActions.IPlayerActions +/// { +/// private MyActions_Actions m_Actions; // Source code representation of asset. +/// private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map. +/// +/// void Awake() +/// { +/// m_Actions = new MyActions_Actions(); // Create asset object. +/// m_Player = m_Actions.Player; // Extract action map object. +/// m_Player.AddCallbacks(this); // Register callback interface IPlayerActions. +/// } +/// +/// void OnDestroy() +/// { +/// m_Actions.Dispose(); // Destroy asset object. +/// } +/// +/// void OnEnable() +/// { +/// m_Player.Enable(); // Enable all actions within map. +/// } +/// +/// void OnDisable() +/// { +/// m_Player.Disable(); // Disable all actions within map. +/// } +/// +/// #region Interface implementation of MyActions.IPlayerActions +/// +/// // Invoked when "Move" action is either started, performed or canceled. +/// public void OnMove(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnMove: {context.ReadValue<Vector2>()}"); +/// } +/// +/// // Invoked when "Attack" action is either started, performed or canceled. +/// public void OnAttack(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnAttack: {context.ReadValue<float>()}"); +/// } +/// +/// #endregion +/// } +/// +/// public partial class @SimpleControls: IInputActionCollection2, IDisposable { + /// + /// Provides access to the underlying asset instance. + /// public InputActionAsset asset { get; } + + /// + /// Constructs a new instance. + /// public @SimpleControls() { asset = InputActionAsset.FromJson(@"{ @@ -172,57 +236,71 @@ public @SimpleControls() UnityEngine.Debug.Assert(!m_gameplay.enabled, "This will cause a leak and performance issues, SimpleControls.gameplay.Disable() has not been called."); } + /// + /// Destroys this asset and all associated instances. + /// public void Dispose() { UnityEngine.Object.Destroy(asset); } + /// public InputBinding? bindingMask { get => asset.bindingMask; set => asset.bindingMask = value; } + /// public ReadOnlyArray? devices { get => asset.devices; set => asset.devices = value; } + /// public ReadOnlyArray controlSchemes => asset.controlSchemes; + /// public bool Contains(InputAction action) { return asset.Contains(action); } + /// public IEnumerator GetEnumerator() { return asset.GetEnumerator(); } + /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + /// public void Enable() { asset.Enable(); } + /// public void Disable() { asset.Disable(); } + /// public IEnumerable bindings => asset.bindings; + /// public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) { return asset.FindAction(actionNameOrId, throwIfNotFound); } + /// public int FindBinding(InputBinding bindingMask, out InputAction action) { return asset.FindBinding(bindingMask, out action); @@ -234,18 +312,51 @@ public int FindBinding(InputBinding bindingMask, out InputAction action) private readonly InputAction m_gameplay_fire; private readonly InputAction m_gameplay_move; private readonly InputAction m_gameplay_look; + /// + /// Provides access to input actions defined in input action map "gameplay". + /// public struct GameplayActions { private @SimpleControls m_Wrapper; + + /// + /// Construct a new instance of the input action map wrapper class. + /// public GameplayActions(@SimpleControls wrapper) { m_Wrapper = wrapper; } + /// + /// Provides access to the underlying input action "gameplay/fire". + /// public InputAction @fire => m_Wrapper.m_gameplay_fire; + /// + /// Provides access to the underlying input action "gameplay/move". + /// public InputAction @move => m_Wrapper.m_gameplay_move; + /// + /// Provides access to the underlying input action "gameplay/look". + /// public InputAction @look => m_Wrapper.m_gameplay_look; + /// + /// Provides access to the underlying input action map instance. + /// public InputActionMap Get() { return m_Wrapper.m_gameplay; } + /// public void Enable() { Get().Enable(); } + /// public void Disable() { Get().Disable(); } + /// public bool enabled => Get().enabled; + /// + /// Implicitly converts an to an instance. + /// public static implicit operator InputActionMap(GameplayActions set) { return set.Get(); } + /// + /// Adds , and callbacks provided via on all input actions contained in this map. + /// + /// Callback instance. + /// + /// If is null or have already been added this method does nothing. + /// + /// public void AddCallbacks(IGameplayActions instance) { if (instance == null || m_Wrapper.m_GameplayActionsCallbackInterfaces.Contains(instance)) return; @@ -261,6 +372,13 @@ public void AddCallbacks(IGameplayActions instance) @look.canceled += instance.OnLook; } + /// + /// Removes , and callbacks provided via on all input actions contained in this map. + /// + /// + /// Calling this method when have not previously been registered has no side-effects. + /// + /// private void UnregisterCallbacks(IGameplayActions instance) { @fire.started -= instance.OnFire; @@ -274,12 +392,25 @@ private void UnregisterCallbacks(IGameplayActions instance) @look.canceled -= instance.OnLook; } + /// + /// Unregisters and unregisters all input action callbacks via . + /// + /// public void RemoveCallbacks(IGameplayActions instance) { if (m_Wrapper.m_GameplayActionsCallbackInterfaces.Remove(instance)) UnregisterCallbacks(instance); } + /// + /// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via . + /// + /// + /// If is null, calling this method will only unregister all existing callbacks but not register any new callbacks. + /// + /// + /// + /// public void SetCallbacks(IGameplayActions instance) { foreach (var item in m_Wrapper.m_GameplayActionsCallbackInterfaces) @@ -288,11 +419,37 @@ public void SetCallbacks(IGameplayActions instance) AddCallbacks(instance); } } + /// + /// Provides a new instance referencing this action map. + /// public GameplayActions @gameplay => new GameplayActions(this); + /// + /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "gameplay" which allows adding and removing callbacks. + /// + /// + /// public interface IGameplayActions { + /// + /// Method invoked when associated input action "fire" is either , or . + /// + /// + /// + /// void OnFire(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "move" is either , or . + /// + /// + /// + /// void OnMove(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "look" is either , or . + /// + /// + /// + /// void OnLook(InputAction.CallbackContext context); } } diff --git a/Assets/Tests/InputSystem/InputActionCodeGeneratorActions.cs b/Assets/Tests/InputSystem/InputActionCodeGeneratorActions.cs index 3500da2666..e0e7b91261 100644 --- a/Assets/Tests/InputSystem/InputActionCodeGeneratorActions.cs +++ b/Assets/Tests/InputSystem/InputActionCodeGeneratorActions.cs @@ -15,9 +15,73 @@ using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; +/// +/// Provides programmatic access to , , and instances defined in asset "Assets/Tests/InputSystem/InputActionCodeGeneratorActions.inputactions". +/// +/// +/// This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified. +/// +/// +/// +/// using namespace UnityEngine; +/// using UnityEngine.InputSystem; +/// +/// // Example of using an InputActionMap named "Player" from a UnityEngine.MonoBehaviour implementing callback interface. +/// public class Example : MonoBehaviour, MyActions.IPlayerActions +/// { +/// private MyActions_Actions m_Actions; // Source code representation of asset. +/// private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map. +/// +/// void Awake() +/// { +/// m_Actions = new MyActions_Actions(); // Create asset object. +/// m_Player = m_Actions.Player; // Extract action map object. +/// m_Player.AddCallbacks(this); // Register callback interface IPlayerActions. +/// } +/// +/// void OnDestroy() +/// { +/// m_Actions.Dispose(); // Destroy asset object. +/// } +/// +/// void OnEnable() +/// { +/// m_Player.Enable(); // Enable all actions within map. +/// } +/// +/// void OnDisable() +/// { +/// m_Player.Disable(); // Disable all actions within map. +/// } +/// +/// #region Interface implementation of MyActions.IPlayerActions +/// +/// // Invoked when "Move" action is either started, performed or canceled. +/// public void OnMove(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnMove: {context.ReadValue<Vector2>()}"); +/// } +/// +/// // Invoked when "Attack" action is either started, performed or canceled. +/// public void OnAttack(InputAction.CallbackContext context) +/// { +/// Debug.Log($"OnAttack: {context.ReadValue<float>()}"); +/// } +/// +/// #endregion +/// } +/// +/// public partial class @InputActionCodeGeneratorActions: IInputActionCollection2, IDisposable { + /// + /// Provides access to the underlying asset instance. + /// public InputActionAsset asset { get; } + + /// + /// Constructs a new instance. + /// public @InputActionCodeGeneratorActions() { asset = InputActionAsset.FromJson(@"{ @@ -85,57 +149,71 @@ public @InputActionCodeGeneratorActions() UnityEngine.Debug.Assert(!m_gameplay.enabled, "This will cause a leak and performance issues, InputActionCodeGeneratorActions.gameplay.Disable() has not been called."); } + /// + /// Destroys this asset and all associated instances. + /// public void Dispose() { UnityEngine.Object.Destroy(asset); } + /// public InputBinding? bindingMask { get => asset.bindingMask; set => asset.bindingMask = value; } + /// public ReadOnlyArray? devices { get => asset.devices; set => asset.devices = value; } + /// public ReadOnlyArray controlSchemes => asset.controlSchemes; + /// public bool Contains(InputAction action) { return asset.Contains(action); } + /// public IEnumerator GetEnumerator() { return asset.GetEnumerator(); } + /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + /// public void Enable() { asset.Enable(); } + /// public void Disable() { asset.Disable(); } + /// public IEnumerable bindings => asset.bindings; + /// public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) { return asset.FindAction(actionNameOrId, throwIfNotFound); } + /// public int FindBinding(InputBinding bindingMask, out InputAction action) { return asset.FindBinding(bindingMask, out action); @@ -146,17 +224,47 @@ public int FindBinding(InputBinding bindingMask, out InputAction action) private List m_GameplayActionsCallbackInterfaces = new List(); private readonly InputAction m_gameplay_action1; private readonly InputAction m_gameplay_action2; + /// + /// Provides access to input actions defined in input action map "gameplay". + /// public struct GameplayActions { private @InputActionCodeGeneratorActions m_Wrapper; + + /// + /// Construct a new instance of the input action map wrapper class. + /// public GameplayActions(@InputActionCodeGeneratorActions wrapper) { m_Wrapper = wrapper; } + /// + /// Provides access to the underlying input action "gameplay/action1". + /// public InputAction @action1 => m_Wrapper.m_gameplay_action1; + /// + /// Provides access to the underlying input action "gameplay/action2". + /// public InputAction @action2 => m_Wrapper.m_gameplay_action2; + /// + /// Provides access to the underlying input action map instance. + /// public InputActionMap Get() { return m_Wrapper.m_gameplay; } + /// public void Enable() { Get().Enable(); } + /// public void Disable() { Get().Disable(); } + /// public bool enabled => Get().enabled; + /// + /// Implicitly converts an to an instance. + /// public static implicit operator InputActionMap(GameplayActions set) { return set.Get(); } + /// + /// Adds , and callbacks provided via on all input actions contained in this map. + /// + /// Callback instance. + /// + /// If is null or have already been added this method does nothing. + /// + /// public void AddCallbacks(IGameplayActions instance) { if (instance == null || m_Wrapper.m_GameplayActionsCallbackInterfaces.Contains(instance)) return; @@ -169,6 +277,13 @@ public void AddCallbacks(IGameplayActions instance) @action2.canceled += instance.OnAction2; } + /// + /// Removes , and callbacks provided via on all input actions contained in this map. + /// + /// + /// Calling this method when have not previously been registered has no side-effects. + /// + /// private void UnregisterCallbacks(IGameplayActions instance) { @action1.started -= instance.OnAction1; @@ -179,12 +294,25 @@ private void UnregisterCallbacks(IGameplayActions instance) @action2.canceled -= instance.OnAction2; } + /// + /// Unregisters and unregisters all input action callbacks via . + /// + /// public void RemoveCallbacks(IGameplayActions instance) { if (m_Wrapper.m_GameplayActionsCallbackInterfaces.Remove(instance)) UnregisterCallbacks(instance); } + /// + /// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via . + /// + /// + /// If is null, calling this method will only unregister all existing callbacks but not register any new callbacks. + /// + /// + /// + /// public void SetCallbacks(IGameplayActions instance) { foreach (var item in m_Wrapper.m_GameplayActionsCallbackInterfaces) @@ -193,10 +321,30 @@ public void SetCallbacks(IGameplayActions instance) AddCallbacks(instance); } } + /// + /// Provides a new instance referencing this action map. + /// public GameplayActions @gameplay => new GameplayActions(this); + /// + /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "gameplay" which allows adding and removing callbacks. + /// + /// + /// public interface IGameplayActions { + /// + /// Method invoked when associated input action "action1" is either , or . + /// + /// + /// + /// void OnAction1(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "action2" is either , or . + /// + /// + /// + /// void OnAction2(InputAction.CallbackContext context); } } diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index caf4b4ec58..fb051ab335 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -13,15 +13,16 @@ however, it has to be formatted properly to pass verification tests. ### Fixed - Fixed an issue causing the Action context menu to not show on right click when right clicking an action in the Input Action Editor [ISXB-1134](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1134). - Reverted changes from 0ddd534d8 (ISXB-746) which introduced a regression [ISXB-1127](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1127). -- Fixed `ArgumentNullException: Value cannot be null.` during the migration of Project-wide Input Actions from `InputManager.asset` to `InputSystem_Actions.inputactions` asset which lead do the lost of the configuration [ISXB-1105](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1105) -- Fixed pointerId staying the same when simultaneously releasing and then pressing in the same frame on mobile using touch. [ISXB-1006](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-845) -- Fixed ISubmitHandler.OnSubmit event processing when operating in Manual Update mode (ISXB-1141) -- Fixed Rename mode is not entered and name is autocompleted to default when creating a new Action Map on 2022.3. [ISXB-1151](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1151) -- Fixed unexpected control scheme switch when using `OnScreenControl` and pointer based schemes which registed "Cancel" event on every frame.[ISXB-656](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-656) -- Fixed an issue with The "Add Control Scheme..." popup window so that it now persists until any changes are explicitly Saved or Cancelled [case ISXB-1131](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1131) +- Fixed `ArgumentNullException: Value cannot be null.` during the migration of Project-wide Input Actions from `InputManager.asset` to `InputSystem_Actions.inputactions` asset which lead do the lost of the configuration [ISXB-1105](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1105). +- Fixed pointerId staying the same when simultaneously releasing and then pressing in the same frame on mobile using touch. [ISXB-1006](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-845). +- Fixed ISubmitHandler.OnSubmit event processing when operating in Manual Update mode (ISXB-1141). +- Fixed Rename mode is not entered and name is autocompleted to default when creating a new Action Map on 2022.3. [ISXB-1151](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1151). +- Fixed unexpected control scheme switch when using `OnScreenControl` and pointer based schemes which registed "Cancel" event on every frame.[ISXB-656](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-656). +- Fixed an issue with The "Add Control Scheme..." popup window so that it now persists until any changes are explicitly Saved or Cancelled [case ISXB-1131](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1131). +- Fixed missing documentation for source generated Input Action Assets. This is now generated as part of the source code generation step when "Generate C# Class" is checked in the importer inspector settings. ### Changed -- Added back the InputManager to InputSystem project-wide asset migration code with performance improvement (ISX-2086) +- Added back the InputManager to InputSystem project-wide asset migration code with performance improvement (ISX-2086). - Changed `OnScreenControl` to automaticaly switch, in Single Player with autoswitch enabled, to the target device control scheme when the first component is enabled to prevent bad interactions when it start. ## [1.11.2] - 2024-10-16 diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionCodeGenerator.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionCodeGenerator.cs index dab46023da..a7bdf3f8a3 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionCodeGenerator.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionCodeGenerator.cs @@ -1,5 +1,6 @@ #if UNITY_EDITOR using System; +using System.Collections; using System.IO; using System.Linq; using System.Text; @@ -41,6 +42,54 @@ public static class InputActionCodeGenerator { private const int kSpacesPerIndentLevel = 4; + private const string kClassExample = @"using namespace UnityEngine; +using UnityEngine.InputSystem; + +// Example of using an InputActionMap named ""Player"" from a UnityEngine.MonoBehaviour implementing callback interface. +public class Example : MonoBehaviour, MyActions.IPlayerActions +{ + private MyActions_Actions m_Actions; // Source code representation of asset. + private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map. + + void Awake() + { + m_Actions = new MyActions_Actions(); // Create asset object. + m_Player = m_Actions.Player; // Extract action map object. + m_Player.AddCallbacks(this); // Register callback interface IPlayerActions. + } + + void OnDestroy() + { + m_Actions.Dispose(); // Destroy asset object. + } + + void OnEnable() + { + m_Player.Enable(); // Enable all actions within map. + } + + void OnDisable() + { + m_Player.Disable(); // Disable all actions within map. + } + + #region Interface implementation of MyActions.IPlayerActions + + // Invoked when ""Move"" action is either started, performed or canceled. + public void OnMove(InputAction.CallbackContext context) + { + Debug.Log($""OnMove: {context.ReadValue()}""); + } + + // Invoked when ""Attack"" action is either started, performed or canceled. + public void OnAttack(InputAction.CallbackContext context) + { + Debug.Log($""OnAttack: {context.ReadValue()}""); + } + + #endregion +}"; + public struct Options { public string className { get; set; } @@ -94,12 +143,22 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options } // Begin class. + writer.DocSummary($"Provides programmatic access to , " + + ", and " + + " instances defined " + + $"in asset \"{options.sourceAssetPath}\"."); + writer.DocRemarks("This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified."); + writer.DocExample(kClassExample); + writer.WriteLine($"public partial class @{options.className}: IInputActionCollection2, IDisposable"); writer.BeginBlock(); + writer.DocSummary("Provides access to the underlying asset instance."); writer.WriteLine($"public InputActionAsset asset {{ get; }}"); + writer.WriteLine(); // Default constructor. + writer.DocSummary("Constructs a new instance."); writer.WriteLine($"public @{options.className}()"); writer.BeginBlock(); writer.WriteLine($"asset = InputActionAsset.FromJson(@\"{asset.ToJson().Replace("\"", "\"\"")}\");"); @@ -131,12 +190,15 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.EndBlock(); writer.WriteLine(); + writer.DocSummary("Destroys this asset and all associated instances."); writer.WriteLine("public void Dispose()"); writer.BeginBlock(); writer.WriteLine("UnityEngine.Object.Destroy(asset);"); writer.EndBlock(); writer.WriteLine(); + var classNamePrefix = typeof(InputActionAsset).Namespace + "." + nameof(InputActionAsset) + "."; + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.bindingMask)); writer.WriteLine("public InputBinding? bindingMask"); writer.BeginBlock(); writer.WriteLine("get => asset.bindingMask;"); @@ -144,6 +206,7 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.devices)); writer.WriteLine("public ReadOnlyArray? devices"); writer.BeginBlock(); writer.WriteLine("get => asset.devices;"); @@ -151,54 +214,64 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.controlSchemes)); writer.WriteLine("public ReadOnlyArray controlSchemes => asset.controlSchemes;"); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.Contains) + "(InputAction)"); writer.WriteLine("public bool Contains(InputAction action)"); writer.BeginBlock(); writer.WriteLine("return asset.Contains(action);"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.GetEnumerator) + "()"); writer.WriteLine("public IEnumerator GetEnumerator()"); writer.BeginBlock(); writer.WriteLine("return asset.GetEnumerator();"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(nameof(IEnumerable) + "." + nameof(IEnumerable.GetEnumerator) + "()"); writer.WriteLine("IEnumerator IEnumerable.GetEnumerator()"); writer.BeginBlock(); writer.WriteLine("return GetEnumerator();"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.Enable) + "()"); writer.WriteLine("public void Enable()"); writer.BeginBlock(); writer.WriteLine("asset.Enable();"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.Disable) + "()"); writer.WriteLine("public void Disable()"); writer.BeginBlock(); writer.WriteLine("asset.Disable();"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.bindings)); writer.WriteLine("public IEnumerable bindings => asset.bindings;"); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.FindAction) + "(string, bool)"); writer.WriteLine("public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false)"); writer.BeginBlock(); writer.WriteLine("return asset.FindAction(actionNameOrId, throwIfNotFound);"); writer.EndBlock(); writer.WriteLine(); + writer.DocInherit(classNamePrefix + nameof(InputActionAsset.FindBinding) + "(InputBinding, out InputAction)"); writer.WriteLine("public int FindBinding(InputBinding bindingMask, out InputAction action)"); writer.BeginBlock(); writer.WriteLine("return asset.FindBinding(bindingMask, out action);"); writer.EndBlock(); // Action map accessors. + var inputActionMapClassPrefix = typeof(InputActionMap).Namespace + "." + nameof(InputActionMap) + "."; foreach (var map in maps) { writer.WriteLine(); @@ -219,34 +292,48 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options } // Struct wrapping access to action set. + writer.DocSummary($"Provides access to input actions defined in input action map \"{map.name}\"."); writer.WriteLine($"public struct {mapTypeName}"); writer.BeginBlock(); - // Constructor. writer.WriteLine($"private @{options.className} m_Wrapper;"); + writer.WriteLine(); + + // Constructor. + writer.DocSummary("Construct a new instance of the input action map wrapper class."); writer.WriteLine($"public {mapTypeName}(@{options.className} wrapper) {{ m_Wrapper = wrapper; }}"); // Getter for each action. foreach (var action in map.actions) { var actionName = CSharpCodeHelpers.MakeIdentifier(action.name); + writer.DocSummary($"Provides access to the underlying input action \"{mapName}/{actionName}\"."); writer.WriteLine( $"public InputAction @{actionName} => m_Wrapper.m_{mapName}_{actionName};"); } // Action map getter. + writer.DocSummary("Provides access to the underlying input action map instance."); writer.WriteLine($"public InputActionMap Get() {{ return m_Wrapper.m_{mapName}; }}"); // Enable/disable methods. + writer.DocInherit(inputActionMapClassPrefix + nameof(InputActionMap.Enable) + "()"); writer.WriteLine("public void Enable() { Get().Enable(); }"); + writer.DocInherit(inputActionMapClassPrefix + nameof(InputActionMap.Disable) + "()"); writer.WriteLine("public void Disable() { Get().Disable(); }"); + writer.DocInherit(inputActionMapClassPrefix + nameof(InputActionMap.enabled)); writer.WriteLine("public bool enabled => Get().enabled;"); // Implicit conversion operator. + writer.DocSummary($"Implicitly converts an to an instance."); writer.WriteLine( $"public static implicit operator InputActionMap({mapTypeName} set) {{ return set.Get(); }}"); // AddCallbacks method. + writer.DocSummary("Adds , and callbacks provided via on all input actions contained in this map."); + writer.DocParam("instance", "Callback instance."); + writer.DocRemarks("If is null or have already been added this method does nothing."); + writer.DocSeeAlso(mapTypeName); writer.WriteLine($"public void AddCallbacks(I{mapTypeName} instance)"); writer.BeginBlock(); @@ -268,6 +355,9 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.WriteLine(); // UnregisterCallbacks method. + writer.DocSummary("Removes , and callbacks provided via on all input actions contained in this map."); + writer.DocRemarks("Calling this method when have not previously been registered has no side-effects."); + writer.DocSeeAlso(mapTypeName); writer.WriteLine($"private void UnregisterCallbacks(I{mapTypeName} instance)"); writer.BeginBlock(); foreach (var action in map.actions) @@ -283,6 +373,8 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.WriteLine(); // RemoveCallbacks method. + writer.DocSummary($"Unregisters and unregisters all input action callbacks via ."); + writer.DocSeeAlso($"{mapTypeName}.UnregisterCallbacks(I{mapTypeName})"); writer.WriteLine($"public void RemoveCallbacks(I{mapTypeName} instance)"); writer.BeginBlock(); writer.WriteLine($"if (m_Wrapper.m_{mapTypeName}CallbackInterfaces.Remove(instance))"); @@ -291,9 +383,13 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.WriteLine(); // SetCallbacks method. + writer.DocSummary($"Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via ."); + writer.DocRemarks($"If is null, calling this method will only unregister all existing callbacks but not register any new callbacks."); + writer.DocSeeAlso($"{mapTypeName}.AddCallbacks(I{mapTypeName})"); + writer.DocSeeAlso($"{mapTypeName}.RemoveCallbacks(I{mapTypeName})"); + writer.DocSeeAlso($"{mapTypeName}.UnregisterCallbacks(I{mapTypeName})"); writer.WriteLine($"public void SetCallbacks(I{mapTypeName} instance)"); writer.BeginBlock(); - ////REVIEW: this would benefit from having a single callback on InputActions rather than three different endpoints writer.WriteLine($"foreach (var item in m_Wrapper.m_{mapTypeName}CallbackInterfaces)"); @@ -306,6 +402,7 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options writer.EndBlock(); // Getter for instance of struct. + writer.DocSummary($"Provides a new instance referencing this action map."); writer.WriteLine($"public {mapTypeName} @{mapName} => new {mapTypeName}(this);"); } @@ -315,6 +412,8 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options var identifier = CSharpCodeHelpers.MakeIdentifier(scheme.name); writer.WriteLine($"private int m_{identifier}SchemeIndex = -1;"); + writer.DocSummary("Provides access to the input control scheme."); + writer.DocSeeAlso(typeof(InputControlScheme).Namespace + "." + nameof(InputControlScheme)); writer.WriteLine($"public InputControlScheme {identifier}Scheme"); writer.BeginBlock(); writer.WriteLine("get"); @@ -326,15 +425,23 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options } // Generate interfaces. + var inputActionClassReference = typeof(InputAction).Namespace + "." + nameof(InputAction) + "."; foreach (var map in maps) { var typeName = CSharpCodeHelpers.MakeTypeName(map.name); + writer.DocSummary($"Interface to implement callback methods for all input action callbacks associated with input actions defined by \"{map.name}\" which allows adding and removing callbacks."); + writer.DocSeeAlso($"{typeName}Actions.AddCallbacks(I{typeName}Actions)"); + writer.DocSeeAlso($"{typeName}Actions.RemoveCallbacks(I{typeName}Actions)"); writer.WriteLine($"public interface I{typeName}Actions"); writer.BeginBlock(); foreach (var action in map.actions) { var methodName = CSharpCodeHelpers.MakeTypeName(action.name); + writer.DocSummary($"Method invoked when associated input action \"{action.name}\" is either , or ."); + writer.DocSeeAlso(string.Concat(inputActionClassReference, "started")); + writer.DocSeeAlso(string.Concat(inputActionClassReference, "performed")); + writer.DocSeeAlso(string.Concat(inputActionClassReference, "canceled")); writer.WriteLine($"void On{methodName}(InputAction.CallbackContext context);"); } @@ -399,6 +506,68 @@ public void WriteIndent() buffer.Append(' '); } } + + public void DocSummary(string text) + { + DocElement("summary", text); + } + + public void DocParam(string paramName, string text) + { + WriteLine($"/// {text}"); + } + + public void DocRemarks(string text) + { + DocElement("remarks", text); + } + + public void DocInherit(string cref) + { + DocReference("inheritdoc", cref); + } + + public void DocSeeAlso(string cref) + { + DocReference("seealso", cref: cref); + } + + public void DocExample(string code) + { + DocComment(""); + DocComment(""); + + foreach (var line in code.Split('\n')) + DocComment(line.Replace("<", "<").Replace(">", ">")); + + DocComment(""); + DocComment(""); + } + + private void DocComment(string text) + { + if (string.IsNullOrEmpty(text)) + WriteLine("///"); + else + WriteLine(string.Concat("/// ", text)); + } + + private void DocElement(string tag, string text) + { + DocComment($"<{tag}>"); + DocComment(text); + DocComment($""); + } + + private void DocReference(string tag, string cref) + { + DocInlineElement(tag, "cref", cref); + } + + private void DocInlineElement(string tag, string property, string value) + { + DocComment($"<{tag} {property}=\"{value}\" />"); + } } // Updates the given file with wrapper code generated for the given action sets.