A game about forced loneliness, made by TACStudios
at master 242 lines 11 kB view raw
1#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS 2 3using System; 4using System.Collections.Generic; 5using System.IO; 6using System.Linq; 7using UnityEditor; 8using UnityEngine.InputSystem.Utilities; 9 10namespace UnityEngine.InputSystem.Editor 11{ 12 internal static class ProjectWideActionsAsset 13 { 14 private const string kDefaultAssetName = "InputSystem_Actions"; 15 private const string kDefaultAssetPath = "Assets/" + kDefaultAssetName + ".inputactions"; 16 private const string kDefaultTemplateAssetPath = "Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsTemplate.json"; 17 18 internal static class ProjectSettingsProjectWideActionsAssetConverter 19 { 20 class ProjectSettingsPostprocessor : AssetPostprocessor 21 { 22#if UNITY_2021_2_OR_NEWER 23 private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload) 24#else 25 private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) 26#endif 27 { 28 if (!Application.isPlaying) 29 { 30 // If the Library folder is deleted, InputSystem will fail to retrieve the assigned Project-wide Asset because this look-up occurs 31 // during initialization while the Library is being rebuilt. So, afterwards perform another check and assign PWA asset if needed. 32 var pwaAsset = ProjectWideActionsBuildProvider.actionsToIncludeInPlayerBuild; 33 if (InputSystem.actions == null && pwaAsset != null) 34 InputSystem.actions = pwaAsset; 35 } 36 } 37 } 38 } 39 40 // Returns the default asset path for where to create project-wide actions asset. 41 internal static string defaultAssetPath => kDefaultAssetPath; 42 43 // Returns the default template JSON content. 44 internal static string GetDefaultAssetJson() 45 { 46 return File.ReadAllText(EditorHelpers.GetPhysicalPath(kDefaultTemplateAssetPath)); 47 } 48 49 // Creates an asset at the given path containing the default template JSON. 50 internal static InputActionAsset CreateDefaultAssetAtPath(string assetPath = kDefaultAssetPath) 51 { 52 return CreateAssetAtPathFromJson(assetPath, File.ReadAllText(EditorHelpers.GetPhysicalPath(kDefaultTemplateAssetPath))); 53 } 54 55 // These may be moved out to internal types if decided to extend validation at a later point. 56 57 /// <summary> 58 /// Interface for reporting asset verification errors. 59 /// </summary> 60 internal interface IReportInputActionAssetVerificationErrors 61 { 62 /// <summary> 63 /// Reports a failure to comply to requirements with a message meaningful to the user. 64 /// </summary> 65 /// <param name="message">User-friendly error message.</param> 66 void Report(string message); 67 } 68 69 /// <summary> 70 /// Interface for asset verification. 71 /// </summary> 72 internal interface IInputActionAssetVerifier 73 { 74 /// <summary> 75 /// Verifies the given asset. 76 /// </summary> 77 /// <param name="asset">The asset to be verified</param> 78 /// <param name="reporter">The reporter to be used to report failure to meet requirements.</param> 79 public void Verify(InputActionAsset asset, IReportInputActionAssetVerificationErrors reporter); 80 } 81 82 /// <summary> 83 /// Verifier managing verification and reporting of asset compliance with external requirements. 84 /// </summary> 85 class Verifier : IReportInputActionAssetVerificationErrors 86 { 87 private readonly IReportInputActionAssetVerificationErrors m_Reporter; 88 89 // Default verification error reporter which generates feedback as debug warnings. 90 private class DefaultInputActionAssetVerificationReporter : IReportInputActionAssetVerificationErrors 91 { 92 public void Report(string message) 93 { 94 Debug.LogWarning(message); 95 } 96 } 97 98 /// <summary> 99 /// Constructs a an instance associated with the given reporter. 100 /// </summary> 101 /// <param name="reporter">The associated reporter instance. If null, a default reporter will be constructed.</param> 102 public Verifier(IReportInputActionAssetVerificationErrors reporter = null) 103 { 104 m_Reporter = reporter ?? new DefaultInputActionAssetVerificationReporter(); 105 errors = 0; 106 } 107 108 #region IReportInputActionAssetVerificationErrors interface 109 110 /// <inheritdoc cref="IReportInputActionAssetVerificationErrors"/> 111 public void Report(string message) 112 { 113 ++errors; 114 115 try 116 { 117 m_Reporter.Report(message); 118 } 119 catch (Exception e) 120 { 121 // Only log unexpected but non-fatal exception 122 Debug.LogException(e); 123 } 124 } 125 126 #endregion 127 128 /// <summary> 129 /// Returns the total number of errors seen in verification (accumulative). 130 /// </summary> 131 public int errors { get; private set; } 132 133 /// <summary> 134 /// Returns <c>true</c> if the number of reported errors in verification is zero, else <c>false</c>. 135 /// </summary> 136 public bool isValid => errors == 0; 137 138 private static List<Func<IInputActionAssetVerifier>> s_VerifierFactories; 139 140 /// <summary> 141 /// Registers a factory instance. 142 /// </summary> 143 /// <param name="factory">The factory instance.</param> 144 /// <returns>true if successfully added, <c>false</c> if the factory have already been registered.</returns> 145 public static bool RegisterFactory(Func<IInputActionAssetVerifier> factory) 146 { 147 if (s_VerifierFactories == null) 148 s_VerifierFactories = new List<Func<IInputActionAssetVerifier>>(1); 149 if (s_VerifierFactories.Contains(factory)) 150 return false; 151 s_VerifierFactories.Add(factory); 152 return true; 153 } 154 155 /// <summary> 156 /// Unregisters a factory instance that has previously been registered. 157 /// </summary> 158 /// <param name="factory">The factory instance to be removed.</param> 159 /// <returns>true if successfully unregistered, <c>false</c> if the given factory instance could not be found.</returns> 160 public static bool UnregisterFactory(Func<IInputActionAssetVerifier> factory) 161 { 162 return s_VerifierFactories.Remove(factory); 163 } 164 165 /// <summary> 166 /// Verifies the given project-wide input action asset using all registered verifiers. 167 /// </summary> 168 /// <param name="asset">The asset to be verified.</param> 169 /// <returns><c>true</c> if no verification errors occurred, else <c>false</c>.</returns> 170 /// <remarks> 171 /// Throws <c>System.ArgumentNullException</c> if <c>asset</c> is <c>null</c>. 172 /// 173 /// If any registered factory and/or verifier instance throws an exception this will be evaluated 174 /// as a verification error since the execution of the verifier could not continue. However, any 175 /// exceptions thrown will be caught and logged but not stop execution of the calling thread. 176 /// </remarks> 177 bool Verify(InputActionAsset asset) 178 { 179 if (asset == null) 180 throw new ArgumentNullException(nameof(asset)); 181 182 if (s_VerifierFactories == null || s_VerifierFactories.Count == 0) 183 return true; 184 185 var instance = new Verifier(m_Reporter); 186 foreach (var factory in s_VerifierFactories) 187 { 188 try 189 { 190 factory.Invoke().Verify(asset, instance); 191 } 192 catch (Exception e) 193 { 194 // Only log unexpected but non-fatal exception and count to fail verification 195 ++errors; 196 Debug.LogException(e); 197 } 198 } 199 200 return errors == 0; 201 } 202 203 /// <summary> 204 /// Verifies the given project-wide input action asset using all registered verifiers. 205 /// </summary> 206 /// <param name="asset">The asset to be verified.</param> 207 /// <param name="reporter">The reporter to be used. If this argument is <c>null</c> the default reporter will be used.</param> 208 /// <returns><c>true</c> if no verification errors occurred, else <c>false</c>.</returns> 209 /// <remarks>Throws <c>System.ArgumentNullException</c> if <c>asset</c> is <c>null</c>.</remarks> 210 public static bool Verify(InputActionAsset asset, IReportInputActionAssetVerificationErrors reporter = null) 211 { 212 return (s_VerifierFactories == null || s_VerifierFactories.Count == 0) || new Verifier(reporter).Verify(asset); 213 } 214 } 215 216 internal static bool Verify(InputActionAsset asset, IReportInputActionAssetVerificationErrors reporter = null) 217 { 218 return Verifier.Verify(asset, reporter); 219 } 220 221 internal static bool RegisterInputActionAssetVerifier(Func<IInputActionAssetVerifier> factory) 222 { 223 return Verifier.RegisterFactory(factory); 224 } 225 226 internal static bool UnregisterInputActionAssetVerifier(Func<IInputActionAssetVerifier> factory) 227 { 228 return Verifier.UnregisterFactory(factory); 229 } 230 231 // Creates an asset at the given path containing the given JSON content. 232 private static InputActionAsset CreateAssetAtPathFromJson(string assetPath, string json) 233 { 234 // Note that the extra work here is to override the JSON name from the source asset 235 var inputActionAsset = InputActionAsset.FromJson(json); 236 inputActionAsset.name = InputActionImporter.NameFromAssetPath(assetPath); 237 InputActionAssetManager.SaveAsset(assetPath, inputActionAsset.ToJson()); 238 return AssetDatabase.LoadAssetAtPath<InputActionAsset>(assetPath); 239 } 240 } 241} 242#endif // UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS