PluginProcessor.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #if UNITY_2018_1_OR_NEWER || (UNITY_2017_4_OR_NEWER && !UNITY_2017_4_0 && !UNITY_2017_4_1 && !UNITY_2017_4_2 && !UNITY_2017_4_3 && !UNITY_2017_4_4 && !UNITY_2017_4_5 && !UNITY_2017_4_6 && !UNITY_2017_4_7 && !UNITY_2017_4_8 && !UNITY_2017_4_9 && !UNITY_2017_4_10 && !UNITY_2017_4_11 && !UNITY_2017_4_12 && !UNITY_2017_4_13 && !UNITY_2017_4_14 && !UNITY_2017_4_15 && !UNITY_2017_4_15)
  2. // Unity added Android ARM64 support in 2018.1, and backported to 2017.4.16
  3. #define AVPROVIDEO_UNITY_ANDROID_ARM64_SUPPORT
  4. #endif
  5. #if !UNITY_2019_3_OR_NEWER || UNITY_2021_2_OR_NEWER || (UNITY_2020_3_OR_NEWER && !UNITY_2020_3_0 && !UNITY_2020_3_1 && !UNITY_2020_3_2 && !UNITY_2020_3_3 && !UNITY_2020_3_4 && !UNITY_2020_3_5 && !UNITY_2020_3_6 && !UNITY_2020_3_7 && !UNITY_2020_3_8 && !UNITY_2020_3_9 && !UNITY_2020_3_10 && !UNITY_2020_3_11 && !UNITY_2020_3_12 && !UNITY_2020_3_13 && !UNITY_2020_3_14 && !UNITY_2020_3_15 && !UNITY_2020_3_16) || (UNITY_2019_4_OR_NEWER && !UNITY_2019_4_0 && !UNITY_2019_4_1 && !UNITY_2019_4_2 && !UNITY_2019_4_3 && !UNITY_2019_4_4 && !UNITY_2019_4_5 && !UNITY_2019_4_6 && !UNITY_2019_4_7 && !UNITY_2019_4_8 && !UNITY_2019_4_9 && !UNITY_2019_4_10 && !UNITY_2019_4_11 && !UNITY_2019_4_12 && !UNITY_2019_4_13 && !UNITY_2019_4_14 && !UNITY_2019_4_15 && !UNITY_2019_4_16 && !UNITY_2019_4_17 && !UNITY_2019_4_18 && !UNITY_2019_4_19 && !UNITY_2019_4_20 && !UNITY_2019_4_21 && !UNITY_2019_4_22 && !UNITY_2019_4_23 && !UNITY_2019_4_24 && !UNITY_2019_4_25 && !UNITY_2019_4_26 && !UNITY_2019_4_27 && !UNITY_2019_4_28 && !UNITY_2019_4_29 && !UNITY_2019_4_30)
  6. // Unity dropped Android x86 support in 2019, but then added it back in 2021.2.0 and backported to 2020.3.17 and 2019.4.31
  7. #define AVPROVIDEO_UNITY_ANDROID_X86_SUPPORT
  8. #endif
  9. #if UNITY_2021_2_OR_NEWER || (UNITY_2020_3_OR_NEWER && !UNITY_2020_3_0 && !UNITY_2020_3_1 && !UNITY_2020_3_2 && !UNITY_2020_3_3 && !UNITY_2020_3_4 && !UNITY_2020_3_5 && !UNITY_2020_3_6 && !UNITY_2020_3_7 && !UNITY_2020_3_8 && !UNITY_2020_3_9 && !UNITY_2020_3_10 && !UNITY_2020_3_11 && !UNITY_2020_3_12 && !UNITY_2020_3_13 && !UNITY_2020_3_14 && !UNITY_2020_3_15 && !UNITY_2020_3_16) || (UNITY_2019_4_OR_NEWER && !UNITY_2019_4_0 && !UNITY_2019_4_1 && !UNITY_2019_4_2 && !UNITY_2019_4_3 && !UNITY_2019_4_4 && !UNITY_2019_4_5 && !UNITY_2019_4_6 && !UNITY_2019_4_7 && !UNITY_2019_4_8 && !UNITY_2019_4_9 && !UNITY_2019_4_10 && !UNITY_2019_4_11 && !UNITY_2019_4_12 && !UNITY_2019_4_13 && !UNITY_2019_4_14 && !UNITY_2019_4_15 && !UNITY_2019_4_16 && !UNITY_2019_4_17 && !UNITY_2019_4_18 && !UNITY_2019_4_19 && !UNITY_2019_4_20 && !UNITY_2019_4_21 && !UNITY_2019_4_22 && !UNITY_2019_4_23 && !UNITY_2019_4_24 && !UNITY_2019_4_25 && !UNITY_2019_4_26 && !UNITY_2019_4_27 && !UNITY_2019_4_28 && !UNITY_2019_4_29 && !UNITY_2019_4_30)
  10. // Unity added Android x86_64 support in 2021.2.0 and backported to 2020.3.17 and 2019.4.31
  11. #define AVPROVIDEO_UNITY_ANDROID_X8664_SUPPORT
  12. #endif
  13. #if UNITY_2019_1_OR_NEWER
  14. #define AVPROVIDEO_UNITY_UWP_ARM64_SUPPORT
  15. #endif
  16. #if UNITY_2018_1_OR_NEWER
  17. #define AVPROVIDEO_UNITY_BUILDWITHREPORT_SUPPORT
  18. #endif
  19. using UnityEngine;
  20. using UnityEditor;
  21. using UnityEditor.Build;
  22. #if AVPROVIDEO_UNITY_BUILDWITHREPORT_SUPPORT
  23. using UnityEditor.Build.Reporting;
  24. #endif
  25. using System.Collections.Generic;
  26. using System.IO;
  27. //-----------------------------------------------------------------------------
  28. // Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
  29. //-----------------------------------------------------------------------------
  30. namespace RenderHeads.Media.AVProVideo.Editor
  31. {
  32. /// <summary>
  33. /// Some versions of Unity do not support specific CPU architectures for plugin files
  34. /// so this Build Preprocessor checks the plugin files for those and either disables
  35. /// them if their arch is not supported, or assigns the correct arch and enables them
  36. /// </summary>
  37. public class PluginProcessor :
  38. #if AVPROVIDEO_UNITY_BUILDWITHREPORT_SUPPORT
  39. IPreprocessBuildWithReport
  40. #else
  41. IPreprocessBuild
  42. #endif
  43. {
  44. internal class CpuArchitecture
  45. {
  46. internal CpuArchitecture(string code, bool isSupportedByThisUnityVersion)
  47. {
  48. _code = code;
  49. _isSupportedByThisUnityVersion = isSupportedByThisUnityVersion;
  50. }
  51. private string _code;
  52. private bool _isSupportedByThisUnityVersion;
  53. internal string Code()
  54. {
  55. return _code;
  56. }
  57. internal bool IsSupportedByThisUnityVersion()
  58. {
  59. return _isSupportedByThisUnityVersion;
  60. }
  61. }
  62. internal class PluginFile
  63. {
  64. internal PluginFile(BuildTarget buildTarget, string relativeFilePath, bool supportsEditor, CpuArchitecture cpuArchitecture)
  65. {
  66. _buildTarget = buildTarget;
  67. _relativeFilePath = relativeFilePath;
  68. _cpuArchitecture = cpuArchitecture;
  69. _supportsEditor = supportsEditor;
  70. }
  71. internal bool IsBuildTarget(BuildTarget buildTarget)
  72. {
  73. return (_buildTarget == buildTarget);
  74. }
  75. internal BuildTarget BuildTarget()
  76. {
  77. return _buildTarget;
  78. }
  79. internal bool IsForFile(string path)
  80. {
  81. return path.Replace("\\", "/").Contains(_relativeFilePath);
  82. }
  83. internal bool IsSupportedByThisUnityVersion()
  84. {
  85. return _cpuArchitecture.IsSupportedByThisUnityVersion();
  86. }
  87. internal string CpuArchitectureCode()
  88. {
  89. return _cpuArchitecture.Code();
  90. }
  91. internal bool SupportsEditor()
  92. {
  93. return _supportsEditor;
  94. }
  95. private BuildTarget _buildTarget;
  96. private string _relativeFilePath;
  97. private CpuArchitecture _cpuArchitecture;
  98. private bool _supportsEditor;
  99. }
  100. private static List<PluginFile> _pluginFiles = new List<PluginFile>(32);
  101. internal static void AddPluginFiles(BuildTarget buildTarget, string[] filenames, string folderPrefix, bool supportsEditor, CpuArchitecture cpuArchitecture)
  102. {
  103. foreach (string filename in filenames)
  104. {
  105. _pluginFiles.Add(new PluginFile(buildTarget, folderPrefix + filename, supportsEditor, cpuArchitecture));
  106. }
  107. }
  108. internal static void AddPlugins_Android()
  109. {
  110. #if AVPROVIDEO_UNITY_ANDROID_ARM64_SUPPORT
  111. const bool IsAndroidArm64Supported = true;
  112. #else
  113. const bool IsAndroidArm64Supported = false;
  114. #endif
  115. #if AVPROVIDEO_UNITY_ANDROID_X86_SUPPORT
  116. const bool IsAndroidX86Supported = true;
  117. #else
  118. const bool IsAndroidX86Supported = false;
  119. #endif
  120. #if AVPROVIDEO_UNITY_ANDROID_X8664_SUPPORT
  121. const bool IsAndroidX8664Supported = true;
  122. #else
  123. const bool IsAndroidX8664Supported = false;
  124. #endif
  125. string[] filenames = {
  126. "libAudio360.so",
  127. "libAudio360-JNI.so",
  128. "libAVProVideo2Native.so",
  129. "libopus.so",
  130. "libopusJNI.so",
  131. "libresample-rh.so",
  132. "libsamplerate-android.so",
  133. "libssrc-android.so",
  134. };
  135. BuildTarget target = BuildTarget.Android;
  136. AddPluginFiles(target, filenames, "Android/libs/armeabi-v7a/", false, new CpuArchitecture("ARMv7", true));
  137. AddPluginFiles(target, filenames, "Android/libs/arm64-v8a/", false, new CpuArchitecture("ARM64", IsAndroidArm64Supported));
  138. AddPluginFiles(target, filenames, "Android/libs/x86/", false, new CpuArchitecture("X86", IsAndroidX86Supported));
  139. AddPluginFiles(target, filenames, "Android/libs/x86_64/", false, new CpuArchitecture("X86_64", IsAndroidX8664Supported));
  140. }
  141. internal static void AddPlugins_UWP()
  142. {
  143. #if AVPROVIDEO_UNITY_UWP_ARM64_SUPPORT
  144. const bool IsUwpArm64Supported = true;
  145. #else
  146. const bool IsUwpArm64Supported = false;
  147. #endif
  148. string[] filenames = {
  149. "Audio360.dll",
  150. "AVProVideo.dll",
  151. "AVProVideoWinRT.dll",
  152. };
  153. BuildTarget target = BuildTarget.WSAPlayer;
  154. AddPluginFiles(target, filenames, "WSA/UWP/ARM/", false, new CpuArchitecture("ARM", true));
  155. AddPluginFiles(target, filenames, "WSA/UWP/ARM64/", false, new CpuArchitecture("ARM64", IsUwpArm64Supported));
  156. AddPluginFiles(target, filenames, "WSA/UWP/x86/", false, new CpuArchitecture("X86", true));
  157. AddPluginFiles(target, filenames, "WSA/UWP/x86_64/", false, new CpuArchitecture("X64", true));
  158. }
  159. private static void BuildPluginFileList()
  160. {
  161. _pluginFiles.Clear();
  162. AddPlugins_Android();
  163. AddPlugins_UWP();
  164. }
  165. private class SFileToDelete
  166. {
  167. public SFileToDelete(string fn)
  168. {
  169. filename = fn;
  170. fullPath = "";
  171. found = false;
  172. }
  173. public string filename;
  174. public string fullPath;
  175. public bool found;
  176. };
  177. private static void RemoveLegacyPluginFiles()
  178. {
  179. List<SFileToDelete> aFilesToDelete = new List<SFileToDelete>();
  180. #if (UNITY_EDITOR && UNITY_ANDROID)
  181. aFilesToDelete.Add( new SFileToDelete( "Android/guava-27.1-android.jar" ) );
  182. #endif
  183. if ( aFilesToDelete.Count > 0 )
  184. {
  185. int iNumFoundFilesToDelete = 0;
  186. string aFilesToDeleteString = "";
  187. PluginImporter[] importers = PluginImporter.GetAllImporters();
  188. foreach (PluginImporter pi in importers)
  189. {
  190. foreach( SFileToDelete fileToDelete in aFilesToDelete )
  191. {
  192. string pluginFilename = pi.assetPath;
  193. pluginFilename.Replace("\\", "/");
  194. if( pluginFilename.Contains( fileToDelete.filename ) )
  195. {
  196. fileToDelete.fullPath = pi.assetPath;
  197. fileToDelete.found = true;
  198. if( iNumFoundFilesToDelete > 0 )
  199. {
  200. aFilesToDeleteString += "\n";
  201. }
  202. aFilesToDeleteString += pi.assetPath;
  203. ++iNumFoundFilesToDelete;
  204. }
  205. }
  206. }
  207. if( iNumFoundFilesToDelete > 0 )
  208. {
  209. string message = ( iNumFoundFilesToDelete == 1 ) ? "A legacy AVPro Video plugin file has been found that requires deleting in order to build." : "Legacy AVPro Video plugin files have been found that require deleting in order to build.";
  210. Debug.Log("[AVProVideo] " + message + " Files: " + aFilesToDeleteString );
  211. if ( EditorUtility.DisplayDialog( "AVPro Video Legacy File", message + "\n\nDelete the following files?\n\n" + aFilesToDeleteString, "Delete", "Ignore" ) )
  212. {
  213. foreach( SFileToDelete fileToDelete in aFilesToDelete )
  214. {
  215. bool bDeleted = AssetDatabase.DeleteAsset( fileToDelete.fullPath );
  216. if( bDeleted )
  217. {
  218. Debug.Log( "[AVProVideo] Deleting " + fileToDelete.fullPath );
  219. }
  220. }
  221. }
  222. }
  223. }
  224. }
  225. public int callbackOrder { get { return 0; } }
  226. #if AVPROVIDEO_UNITY_BUILDWITHREPORT_SUPPORT
  227. public void OnPreprocessBuild(BuildReport report)
  228. {
  229. RemoveLegacyPluginFiles();
  230. BuildPluginFileList();
  231. CheckNativePlugins(report.summary.platform);
  232. }
  233. #else
  234. public void OnPreprocessBuild(BuildTarget target, string path)
  235. {
  236. RemoveLegacyPluginFiles();
  237. BuildPluginFileList();
  238. CheckNativePlugins(target);
  239. }
  240. #endif
  241. internal static void CheckNativePlugins(BuildTarget target)
  242. {
  243. PluginImporter[] importers = PluginImporter.GetAllImporters();
  244. foreach (PluginImporter pi in importers)
  245. {
  246. // Currently we're only interested in native plugins
  247. if (!pi.isNativePlugin) continue;
  248. // Skip plugins that aren't in the AVProVideo path
  249. // NOTE: This is commented out for now to allow the case where users have moved the plugin files to another folder.
  250. // Eventually might need a more robust method, perhaps using GUIDS
  251. //if (!pi.assetPath.Contains("AVProVideo")) continue;
  252. foreach (PluginFile pluginFile in _pluginFiles)
  253. {
  254. if (pluginFile.IsBuildTarget(target) &&
  255. pluginFile.IsForFile(pi.assetPath))
  256. {
  257. pi.SetCompatibleWithAnyPlatform(false);
  258. if (pluginFile.IsSupportedByThisUnityVersion())
  259. {
  260. Debug.Log("[AVProVideo] Enabling " + pluginFile.CpuArchitectureCode() + " " + pi.assetPath);
  261. pi.SetCompatibleWithEditor(pluginFile.SupportsEditor());
  262. pi.SetCompatibleWithPlatform(pluginFile.BuildTarget(), true);
  263. pi.SetPlatformData(pluginFile.BuildTarget(), "CPU", pluginFile.CpuArchitectureCode());
  264. }
  265. else
  266. {
  267. pi.SetCompatibleWithEditor(false);
  268. pi.SetCompatibleWithPlatform(pluginFile.BuildTarget(), false);
  269. pi.SetPlatformData(pluginFile.BuildTarget(), "CPU", "");
  270. Debug.Log("[AVProVideo] Disabling " + pluginFile.CpuArchitectureCode() + " " + pi.assetPath);
  271. }
  272. pi.SaveAndReimport();
  273. break;
  274. }
  275. }
  276. }
  277. }
  278. }
  279. }