CompatibilityUtil.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. #if UNITY_EDITOR
  2. using System.Runtime.CompilerServices;
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace MTE
  6. {
  7. public enum TerrainMaterialType
  8. {
  9. BuiltInStandard,
  10. BuiltInLegacyDiffuse,
  11. BuiltInLegacySpecular,
  12. Custom,
  13. LWRPTerrainLit_Removed,
  14. URPTerrainLit,
  15. Unknown,
  16. }
  17. public static class CompatibilityUtil
  18. {
  19. public static TerrainLayer[] GetSplatLayers(TerrainData terrainData)
  20. {
  21. return terrainData.terrainLayers;
  22. }
  23. public static void SetSplatLayers(TerrainData terrainData, TerrainLayer[] layers)
  24. {
  25. terrainData.terrainLayers = layers;
  26. }
  27. public static Texture2D GetSplatLayerNormalMap(TerrainLayer splatLayer)
  28. {
  29. if (!splatLayer)
  30. {
  31. return null;
  32. }
  33. return splatLayer.normalMapTexture;
  34. }
  35. public static Texture2D GetSplatLayerDiffuseTexture(TerrainLayer splatLayer)
  36. {
  37. if (!splatLayer)
  38. {
  39. return null;
  40. }
  41. return splatLayer.diffuseTexture;
  42. }
  43. public static float GetSplatLayerMetallic(TerrainLayer splatLayer)
  44. {
  45. if (!splatLayer)
  46. {
  47. return 0;
  48. }
  49. return splatLayer.metallic;
  50. }
  51. public static float GetSplatLayerSmoothness(TerrainLayer splatLayer)
  52. {
  53. if (!splatLayer)
  54. {
  55. return 0;
  56. }
  57. return splatLayer.smoothness;
  58. }
  59. public static Texture2D GetMaskTexture(TerrainLayer splatLayer)
  60. {
  61. if (!splatLayer)
  62. {
  63. return null;
  64. }
  65. return splatLayer.maskMapTexture;
  66. }
  67. public static TerrainLayer[] CreateSplatLayers(int number)
  68. {
  69. return new TerrainLayer[number];
  70. }
  71. public static TerrainLayer CreateSplatLayer()
  72. {
  73. return new TerrainLayer();
  74. }
  75. public static void SetSplatLayerDiffueTexture(TerrainLayer splatLayer, Texture2D diffuseTexture)
  76. {
  77. splatLayer.diffuseTexture = diffuseTexture;
  78. }
  79. public static void SetSplatLayerNormalMap(TerrainLayer splatLayer, Texture2D normalMap)
  80. {
  81. splatLayer.normalMapTexture = normalMap;
  82. }
  83. public static void SaveSplatLayer(TerrainLayer splat, string name)
  84. {
  85. AssetDatabase.CreateAsset(splat, name);
  86. }
  87. /// <summary>
  88. /// Create a prefab file for a GameObject.
  89. /// </summary>
  90. /// <param name="obj">the GameObject</param>
  91. /// <param name="relativePath">Unity file path of the prefab</param>
  92. public static void CreatePrefab(GameObject obj, string relativePath)
  93. {
  94. PrefabUtility.SaveAsPrefabAsset(obj, relativePath);
  95. }
  96. /// <summary>
  97. /// Check if a gameObject is the root of a instantiated prefab.
  98. /// </summary>
  99. /// <param name="gameObject"></param>
  100. /// <returns></returns>
  101. public static bool IsPrefab(GameObject gameObject)
  102. {
  103. return PrefabUtility.IsAnyPrefabInstanceRoot(gameObject);
  104. }
  105. public static bool IsInstanceOfPrefab(GameObject obj, GameObject prefab)
  106. {
  107. return PrefabUtility.GetCorrespondingObjectFromOriginalSource(obj) == prefab;
  108. }
  109. public static Object GetPrefabRoot(GameObject instance)
  110. {
  111. return PrefabUtility.GetCorrespondingObjectFromSource(instance);
  112. }
  113. //This field will invoke a compile error if this version isn't officially supported by MTE.
  114. public const string VersionCheckString =
  115. #if UNITY_2018_4
  116. "2018.4"
  117. #elif UNITY_2019_3
  118. "2019.3"
  119. #elif UNITY_2019_4
  120. "2019.4"
  121. #elif UNITY_2020_1
  122. "2020.1"
  123. #elif UNITY_2020_2
  124. "2020.2"
  125. #elif UNITY_2020_3
  126. "2020.3"
  127. #elif UNITY_2021_1
  128. "2021.1"
  129. #elif UNITY_2021_2
  130. "2021.2"
  131. #elif UNITY_2021_3_OR_NEWER
  132. #warning Might be a unsupported Unity Version, not tested yet.
  133. "2021.3+"
  134. #else
  135. #error Unsupported Unity Version. You can try to fix this file or report the issue.
  136. #endif
  137. ;
  138. public static bool IsWebRequestError(UnityEngine.Networking.UnityWebRequest request)
  139. {
  140. #if UNITY_2018_4 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1
  141. return request.isNetworkError || request.isHttpError;
  142. #elif UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  143. return request.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError
  144. || request.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError;
  145. #else
  146. #error not supported on any Unity build targets
  147. #endif
  148. }
  149. public static object AttachOnSceneGUI(System.Action<SceneView> action)
  150. {
  151. #if UNITY_2018_4
  152. SceneView.OnSceneFunc func = view => action(view);
  153. SceneView.onSceneGUIDelegate += func;
  154. return func;
  155. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  156. SceneView.duringSceneGui += action;
  157. return action;
  158. #else
  159. #error not supported on any Unity build targets
  160. #endif
  161. }
  162. public static void DetachOnSceneGUI(object cachedOnSceneGUI)
  163. {
  164. #if UNITY_2018_4
  165. SceneView.OnSceneFunc func = (SceneView.OnSceneFunc)cachedOnSceneGUI;
  166. SceneView.onSceneGUIDelegate -= func;
  167. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  168. var action = (System.Action<SceneView>)cachedOnSceneGUI;
  169. SceneView.duringSceneGui -= action;
  170. #else
  171. #error not supported on any Unity build targets
  172. #endif
  173. }
  174. public static void DontOptimizeMesh(ModelImporter importer)
  175. {
  176. #if UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  177. importer.optimizeMeshVertices = false;
  178. importer.optimizeMeshPolygons = false;
  179. importer.weldVertices = false;
  180. #elif UNITY_2018_4
  181. importer.optimizeMesh = false;
  182. #else
  183. #error not supported on any Unity build targets
  184. #endif
  185. }
  186. public static TerrainMaterialType GetTerrainMaterialType(Terrain terrain)
  187. {
  188. #if UNITY_2018_4
  189. switch (terrain.materialType)
  190. {
  191. case Terrain.MaterialType.BuiltInStandard:
  192. return TerrainMaterialType.BuiltInStandard;
  193. case Terrain.MaterialType.BuiltInLegacyDiffuse:
  194. return TerrainMaterialType.BuiltInLegacyDiffuse;
  195. case Terrain.MaterialType.BuiltInLegacySpecular:
  196. return TerrainMaterialType.BuiltInLegacySpecular;
  197. case Terrain.MaterialType.Custom:
  198. return TerrainMaterialType.Custom;
  199. default:
  200. throw new System.ArgumentOutOfRangeException();
  201. }
  202. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  203. var material = terrain.materialTemplate;
  204. if (material == null)
  205. {
  206. Debug.LogErrorFormat(
  207. "Terrain<{0}> is using an empty material." +
  208. "The conversion result is probably not right." +
  209. " Please check the material of the terrain",
  210. terrain.name);
  211. return TerrainMaterialType.Custom;
  212. }
  213. if (material.name == "Default-Terrain-Standard")
  214. {
  215. return TerrainMaterialType.BuiltInStandard;
  216. }
  217. if (material.name == "Default-Terrain-Diffuse")
  218. {
  219. return TerrainMaterialType.BuiltInLegacyDiffuse;
  220. }
  221. if (material.name == "Default-Terrain-Specular")
  222. {
  223. return TerrainMaterialType.BuiltInLegacySpecular;
  224. }
  225. if (material.shader != null
  226. && material.shader.name == "Lightweight Render Pipeline/Terrain/Lit")
  227. {
  228. return TerrainMaterialType.LWRPTerrainLit_Removed;
  229. }
  230. if (material.shader != null
  231. && material.shader.name == "Universal Render Pipeline/Terrain/Lit")
  232. {
  233. return TerrainMaterialType.URPTerrainLit;
  234. }
  235. var materialFileRelativePath = AssetDatabase.GetAssetPath(material);
  236. Debug.LogErrorFormat(
  237. "Terrain<{0}> is using a material<{1}> at {2} that is unknown to MTE." +
  238. "The conversion result is probably not right.",
  239. terrain.name, material.name, materialFileRelativePath);
  240. return TerrainMaterialType.Unknown;
  241. #else
  242. #error not supported on any Unity build targets
  243. #endif
  244. }
  245. public static Color GetTerrainMaterialSpecularColor(Terrain terrain)
  246. {
  247. #if UNITY_2018_4
  248. return terrain.legacySpecular;
  249. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  250. var material = terrain.materialTemplate;
  251. if (material.HasProperty("_SpecColor"))
  252. {
  253. return material.GetColor("_SpecColor");
  254. }
  255. return Color.black;
  256. #else
  257. #error not supported on any Unity build targets
  258. #endif
  259. }
  260. public static float GetTerrainMaterialShininess(Terrain terrain)
  261. {
  262. #if UNITY_2018_4
  263. return terrain.legacyShininess;
  264. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  265. var material = terrain.materialTemplate;
  266. return material.GetFloat("_Shininess");
  267. #else
  268. #error not supported on any Unity build targets
  269. #endif
  270. }
  271. public static int GetHeightmapWidth(TerrainData terrainData)
  272. {
  273. #if UNITY_2018_4
  274. return terrainData.heightmapWidth;
  275. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  276. return terrainData.heightmapResolution;
  277. #endif
  278. }
  279. public static int GetHeightmapHeight(TerrainData terrainData)
  280. {
  281. #if UNITY_2018_4
  282. return terrainData.heightmapHeight;
  283. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  284. return terrainData.heightmapResolution;
  285. #endif
  286. }
  287. public static void SetTerrainMaterialType(Terrain terrain, TerrainMaterialType materialType)
  288. {
  289. switch (materialType)
  290. {
  291. case TerrainMaterialType.BuiltInStandard:
  292. {
  293. #if UNITY_2018_4
  294. terrain.materialType = Terrain.MaterialType.BuiltInStandard;
  295. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  296. var material = Resources.Load<Material>("unity_builtin_extra/Default-Terrain-Standard");
  297. terrain.materialTemplate = material;
  298. #else
  299. #error not supported on any Unity build targets
  300. #endif
  301. }
  302. break;
  303. case TerrainMaterialType.BuiltInLegacyDiffuse:
  304. {
  305. #if UNITY_2018_4
  306. terrain.materialType = Terrain.MaterialType.BuiltInLegacyDiffuse;
  307. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  308. var material = Resources.Load<Material>("unity_builtin_extra/Default-Terrain-Diffuse");
  309. terrain.materialTemplate = material;
  310. #else
  311. #error not supported on any Unity build targets
  312. #endif
  313. }
  314. break;
  315. case TerrainMaterialType.BuiltInLegacySpecular:
  316. {
  317. #if UNITY_2018_4
  318. terrain.materialType = Terrain.MaterialType.BuiltInLegacySpecular;
  319. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  320. var material = Resources.Load<Material>("unity_builtin_extra/Default-Terrain-Specular");
  321. terrain.materialTemplate = material;
  322. #else
  323. #error not supported on any Unity build targets
  324. #endif
  325. }
  326. break;
  327. default:
  328. throw new System.NotSupportedException("Cannot set terrain material.");
  329. }
  330. }
  331. //Unity 2021.2.0 changed
  332. //https://unity3d.com/unity/whats-new/2021.2.0
  333. //Graphics: Changed: Renamed Texture2D.Resize to Reinitialize.
  334. public static void ReinitializeTexture2D(Texture2D texture, int newWidth, int newHeight)
  335. {
  336. #if UNITY_2018_4 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1
  337. texture.Resize(newWidth, newHeight);
  338. #elif UNITY_2021_2_OR_NEWER
  339. texture.Reinitialize(newWidth, newHeight);
  340. #endif
  341. }
  342. public static byte[] EncodeTextureToPNG(Texture2D texture)
  343. {
  344. return ImageConversion.EncodeToPNG(texture);
  345. }
  346. public static bool GetTextureReadable(Texture texture)
  347. {
  348. return texture.isReadable;
  349. }
  350. public static bool BeginFoldoutHeaderGroup(bool foldout, string content)
  351. {
  352. #if UNITY_2018_4
  353. return GUILayout.Toggle(foldout, content, "button");
  354. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  355. return EditorGUILayout.BeginFoldoutHeaderGroup(foldout, content);
  356. #else
  357. #error not supported on any Unity build targets
  358. #endif
  359. }
  360. public static void EndFoldoutHeaderGroup()
  361. {
  362. #if UNITY_2018_4
  363. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  364. EditorGUILayout.EndFoldoutHeaderGroup();
  365. #else
  366. #error not supported on any Unity build targets
  367. #endif
  368. }
  369. //FBXExporter support
  370. public static System.Func<string, UnityEngine.Object, string> exportFbxMethod = null;
  371. public static bool InitFbxExport()
  372. {
  373. var ModelExporterType = System.Type.GetType("UnityEditor.Formats.Fbx.Exporter.ModelExporter, Unity.Formats.Fbx.Editor");
  374. if (ModelExporterType == null)
  375. {
  376. return false;
  377. }
  378. var method = ModelExporterType.GetMethod("ExportObject");
  379. if (method == null)
  380. {
  381. Debug.LogError("Failed to fetch the method: UnityEditor.Formats.Fbx.Exporter.ModelExporter.");
  382. return false;
  383. }
  384. exportFbxMethod = (System.Func<string, UnityEngine.Object, string>)System.Delegate.CreateDelegate(typeof(System.Func<string, UnityEngine.Object, string>), method);
  385. //Debug.Log("Successfully fetched the method: UnityEditor.Formats.Fbx.Exporter.ModelExporter().");
  386. return true;
  387. }
  388. private static Texture2D MakeTexture(int width, int height, Color color)
  389. {
  390. Color[] pixels = new Color[width * height];
  391. for (int i = 0; i < pixels.Length; i++)
  392. {
  393. pixels[i] = color;
  394. }
  395. Texture2D result = new Texture2D(width, height);
  396. result.SetPixels(pixels);
  397. result.Apply();
  398. return result;
  399. }
  400. public static GUIStyle GetGridListStyle()
  401. {
  402. var editorLabelStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).label;
  403. var gridListStyle = new GUIStyle(editorLabelStyle)
  404. {
  405. fixedWidth = 0,
  406. fixedHeight = 0,
  407. stretchWidth = true,
  408. stretchHeight = true,
  409. alignment = TextAnchor.MiddleCenter
  410. };
  411. Color32 hoverColor = Color.grey;
  412. Color32 selectedColor = new Color32(62, 125, 231, 255);
  413. gridListStyle.onHover.background = MakeTexture(1, 1, selectedColor);
  414. gridListStyle.hover.background = MakeTexture(1, 1, hoverColor);
  415. gridListStyle.normal.background = MakeTexture(1, 1, Color.clear);
  416. gridListStyle.onNormal.background = MakeTexture(1, 1, selectedColor);
  417. //gridListStyle.hover.background = MakeTexture(1, 1, new Color32(255, 255, 255, 62));
  418. //gridListStyle.onNormal.background = MakeTexture(1, 1, new Color32(62, 125, 231, 255));
  419. return gridListStyle;
  420. }
  421. public static object GetRenderPipelineAsset()
  422. {
  423. return UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset;
  424. }
  425. public static void SetTextureFormatToA8(TextureImporterPlatformSettings textureSettings)
  426. {
  427. textureSettings.format = TextureImporterFormat.R8;
  428. }
  429. public static int FindPropertyIndex(Shader shader, string propertyName)
  430. {
  431. #if UNITY_2018_4
  432. var propertyCount = ShaderUtil.GetPropertyCount(shader);
  433. for (int i = 0; i < propertyCount; i++)
  434. {
  435. var name = ShaderUtil.GetPropertyName(shader, i);
  436. if (name == propertyName)
  437. {
  438. return i;
  439. }
  440. }
  441. return -1;
  442. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  443. return shader.FindPropertyIndex(propertyName);
  444. #else
  445. #error not supported on any Unity build targets
  446. #endif
  447. }
  448. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  449. public static byte GetColor32ChannelValue(Color32 color32, int channel)
  450. {
  451. #if UNITY_2018_4
  452. switch (channel)
  453. {
  454. case 0:
  455. return color32.r;
  456. case 1:
  457. return color32.g;
  458. case 2:
  459. return color32.b;
  460. case 3:
  461. return color32.a;
  462. default:
  463. throw new System.IndexOutOfRangeException("Invalid Color32 index(" + channel.ToString() + ")!");
  464. }
  465. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  466. return color32[channel];
  467. #endif
  468. }
  469. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  470. public static void SetColor32ChannelValue(ref Color32 color32, int channel, byte value)
  471. {
  472. #if UNITY_2018_4
  473. switch (channel)
  474. {
  475. case 0:
  476. color32.r = value;
  477. break;
  478. case 1:
  479. color32.g = value;
  480. break;
  481. case 2:
  482. color32.b = value;
  483. break;
  484. case 3:
  485. color32.a = value;
  486. break;
  487. default:
  488. throw new System.IndexOutOfRangeException("Invalid Color32 index(" + channel.ToString() + ")!");
  489. }
  490. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  491. color32[channel] = value;
  492. #endif
  493. }
  494. public class GUI
  495. {
  496. public static float Slider(
  497. Rect position,
  498. float value,
  499. float size,
  500. float start,
  501. float end,
  502. GUIStyle slider,
  503. GUIStyle thumb,
  504. bool horiz,
  505. int id)
  506. {
  507. return UnityEngine.GUI.Slider(
  508. position,
  509. value,
  510. size,
  511. start,
  512. end,
  513. slider,
  514. thumb,
  515. horiz,
  516. id);
  517. }
  518. }
  519. public class EditorGUILayoutEx
  520. {
  521. public static bool BeginFoldout(bool foldout, string content)
  522. {
  523. #if UNITY_2018_4
  524. return GUILayout.Toggle(foldout, content, "button");
  525. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  526. return EditorGUILayout.BeginFoldoutHeaderGroup(foldout, content);
  527. #endif
  528. }
  529. public static void EndFoldout()
  530. {
  531. #if UNITY_2018_4
  532. //nothing to do
  533. #elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
  534. EditorGUILayout.EndFoldoutHeaderGroup();
  535. #endif
  536. }
  537. }
  538. }
  539. }
  540. #endif