Geen omschrijving
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InputActionAssetVerifier.cs 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #if UNITY_EDITOR && ENABLE_INPUT_SYSTEM && UNITY_2023_2_OR_NEWER
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine.InputSystem.Editor;
  5. namespace UnityEngine.InputSystem.Plugins.InputForUI
  6. {
  7. // Unlike InputSystemProvider we want the verifier to register itself directly on domain reload in editor.
  8. [InitializeOnLoad]
  9. internal class InputActionAssetVerifier : ProjectWideActionsAsset.IInputActionAssetVerifier
  10. {
  11. public enum ReportPolicy
  12. {
  13. ReportAll,
  14. SuppressChildErrors
  15. }
  16. // Note: This is intentionally not a constant to avoid dead code warning in tests while this remains
  17. // as a setting type of value.
  18. public static ReportPolicy DefaultReportPolicy = ReportPolicy.SuppressChildErrors;
  19. static InputActionAssetVerifier()
  20. {
  21. // Register an InputActionAsset verifier for this plugin.
  22. ProjectWideActionsAsset.RegisterInputActionAssetVerifier(() => new InputActionAssetVerifier());
  23. InputSystemProvider.SetOnRegisterActions((asset) => { ProjectWideActionsAsset.Verify(asset); });
  24. }
  25. #region ProjectWideActionsAsset.IInputActionAssetVerifier
  26. public void Verify(InputActionAsset asset,
  27. ProjectWideActionsAsset.IReportInputActionAssetVerificationErrors reporter)
  28. {
  29. // Note that we never cache this to guarantee we have the current configuration.
  30. var config = InputSystemProvider.Configuration.GetDefaultConfiguration();
  31. Verify(asset, ref config, reporter);
  32. }
  33. #endregion
  34. private struct Context
  35. {
  36. const string errorSuffix = "The Input System's runtime UI integration relies on certain required input action definitions, some of which are missing. This means some runtime UI input may not work correctly. See <a href=\"https://docs.unity3d.com/Packages/com.unity.inputsystem@latest/index.html?subfolder=/manual/UISupport.html#required-actions-for-ui\">Input System Manual - UI Support</a> for guidance on required actions for UI integration or see <a href=\"https://docs.unity3d.com/Packages/com.unity.inputsystem@latest/index.html?subfolder=/manual/ProjectWideActions.html#the-default-actions\">how to revert to defaults</a>.";
  37. public Context(InputActionAsset asset,
  38. ProjectWideActionsAsset.IReportInputActionAssetVerificationErrors reporter,
  39. ReportPolicy policy)
  40. {
  41. this.asset = asset;
  42. this.missingPaths = new HashSet<string>();
  43. this.reporter = reporter;
  44. this.policy = policy;
  45. }
  46. private string GetAssetReference()
  47. {
  48. var path = AssetDatabase.GetAssetPath(asset);
  49. return path ?? asset.name;
  50. }
  51. private void ActionMapWarning(string actionMap, string problem)
  52. {
  53. reporter.Report($"InputActionMap with path '{actionMap}' in asset \"{GetAssetReference()}\" {problem}. {errorSuffix}");
  54. }
  55. private void ActionWarning(string actionNameOrId, string problem)
  56. {
  57. reporter.Report($"InputAction with path '{actionNameOrId}' in asset \"{GetAssetReference()}\" {problem}. {errorSuffix}");
  58. }
  59. public void Verify(string actionNameOrId, InputActionType actionType, string expectedControlType)
  60. {
  61. var action = asset.FindAction(actionNameOrId);
  62. if (action == null)
  63. {
  64. const string kCouldNotBeFound = "could not be found";
  65. // Check if the map (if any) exists
  66. var noMapOrMapExists = true;
  67. var index = actionNameOrId.IndexOf('/');
  68. if (index > 0)
  69. {
  70. var path = actionNameOrId.Substring(0, index);
  71. if (asset.FindActionMap(path) == null)
  72. {
  73. if (missingPaths == null)
  74. missingPaths = new HashSet<string>(1);
  75. if (missingPaths.Add(path))
  76. ActionMapWarning(path, kCouldNotBeFound);
  77. noMapOrMapExists = false;
  78. }
  79. }
  80. if (!noMapOrMapExists && policy == ReportPolicy.SuppressChildErrors)
  81. return;
  82. ActionWarning(actionNameOrId, kCouldNotBeFound);
  83. }
  84. else if (action.bindings.Count == 0)
  85. ActionWarning(actionNameOrId, "do not have any configured bindings");
  86. else if (action.type != actionType)
  87. ActionWarning(actionNameOrId, $"has 'type' set to '{nameof(InputActionType)}.{action.type}', but '{nameof(InputActionType)}.{actionType}' was expected");
  88. else if (!string.IsNullOrEmpty(expectedControlType) && !string.IsNullOrEmpty(action.expectedControlType) && action.expectedControlType != expectedControlType)
  89. ActionWarning(actionNameOrId, $"has 'expectedControlType' set to '{action.expectedControlType}', but '{expectedControlType}' was expected");
  90. }
  91. private readonly InputActionAsset asset;
  92. private readonly ProjectWideActionsAsset.IReportInputActionAssetVerificationErrors reporter;
  93. private HashSet<string> missingPaths; // Avoids generating multiple warnings around missing map
  94. private ReportPolicy policy;
  95. }
  96. private static void Verify(InputActionAsset asset, ref InputSystemProvider.Configuration config,
  97. ProjectWideActionsAsset.IReportInputActionAssetVerificationErrors reporter)
  98. {
  99. // Note:
  100. // PWA has initial state check true for "Point" action, DefaultActions do not, does it matter?
  101. //
  102. // Additionally note that "Submit" and "Cancel" are indirectly expected to be of Button action type.
  103. // This is not available in UI configuration, but InputActionRebindingExtensions suggests this.
  104. //
  105. // Additional "LeftClick" has initial state check set in PWA, but not "MiddleClick" and "RightClick".
  106. // Is this intentional? Are requirements different?
  107. var context = new Context(asset, reporter, DefaultReportPolicy);
  108. context.Verify(actionNameOrId: config.PointAction, actionType: InputActionType.PassThrough, expectedControlType: nameof(Vector2));
  109. context.Verify(actionNameOrId: config.MoveAction, actionType: InputActionType.PassThrough, expectedControlType: nameof(Vector2));
  110. context.Verify(actionNameOrId: config.SubmitAction, actionType: InputActionType.Button, expectedControlType: "Button");
  111. context.Verify(actionNameOrId: config.CancelAction, actionType: InputActionType.Button, expectedControlType: "Button");
  112. context.Verify(actionNameOrId: config.LeftClickAction, actionType: InputActionType.PassThrough, expectedControlType: "Button");
  113. context.Verify(actionNameOrId: config.MiddleClickAction, actionType: InputActionType.PassThrough, expectedControlType: "Button");
  114. context.Verify(actionNameOrId: config.RightClickAction, actionType: InputActionType.PassThrough, expectedControlType: "Button");
  115. context.Verify(actionNameOrId: config.ScrollWheelAction, actionType: InputActionType.PassThrough, expectedControlType: nameof(Vector2));
  116. }
  117. }
  118. }
  119. #endif // UNITY_EDITOR && ENABLE_INPUT_SYSTEM && UNITY_2023_2_OR_NEWER