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