From db44a6e164c2072a6526bb4e588e7590df4e08c4 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 11 May 2021 20:13:09 +0800 Subject: *rename --- .../Tools/ModelUVViewer/Editor/ModelUVViewer.cs | 423 +++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 UnityCollection/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs (limited to 'UnityCollection/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs') diff --git a/UnityCollection/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs b/UnityCollection/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs new file mode 100644 index 0000000..e7e04cc --- /dev/null +++ b/UnityCollection/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs @@ -0,0 +1,423 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System.IO; + + +namespace UVViwer +{ + internal class PostProcessingMesh : AssetPostprocessor + { + void OnPreprocessModel() + { + if (ModelUVViewer.s_Editor == null) + return; + ModelImporter modelImporter = assetImporter as ModelImporter; + string path = modelImporter.assetPath; + string GUID = AssetDatabase.AssetPathToGUID(path); + if (ModelUVViewer.s_Guid == GUID) + { + ModelUVViewer.ForceRepaint(); + } + } + + //void OnPostprocessModel(GameObject go) + //{ + // //return; + // Mesh mesh = go.GetComponent().sharedMesh; + // if (mesh) + // { + // Vector2[] uvs = mesh.uv2; + // for (int i = 0; i < uvs.Length; ++i) + // { + // Vector2 uv = uvs[i]; + // uv.x = Mathf.Clamp(uv.x, 0, 1); + // uv.y = Mathf.Clamp(uv.y, 0, 1); + // uvs[i] = uv; + // } + // mesh.uv2 = uvs; + // } + //} + + } + + public class ModelUVViewer : EditorWindow + { + [MenuItem("Assets/Model UV Viewer", true)] + static bool TryOpenModelUVViewer() + { + string[] guids = Selection.assetGUIDs; + if (guids == null || guids.Length == 0) + return false; + for (int i = 0; i < guids.Length; ++i) + { + string guid = guids[i]; + string path = AssetDatabase.GUIDToAssetPath(guid); + string extension = Path.GetExtension(path).ToLower(); + if (extension != ".fbx") + return false; + } + return true; + } + + [MenuItem("Assets/Model UV Viewer", false)] + static void OpenModelUVViewer() + { + string[] guids = Selection.assetGUIDs; + s_Mesh.Clear(); + s_MeshToAsset = new Dictionary(); + foreach (string guid in guids) + { + string path = AssetDatabase.GUIDToAssetPath(guid); + Mesh mesh = AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)) as Mesh; + if (mesh != null) + { + s_Mesh.Add(mesh); + s_MeshToAsset.Add(mesh.GetHashCode(), guid); + } + } + +#if UNITY_2020 || UNITY_2021 || UNITY_2019 + if (!HasOpenInstances() || s_Editor == null) +#else + if (s_Editor == null) +#endif + { + s_Editor = GetWindow(); + s_Editor.titleContent = new GUIContent("Model UV Viewer"); + s_Editor.Show(); + } + + s_Editor.Focus(); + s_Selcted = string.Empty; + s_TargetTexture = null; + if (s_Mat == null) + { + s_Mat = new Material(Shader.Find("UI/Default")); + } + if (s_UVMesh == null) + { + s_UVMesh = new Mesh(); + } + s_HashCode = 0; + s_TillingOffset = new Rect(0, 0, 1, 1); + } + + public static ModelUVViewer s_Editor; + static List s_Mesh = new List(); + + static string s_Selcted; + static int s_HashCode; + + public static string s_Guid + { + get + { + if (s_HashCode == 0) + return string.Empty; + string guid; + if (s_MeshToAsset.TryGetValue(s_HashCode, out guid)) + return guid; + return string.Empty; + } + } + + static Texture2D s_TargetTexture; + + static int s_Size = 500; + + static Vector2[] s_UV; + + // 性能太低 + //static Vector2[] s_UV + //{ + // get + // { + // Mesh mesh = GetMeshByHashCode(s_HashCode); + // if (mesh == null) + // return null; + // return GetMeshUV(mesh, s_UVIndex); + // } + //} + + static int s_UVIndex; + + static Material s_Mat; + + static Mesh s_UVMesh; + + static Rect s_TillingOffset; + + static GUIStyle s_SelectStyle; + static GUIStyle s_AlignRightText; + + public static Dictionary s_MeshToAsset = new Dictionary(); + + static IEnumerator s_ReloadUV; + + static bool s_HasWarning + { + get + { + return s_Warning != null && s_Warning != string.Empty && s_Warning.Length > 0; + } + } + static string s_Warning; + + private void OnGUI() + { + if (s_Editor == null) + return; + if (s_Mesh == null || s_Mesh.Count == 0) + return; + + if (s_SelectStyle == null) + { + s_SelectStyle = new GUIStyle(EditorStyles.miniButtonMid); + s_SelectStyle.normal.background = EditorStyles.miniButtonMid.active.background; + s_SelectStyle.normal.scaledBackgrounds = EditorStyles.miniButtonMid.active.scaledBackgrounds; + } + + if (s_AlignRightText == null) + { + s_AlignRightText = new GUIStyle(EditorStyles.label); + s_AlignRightText.alignment = TextAnchor.MiddleRight; + } + + if (Event.current.isScrollWheel) + { + Vector2 delta = Event.current.delta; + float dy = delta.y; + s_Size -= (int)dy * 10; + s_Size = Mathf.Clamp(s_Size, 350, 1000); + this.Repaint(); + } + + int xOff = 10; + int yOff = 10; + + EditorGUILayout.Space(); + + yOff = (int)EditorGUILayout.GetControlRect().y; + + for (int i = 0; i < s_Mesh.Count; ++i) + { + Mesh mesh = s_Mesh[i]; + if (mesh == null) + continue; + s_Mesh[i] = ShowMeshItem(mesh, i, new Rect(xOff, yOff, 200, 16)); + yOff += 25; + } + + GUI.Label(new Rect(xOff, yOff, 100, 20), "选择贴图:"); + yOff += 5; + s_TargetTexture = EditorGUI.ObjectField(new Rect(xOff + 100, yOff, 60, 60), s_TargetTexture, typeof(Texture2D), false) as Texture2D; + + Vector2 tilling = new Vector2(s_TillingOffset.width, s_TillingOffset.height); + Vector2 offset = new Vector2(s_TillingOffset.x, s_TillingOffset.y); + tilling = EditorGUI.Vector2Field(new Rect(xOff + 170, yOff - 5, 200, 20), "Tilling", tilling); + offset = EditorGUI.Vector2Field(new Rect(xOff + 170, yOff + 30, 200, 20), "Offset", offset); + s_TillingOffset.x = offset.x; + s_TillingOffset.y = offset.y; + s_TillingOffset.width = tilling.x; + s_TillingOffset.height = tilling.y; + + yOff += 75; + + if (s_HasWarning) + { + EditorGUI.HelpBox(new Rect(xOff, yOff, position.width - 20, 40), s_Warning, MessageType.Warning); + yOff += 45; + } + + + s_Size = EditorGUI.IntSlider(new Rect(xOff, yOff, 200, 20), s_Size, 350, 1000); + EditorGUI.LabelField(new Rect(xOff + 203, yOff, 50, 20), "texels"); + + yOff += 25; + + int previewYOff = yOff; + + if (s_TargetTexture != null) + GUI.DrawTextureWithTexCoords(new Rect(xOff, yOff, s_Size, s_Size), s_TargetTexture, s_TillingOffset, false); + // EditorGUI.DrawPreviewTexture(new Rect(xOff, yOff, s_Size, s_Size), s_TargetTexture/*, s_TillingOffset, false*/); + else + GUI.DrawTextureWithTexCoords(new Rect(xOff, yOff, s_Size, s_Size), Texture2D.blackTexture, s_TillingOffset, false); + + if (s_Selcted != string.Empty && s_Selcted != "") + { + int hashCode = int.Parse(s_Selcted.Substring(0, s_Selcted.LastIndexOf("_"))); + Mesh mesh = GetMeshByHashCode(hashCode); + if (mesh != null) + { + string uvi = s_Selcted.Substring(s_Selcted.LastIndexOf("_") + 1, s_Selcted.Length - s_Selcted.LastIndexOf("_") - 1); + + GUI.Label(new Rect(xOff + s_Size - 200, yOff - 25, 200, 20), mesh.name + "." + uvi, s_AlignRightText); + + yOff += 25; + + if (s_UV != null && s_UV.Length > 0 && s_Mat != null) + { + + if (s_UVMesh == null) + s_UVMesh = new Mesh(); + if (s_UVMesh.vertices == null || s_UVMesh.vertices.Length == 0) + { + Vector3[] vertices = new Vector3[mesh.vertices.Length]; + for (int i = 0; i < vertices.Length; ++i) + { + Vector2 uv = s_UV[i]; + if ((uv.x > 1 || uv.y > 1 || uv.x < 0 || uv.y < 0) && !s_HasWarning) + s_Warning = "这套UV有超过[0,1]范围的值"; + vertices[i] = new Vector3(uv.x, 1 - uv.y, 0); + } + s_UVMesh.vertices = vertices; + s_UVMesh.triangles = mesh.triangles; + s_UVMesh.UploadMeshData(true); + } + s_Mat.SetPass(0); + s_Mat.SetColor("_Color", Color.yellow); + GL.wireframe = true; + Graphics.DrawMeshNow(s_UVMesh, Matrix4x4.TRS(new Vector3(xOff, previewYOff, 0), Quaternion.identity, new Vector3(s_Size, s_Size, 1))); + GL.wireframe = false; + } + } + } + if (s_ReloadUV != null) + { + if (!s_ReloadUV.MoveNext()) + { + s_ReloadUV = null; + } + } + } + + private Mesh ShowMeshItem(Mesh mesh, int index, Rect rect) + { + Mesh newMesh = EditorGUI.ObjectField(rect, mesh, typeof(Mesh), false) as Mesh; + if (newMesh != mesh) + return newMesh; + + float xOff = rect.x + rect.width + 10; + float yOff = rect.y; + + int hashCode = mesh.GetHashCode(); + + xOff = ShowUVButton(1, hashCode, "uv", mesh.uv, new Rect(xOff, yOff, 50, 16)); + xOff = ShowUVButton(2, hashCode, "uv2", mesh.uv2, new Rect(xOff, yOff, 50, 16)); + xOff = ShowUVButton(3, hashCode, "uv3", mesh.uv3, new Rect(xOff, yOff, 50, 16)); + xOff = ShowUVButton(4, hashCode, "uv4", mesh.uv4, new Rect(xOff, yOff, 50, 16)); +#if UNITY_2020 || UNITY_2021 || UNITY_2019 + xOff = ShowUVButton(5, hashCode, "uv5", mesh.uv5, new Rect(xOff, yOff, 50, 20)); + xOff = ShowUVButton(6, hashCode, "uv6", mesh.uv6, new Rect(xOff, yOff, 50, 20)); + xOff = ShowUVButton(7, hashCode, "uv7", mesh.uv7, new Rect(xOff, yOff, 50, 20)); + xOff = ShowUVButton(8, hashCode, "uv8", mesh.uv8, new Rect(xOff, yOff, 50, 20)); +#endif + + return mesh; + } + + private float ShowUVButton(int index, int hashCode, string name, Vector2[] uv, Rect rect) + { + if (uv == null || uv.Length == 0) + { + rect.x += 50; + return rect.x; + } + + bool isThis = s_Selcted == hashCode + "_" + name; +#if UNITY_2020 || UNITY_2021 || UNITY_2019 + Color c = GUI.color; + if (isThis) GUI.color = Color.gray; + if (GUI.Button(rect, name, EditorStyles.miniButtonMid)) +#else + if (GUI.Button(rect, name, isThis ? s_SelectStyle : EditorStyles.miniButtonMid)) +#endif + { + if (isThis) + { + s_UV = null; + s_UVIndex = 0; + s_Selcted = string.Empty; + s_HashCode = 0; + s_UVMesh = null; + s_Warning = ""; + } + else + { + s_UV = uv; + s_UVIndex = index; + s_HashCode = hashCode; + s_Selcted = hashCode + "_" + name; + s_UVMesh = null; + s_Warning = ""; + } + } +#if UNITY_2020 || UNITY_2021 || UNITY_2019 + GUI.color = c; +#endif + + rect.x += 50; + return rect.x; + } + + static Vector2[] GetMeshUV(Mesh mesh, int i) + { + switch (i) + { + case 1: return mesh.uv; + case 2: return mesh.uv2; + case 3: return mesh.uv3; + case 4: return mesh.uv4; +#if UNITY_2020 || UNITY_2021 || UNITY_2019 + case 5: return mesh.uv5; + case 6: return mesh.uv6; + case 7: return mesh.uv7; + case 8: return mesh.uv8; +#endif + default: + Debug.LogError("InValid uv index"); + return null; + } + + } + + static Mesh GetMeshByHashCode(int hashCode) + { + foreach (var mesh in s_Mesh) + { + if (mesh.GetHashCode() == hashCode) + { + return mesh; + } + } + return null; + } + + public static void ForceRepaint() + { + if (s_Editor != null) + { + s_Editor.Repaint(); + s_ReloadUV = ReloadUVNextFrame(); + s_ReloadUV.MoveNext(); + } + } + + // 需要等到导入mesh之后的下一帧才能得到最新的UV数据 + static IEnumerator ReloadUVNextFrame() + { + yield return null; + Mesh mesh = GetMeshByHashCode(s_HashCode); + if (mesh != null) + { + s_UVMesh = null; + s_UV = GetMeshUV(mesh, s_UVIndex); + s_Warning = ""; + } + } + + } + +} \ No newline at end of file -- cgit v1.1-26-g67d0