#if UNITY_EDITOR
using System.Runtime.CompilerServices;
using UnityEditor;
using UnityEngine;
namespace MTE
{
public enum TerrainMaterialType
{
BuiltInStandard,
BuiltInLegacyDiffuse,
BuiltInLegacySpecular,
Custom,
LWRPTerrainLit_Removed,
URPTerrainLit,
Unknown,
}
public static class CompatibilityUtil
{
public static TerrainLayer[] GetSplatLayers(TerrainData terrainData)
{
return terrainData.terrainLayers;
}
public static void SetSplatLayers(TerrainData terrainData, TerrainLayer[] layers)
{
terrainData.terrainLayers = layers;
}
public static Texture2D GetSplatLayerNormalMap(TerrainLayer splatLayer)
{
if (!splatLayer)
{
return null;
}
return splatLayer.normalMapTexture;
}
public static Texture2D GetSplatLayerDiffuseTexture(TerrainLayer splatLayer)
{
if (!splatLayer)
{
return null;
}
return splatLayer.diffuseTexture;
}
public static float GetSplatLayerMetallic(TerrainLayer splatLayer)
{
if (!splatLayer)
{
return 0;
}
return splatLayer.metallic;
}
public static float GetSplatLayerSmoothness(TerrainLayer splatLayer)
{
if (!splatLayer)
{
return 0;
}
return splatLayer.smoothness;
}
public static Texture2D GetMaskTexture(TerrainLayer splatLayer)
{
if (!splatLayer)
{
return null;
}
return splatLayer.maskMapTexture;
}
public static TerrainLayer[] CreateSplatLayers(int number)
{
return new TerrainLayer[number];
}
public static TerrainLayer CreateSplatLayer()
{
return new TerrainLayer();
}
public static void SetSplatLayerDiffueTexture(TerrainLayer splatLayer, Texture2D diffuseTexture)
{
splatLayer.diffuseTexture = diffuseTexture;
}
public static void SetSplatLayerNormalMap(TerrainLayer splatLayer, Texture2D normalMap)
{
splatLayer.normalMapTexture = normalMap;
}
public static void SaveSplatLayer(TerrainLayer splat, string name)
{
AssetDatabase.CreateAsset(splat, name);
}
///
/// Create a prefab file for a GameObject.
///
/// the GameObject
/// Unity file path of the prefab
public static void CreatePrefab(GameObject obj, string relativePath)
{
PrefabUtility.SaveAsPrefabAsset(obj, relativePath);
}
///
/// Check if a gameObject is the root of a instantiated prefab.
///
///
///
public static bool IsPrefab(GameObject gameObject)
{
return PrefabUtility.IsAnyPrefabInstanceRoot(gameObject);
}
public static bool IsInstanceOfPrefab(GameObject obj, GameObject prefab)
{
return PrefabUtility.GetCorrespondingObjectFromOriginalSource(obj) == prefab;
}
public static Object GetPrefabRoot(GameObject instance)
{
return PrefabUtility.GetCorrespondingObjectFromSource(instance);
}
//This field will invoke a compile error if this version isn't officially supported by MTE.
public const string VersionCheckString =
#if UNITY_2018_4
"2018.4"
#elif UNITY_2019_3
"2019.3"
#elif UNITY_2019_4
"2019.4"
#elif UNITY_2020_1
"2020.1"
#elif UNITY_2020_2
"2020.2"
#elif UNITY_2020_3
"2020.3"
#elif UNITY_2021_1
"2021.1"
#elif UNITY_2021_2
"2021.2"
#elif UNITY_2021_3_OR_NEWER
#warning Might be a unsupported Unity Version, not tested yet.
"2021.3+"
#else
#error Unsupported Unity Version. You can try to fix this file or report the issue.
#endif
;
public static bool IsWebRequestError(UnityEngine.Networking.UnityWebRequest request)
{
#if UNITY_2018_4 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1
return request.isNetworkError || request.isHttpError;
#elif UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
return request.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError
|| request.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError;
#else
#error not supported on any Unity build targets
#endif
}
public static object AttachOnSceneGUI(System.Action action)
{
#if UNITY_2018_4
SceneView.OnSceneFunc func = view => action(view);
SceneView.onSceneGUIDelegate += func;
return func;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
SceneView.duringSceneGui += action;
return action;
#else
#error not supported on any Unity build targets
#endif
}
public static void DetachOnSceneGUI(object cachedOnSceneGUI)
{
#if UNITY_2018_4
SceneView.OnSceneFunc func = (SceneView.OnSceneFunc)cachedOnSceneGUI;
SceneView.onSceneGUIDelegate -= func;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var action = (System.Action)cachedOnSceneGUI;
SceneView.duringSceneGui -= action;
#else
#error not supported on any Unity build targets
#endif
}
public static void DontOptimizeMesh(ModelImporter importer)
{
#if UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
importer.optimizeMeshVertices = false;
importer.optimizeMeshPolygons = false;
importer.weldVertices = false;
#elif UNITY_2018_4
importer.optimizeMesh = false;
#else
#error not supported on any Unity build targets
#endif
}
public static TerrainMaterialType GetTerrainMaterialType(Terrain terrain)
{
#if UNITY_2018_4
switch (terrain.materialType)
{
case Terrain.MaterialType.BuiltInStandard:
return TerrainMaterialType.BuiltInStandard;
case Terrain.MaterialType.BuiltInLegacyDiffuse:
return TerrainMaterialType.BuiltInLegacyDiffuse;
case Terrain.MaterialType.BuiltInLegacySpecular:
return TerrainMaterialType.BuiltInLegacySpecular;
case Terrain.MaterialType.Custom:
return TerrainMaterialType.Custom;
default:
throw new System.ArgumentOutOfRangeException();
}
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = terrain.materialTemplate;
if (material == null)
{
Debug.LogErrorFormat(
"Terrain<{0}> is using an empty material." +
"The conversion result is probably not right." +
" Please check the material of the terrain",
terrain.name);
return TerrainMaterialType.Custom;
}
if (material.name == "Default-Terrain-Standard")
{
return TerrainMaterialType.BuiltInStandard;
}
if (material.name == "Default-Terrain-Diffuse")
{
return TerrainMaterialType.BuiltInLegacyDiffuse;
}
if (material.name == "Default-Terrain-Specular")
{
return TerrainMaterialType.BuiltInLegacySpecular;
}
if (material.shader != null
&& material.shader.name == "Lightweight Render Pipeline/Terrain/Lit")
{
return TerrainMaterialType.LWRPTerrainLit_Removed;
}
if (material.shader != null
&& material.shader.name == "Universal Render Pipeline/Terrain/Lit")
{
return TerrainMaterialType.URPTerrainLit;
}
var materialFileRelativePath = AssetDatabase.GetAssetPath(material);
Debug.LogErrorFormat(
"Terrain<{0}> is using a material<{1}> at {2} that is unknown to MTE." +
"The conversion result is probably not right.",
terrain.name, material.name, materialFileRelativePath);
return TerrainMaterialType.Unknown;
#else
#error not supported on any Unity build targets
#endif
}
public static Color GetTerrainMaterialSpecularColor(Terrain terrain)
{
#if UNITY_2018_4
return terrain.legacySpecular;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = terrain.materialTemplate;
if (material.HasProperty("_SpecColor"))
{
return material.GetColor("_SpecColor");
}
return Color.black;
#else
#error not supported on any Unity build targets
#endif
}
public static float GetTerrainMaterialShininess(Terrain terrain)
{
#if UNITY_2018_4
return terrain.legacyShininess;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = terrain.materialTemplate;
return material.GetFloat("_Shininess");
#else
#error not supported on any Unity build targets
#endif
}
public static int GetHeightmapWidth(TerrainData terrainData)
{
#if UNITY_2018_4
return terrainData.heightmapWidth;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
return terrainData.heightmapResolution;
#endif
}
public static int GetHeightmapHeight(TerrainData terrainData)
{
#if UNITY_2018_4
return terrainData.heightmapHeight;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
return terrainData.heightmapResolution;
#endif
}
public static void SetTerrainMaterialType(Terrain terrain, TerrainMaterialType materialType)
{
switch (materialType)
{
case TerrainMaterialType.BuiltInStandard:
{
#if UNITY_2018_4
terrain.materialType = Terrain.MaterialType.BuiltInStandard;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = Resources.Load("unity_builtin_extra/Default-Terrain-Standard");
terrain.materialTemplate = material;
#else
#error not supported on any Unity build targets
#endif
}
break;
case TerrainMaterialType.BuiltInLegacyDiffuse:
{
#if UNITY_2018_4
terrain.materialType = Terrain.MaterialType.BuiltInLegacyDiffuse;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = Resources.Load("unity_builtin_extra/Default-Terrain-Diffuse");
terrain.materialTemplate = material;
#else
#error not supported on any Unity build targets
#endif
}
break;
case TerrainMaterialType.BuiltInLegacySpecular:
{
#if UNITY_2018_4
terrain.materialType = Terrain.MaterialType.BuiltInLegacySpecular;
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
var material = Resources.Load("unity_builtin_extra/Default-Terrain-Specular");
terrain.materialTemplate = material;
#else
#error not supported on any Unity build targets
#endif
}
break;
default:
throw new System.NotSupportedException("Cannot set terrain material.");
}
}
//Unity 2021.2.0 changed
//https://unity3d.com/unity/whats-new/2021.2.0
//Graphics: Changed: Renamed Texture2D.Resize to Reinitialize.
public static void ReinitializeTexture2D(Texture2D texture, int newWidth, int newHeight)
{
#if UNITY_2018_4 || UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1
texture.Resize(newWidth, newHeight);
#elif UNITY_2021_2_OR_NEWER
texture.Reinitialize(newWidth, newHeight);
#endif
}
public static byte[] EncodeTextureToPNG(Texture2D texture)
{
return ImageConversion.EncodeToPNG(texture);
}
public static bool GetTextureReadable(Texture texture)
{
return texture.isReadable;
}
public static bool BeginFoldoutHeaderGroup(bool foldout, string content)
{
#if UNITY_2018_4
return GUILayout.Toggle(foldout, content, "button");
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
return EditorGUILayout.BeginFoldoutHeaderGroup(foldout, content);
#else
#error not supported on any Unity build targets
#endif
}
public static void EndFoldoutHeaderGroup()
{
#if UNITY_2018_4
#elif UNITY_2019_3 || UNITY_2019_4 || UNITY_2020_1 || UNITY_2020_2 || UNITY_2020_3 || UNITY_2021_1 || UNITY_2021_2_OR_NEWER
EditorGUILayout.EndFoldoutHeaderGroup();
#else
#error not supported on any Unity build targets
#endif
}
//FBXExporter support
public static System.Func exportFbxMethod = null;
public static bool InitFbxExport()
{
var ModelExporterType = System.Type.GetType("UnityEditor.Formats.Fbx.Exporter.ModelExporter, Unity.Formats.Fbx.Editor");
if (ModelExporterType == null)
{
return false;
}
var method = ModelExporterType.GetMethod("ExportObject");
if (method == null)
{
Debug.LogError("Failed to fetch the method: UnityEditor.Formats.Fbx.Exporter.ModelExporter.");
return false;
}
exportFbxMethod = (System.Func)System.Delegate.CreateDelegate(typeof(System.Func), method);
//Debug.Log("Successfully fetched the method: UnityEditor.Formats.Fbx.Exporter.ModelExporter().");
return true;
}
private static Texture2D MakeTexture(int width, int height, Color color)
{
Color[] pixels = new Color[width * height];
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = color;
}
Texture2D result = new Texture2D(width, height);
result.SetPixels(pixels);
result.Apply();
return result;
}
public static GUIStyle GetGridListStyle()
{
var editorLabelStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).label;
var gridListStyle = new GUIStyle(editorLabelStyle)
{
fixedWidth = 0,
fixedHeight = 0,
stretchWidth = true,
stretchHeight = true,
alignment = TextAnchor.MiddleCenter
};
Color32 hoverColor = Color.grey;
Color32 selectedColor = new Color32(62, 125, 231, 255);
gridListStyle.onHover.background = MakeTexture(1, 1, selectedColor);
gridListStyle.hover.background = MakeTexture(1, 1, hoverColor);
gridListStyle.normal.background = MakeTexture(1, 1, Color.clear);
gridListStyle.onNormal.background = MakeTexture(1, 1, selectedColor);
//gridListStyle.hover.background = MakeTexture(1, 1, new Color32(255, 255, 255, 62));
//gridListStyle.onNormal.background = MakeTexture(1, 1, new Color32(62, 125, 231, 255));
return gridListStyle;
}
public static object GetRenderPipelineAsset()
{
return UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset;
}
public static void SetTextureFormatToA8(TextureImporterPlatformSettings textureSettings)
{
textureSettings.format = TextureImporterFormat.R8;
}
public static int FindPropertyIndex(Shader shader, string propertyName)
{
#if UNITY_2018_4
var propertyCount = ShaderUtil.GetPropertyCount(shader);
for (int i = 0; i < propertyCount; i++)
{
var name = ShaderUtil.GetPropertyName(shader, i);
if (name == propertyName)
{
return i;
}
}
return -1;
#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
return shader.FindPropertyIndex(propertyName);
#else
#error not supported on any Unity build targets
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte GetColor32ChannelValue(Color32 color32, int channel)
{
#if UNITY_2018_4
switch (channel)
{
case 0:
return color32.r;
case 1:
return color32.g;
case 2:
return color32.b;
case 3:
return color32.a;
default:
throw new System.IndexOutOfRangeException("Invalid Color32 index(" + channel.ToString() + ")!");
}
#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
return color32[channel];
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetColor32ChannelValue(ref Color32 color32, int channel, byte value)
{
#if UNITY_2018_4
switch (channel)
{
case 0:
color32.r = value;
break;
case 1:
color32.g = value;
break;
case 2:
color32.b = value;
break;
case 3:
color32.a = value;
break;
default:
throw new System.IndexOutOfRangeException("Invalid Color32 index(" + channel.ToString() + ")!");
}
#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
color32[channel] = value;
#endif
}
public class GUI
{
public static float Slider(
Rect position,
float value,
float size,
float start,
float end,
GUIStyle slider,
GUIStyle thumb,
bool horiz,
int id)
{
return UnityEngine.GUI.Slider(
position,
value,
size,
start,
end,
slider,
thumb,
horiz,
id);
}
}
public class EditorGUILayoutEx
{
public static bool BeginFoldout(bool foldout, string content)
{
#if UNITY_2018_4
return GUILayout.Toggle(foldout, content, "button");
#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
return EditorGUILayout.BeginFoldoutHeaderGroup(foldout, content);
#endif
}
public static void EndFoldout()
{
#if UNITY_2018_4
//nothing to do
#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
EditorGUILayout.EndFoldoutHeaderGroup();
#endif
}
}
}
}
#endif