summaryrefslogtreecommitdiff
path: root/CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs')
-rw-r--r--CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs421
1 files changed, 421 insertions, 0 deletions
diff --git a/CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs b/CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs
new file mode 100644
index 0000000..3e95eac
--- /dev/null
+++ b/CollectionProj/Assets/Tools/ModelUVViewer/Editor/ModelUVViewer.cs
@@ -0,0 +1,421 @@
+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<MeshFilter>().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<int, string>();
+ 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<ModelUVViewer>() || s_Editor == null)
+#else
+ if (s_Editor == null)
+#endif
+ {
+ s_Editor = GetWindow<ModelUVViewer>();
+ 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<Mesh> s_Mesh = new List<Mesh>();
+
+ 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<int, string> s_MeshToAsset = new Dictionary<int, string>();
+
+ 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();
+ EditorGUILayout.HelpBox("查看模型的UV", MessageType.Info);
+ EditorGUILayout.Space();
+ if(s_HasWarning)
+ {
+ EditorGUILayout.HelpBox(s_Warning, MessageType.Warning);
+ 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;
+
+ 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