using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEngine.UI;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Drawing;
|
|
using System.Text.RegularExpressions;
|
|
using System;
|
|
|
|
public class ModelChecker : EditorWindow
|
|
{
|
|
private static ModelChecker instance;
|
|
List<ModelInfo> _infoList = new List<ModelInfo>();
|
|
|
|
static Texture2D _targetPic;
|
|
static string _pathRoot;
|
|
static float _alpha_cut_off = 0f;
|
|
static int _horizontalSpace = 0;
|
|
static int _verticalSpace = 0;
|
|
static int _rate = 200;
|
|
static int _rateImage = 1;
|
|
static int _foreceHight = 23;
|
|
static string splitChar = "\t";
|
|
static string _ignore = "Tools,Fonts,terrain,effect,action,weapon";
|
|
static string[] formatOption = new string[] { "CSV", "xls", "txt" };
|
|
static int indexOfFormat;
|
|
static string[] sortKey = new string[] { "骨骼数", "面数" ,"顶点数"};
|
|
static int indexOfSortKey;
|
|
static string[] sortType = new string[] { "升序", "降序" };
|
|
static int indexOfSortType = 0;
|
|
static SaveType _saveType = SaveType.csv;
|
|
static bool _ignore_effect = false;
|
|
static Encoding ENCODING = Encoding.GetEncoding("GB2312");
|
|
static string titleStr;
|
|
static bool _isCheckEmpty = true;
|
|
static string[] _ignore_list;
|
|
static string des_end_str; //输出文件的后缀名
|
|
static List<string> error_list = new List<string>();
|
|
static List<string> warning_list = new List<string>();
|
|
static string _guiChecker;
|
|
static int _checkCount=10000;
|
|
bool _tog;
|
|
bool _tog2;
|
|
bool _tog3;
|
|
[MenuItem("Tools/检查模型")]
|
|
static void ShowExcelTools()
|
|
{
|
|
Init();
|
|
instance.Show();
|
|
}
|
|
|
|
enum SaveType
|
|
{
|
|
csv = 0,
|
|
xls,
|
|
txt,
|
|
}
|
|
void OnGUI()
|
|
{
|
|
DrawOptions();
|
|
}
|
|
|
|
static bool Get2Flag(int num)
|
|
{
|
|
if (num < 1) return false;
|
|
return (num & num - 1) == 0;
|
|
}
|
|
|
|
private void DrawOptions()
|
|
{
|
|
|
|
_pathRoot = EditorGUILayout.TextField("指定目录", _pathRoot);
|
|
_ignore = EditorGUILayout.TextField("忽略目录关键字", _ignore);
|
|
EditorGUILayout.HelpBox("检查的时候会忽略有上面关键字的目录,用逗号‘,’分割", MessageType.Info);
|
|
_ignore_list = _ignore.Split(',');
|
|
|
|
if (GUILayout.Button("scene目录"))
|
|
{
|
|
_pathRoot = "Assets/LuaFramework/AssetBundleRes/scene";
|
|
}
|
|
if (GUILayout.Button("资源目录"))
|
|
{
|
|
_pathRoot = "Assets/LuaFramework/AssetBundleRes";
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
indexOfFormat = EditorGUILayout.Popup("储存格式", indexOfFormat, formatOption);
|
|
_saveType = (SaveType)indexOfFormat;
|
|
|
|
|
|
if (_saveType == SaveType.csv)
|
|
{
|
|
splitChar = ",";
|
|
des_end_str = ".csv";
|
|
}
|
|
else if (_saveType == SaveType.xls)
|
|
{
|
|
splitChar = "\t";
|
|
des_end_str = ".xls";
|
|
}
|
|
else if (_saveType == SaveType.txt)
|
|
{
|
|
splitChar = "\r\n";
|
|
des_end_str = ".txt";
|
|
}
|
|
|
|
|
|
indexOfSortKey = EditorGUILayout.Popup("排序关键字", indexOfSortKey, sortKey);
|
|
indexOfSortType = EditorGUILayout.Popup("排序类型", indexOfSortType, sortType);
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
|
|
titleStr = "骨骼数" + splitChar + "定点数" + splitChar + "三角面数" + splitChar + "文件路径";// + splitChar + "是否有空余像素" + splitChar + "非空范围X" + splitChar + "非空范围Y" + splitChar + "特效文件NPOT" + splitChar + "路径";
|
|
|
|
_rate = EditorGUILayout.IntField("查找文件速度(文件数/帧)", _rate);
|
|
EditorGUILayout.IntField("检查文件速度(文件数/帧)", 1);
|
|
EditorGUILayout.HelpBox("因为算法原因,只能一个个检查,无法更改", MessageType.Info);
|
|
if (GUILayout.Button("转换"))
|
|
{
|
|
EditorCoroutineRunner.StartEditorCoroutine(Conver());
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.HelpBox("-----------------------------------以下测试用-------------------------------------",MessageType.Info);
|
|
_guiChecker = EditorGUILayout.TextField("GUID", _guiChecker);
|
|
if(GUILayout.Button("GUID转换地址"))
|
|
{
|
|
Debug.LogError(AssetDatabase.GUIDToAssetPath(_guiChecker));
|
|
}
|
|
_checkCount = EditorGUILayout.IntField("最多检查文件数", _checkCount);
|
|
|
|
}
|
|
|
|
class ModelInfo
|
|
{
|
|
public string filePath;
|
|
public int vertsCount;
|
|
public int trisCount;
|
|
public int bonesCount;
|
|
|
|
public ModelInfo(string clearPath)
|
|
{
|
|
filePath = clearPath;
|
|
}
|
|
public string GetInfo()
|
|
{
|
|
string str = "";
|
|
str += bonesCount + splitChar;
|
|
str += vertsCount + splitChar;
|
|
str += trisCount + splitChar;
|
|
str += filePath + splitChar;
|
|
|
|
//str += "\n";
|
|
return str;
|
|
}
|
|
}
|
|
|
|
int CompareDinosBySize(ModelInfo t1, ModelInfo t2)
|
|
{
|
|
if(indexOfSortKey == 0)
|
|
{
|
|
if(indexOfSortType == 0)
|
|
{
|
|
return t1.bonesCount - t2.bonesCount;
|
|
}
|
|
else
|
|
{
|
|
return t2.bonesCount - t1.bonesCount;
|
|
}
|
|
|
|
}
|
|
else if(indexOfSortKey == 1)
|
|
{
|
|
if(indexOfSortType == 0)
|
|
{
|
|
return t1.trisCount - t2.trisCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
return t2.trisCount - t1.trisCount;
|
|
}
|
|
}
|
|
else if(indexOfSortKey == 2)
|
|
{
|
|
if (indexOfSortType == 0)
|
|
{
|
|
return t1.vertsCount - t2.vertsCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
return t2.vertsCount - t1.vertsCount;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool IsIgonrePath(string path)
|
|
{
|
|
foreach (var flag in _ignore_list)
|
|
{
|
|
if (path.ToLower().Contains(flag.ToLower()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IEnumerator Conver()
|
|
{
|
|
string dateStr = DateTime.Now.Hour.ToString() + "_" + DateTime.Now.Minute.ToString() + "_" + DateTime.Now.Second.ToString();
|
|
string newDir = Application.dataPath.Replace("Assets", "") + "/model_output_" + dateStr + des_end_str;
|
|
try
|
|
{
|
|
if(File.Exists(newDir))
|
|
{
|
|
var test = File.Open(newDir, FileMode.Open);
|
|
test.Close();
|
|
test.Dispose();
|
|
}
|
|
|
|
}
|
|
catch (IOException exp)
|
|
{
|
|
EditorUtility.DisplayDialog("提示", "错误,请先关闭写入目录的文件 ", "好的呢", "");
|
|
Debug.LogError(exp);
|
|
yield break;
|
|
}
|
|
|
|
var files = Directory.GetFiles(_pathRoot.Replace("Assets", Application.dataPath), "*.fbx*", SearchOption.AllDirectories);
|
|
//var files2 = Directory.GetFiles(_pathRoot.Replace("Assets", Application.dataPath), "*.FBX*", SearchOption.AllDirectories);
|
|
List<string> modelPath = new List<string>();
|
|
float count = 0;
|
|
foreach (var file in files)
|
|
{
|
|
|
|
count++;
|
|
if (count % _rate == 0)
|
|
{
|
|
yield return 1;
|
|
}
|
|
if (IsIgonrePath(file))
|
|
{
|
|
continue;
|
|
}
|
|
if (file.ToLower().EndsWith(".fbx") && !file.ToLower().Contains("@"))
|
|
{
|
|
var clearPaht = file.Replace(Application.dataPath,"Assets");
|
|
modelPath.Add(clearPaht);
|
|
if (modelPath.Count > _checkCount)
|
|
{
|
|
break;
|
|
}
|
|
|
|
EditorUtility.DisplayProgressBar("查找文件中的FBX···"+ modelPath.Count, file, count / files.Length);
|
|
|
|
}
|
|
}
|
|
if(!EditorUtility.DisplayDialog("提示", "一共查找到"+ modelPath.Count+ "个文件,是否继续\n因为只能一个个检查,所以数量大会很慢哦\n\n520个文件大概5到10分钟", "继续", "取消"))
|
|
{
|
|
EditorUtility.ClearProgressBar();
|
|
yield break;
|
|
}
|
|
error_list.Clear();
|
|
warning_list.Clear();
|
|
_infoList.Clear();
|
|
count = 0;
|
|
foreach (var singPath in modelPath)
|
|
{
|
|
count++;
|
|
//if(count > 180 && count < 200)
|
|
//{
|
|
|
|
//}
|
|
//else
|
|
//{
|
|
// continue;
|
|
//}
|
|
|
|
try
|
|
{
|
|
CheckSinglModel(singPath);
|
|
}
|
|
catch (Exception exp)
|
|
{
|
|
error_list.Add(singPath);
|
|
Debug.LogError(singPath + "\n\n" + exp);
|
|
}
|
|
|
|
if (count % _rateImage == 0)
|
|
{
|
|
yield return 1;
|
|
}
|
|
EditorUtility.DisplayProgressBar("检查模型中···(共" + modelPath.Count + "个)" + count + "/" + modelPath.Count, singPath, count / modelPath.Count);
|
|
}
|
|
_infoList.Sort(CompareDinosBySize);
|
|
|
|
|
|
|
|
|
|
count = 0;
|
|
List<string> str = new List<string>();
|
|
str.Add(titleStr);
|
|
foreach (var info in _infoList)
|
|
{
|
|
count++;
|
|
str.Add(info.GetInfo());
|
|
//if (count % _rateImage * 30 == 0)
|
|
//{
|
|
// yield return 1;
|
|
//}
|
|
EditorUtility.DisplayProgressBar("整理文件中···", "不想告诉你当前进度·····", count / _infoList.Count);
|
|
}
|
|
str.Add("以下文件出错");
|
|
str.AddRange(error_list);
|
|
str.Add("以下文件读取时候出现异常,可能出错");
|
|
str.AddRange(warning_list);
|
|
EditorUtility.DisplayProgressBar("写入文件中···", "", 0);
|
|
|
|
|
|
if (_infoList.Count > 0)
|
|
{
|
|
try
|
|
{
|
|
File.WriteAllLines(newDir, str.ToArray(), ENCODING);
|
|
}
|
|
catch (IOException exp)
|
|
{
|
|
EditorUtility.ClearProgressBar();
|
|
EditorUtility.DisplayDialog("提示", "错误,请先关闭写入目录的文件 ", "好的呢", "");
|
|
yield break;
|
|
}
|
|
}
|
|
EditorUtility.DisplayDialog("提示", "扫描完成", "GOOD", "");
|
|
EditorUtility.ClearProgressBar();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
void CheckSinglModel(string path)
|
|
{
|
|
path = path.Replace(@"\","/");
|
|
if(path.Contains("@"))
|
|
{
|
|
return;
|
|
}
|
|
ModelInfo info = new ModelInfo(path);
|
|
GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
|
var skm = go.GetComponentInChildren<SkinnedMeshRenderer>();
|
|
if(!skm)
|
|
{
|
|
if(!go.GetComponentInChildren<MeshFilter>())
|
|
{
|
|
warning_list.Add(path);
|
|
return;
|
|
}
|
|
}
|
|
_infoList.Add(info);
|
|
|
|
var fullPath = path.Replace("Assets", Application.dataPath) + ".meta";
|
|
var temp = File.ReadAllBytes(fullPath);
|
|
ModelImporter mi = (ModelImporter)MovieImporter.GetAtPath(path);
|
|
mi.isReadable = true;
|
|
mi.optimizeGameObjects = false;
|
|
EditorUtility.SetDirty(mi);
|
|
mi.SaveAndReimport();
|
|
AssetDatabase.SaveAssets();
|
|
|
|
if(skm == null)
|
|
{
|
|
var skm2 = go.GetComponentInChildren<MeshFilter>();
|
|
if(skm2)
|
|
{
|
|
var mesh = skm2.sharedMesh;
|
|
info.vertsCount = mesh.vertexCount;
|
|
info.trisCount = mesh.triangles.Length / 3;
|
|
info.bonesCount = 0;
|
|
}
|
|
else
|
|
{
|
|
_infoList.Remove(info);
|
|
warning_list.Add(path);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
var mesh = skm.sharedMesh;
|
|
info.vertsCount = mesh.vertexCount;
|
|
info.trisCount = mesh.triangles.Length / 3;
|
|
info.bonesCount = skm.bones.Length;
|
|
}
|
|
//Debug.Log(mesh.vertexCount);
|
|
//Debug.Log(mesh.triangles.Length / 3);
|
|
//Debug.Log("骨骼数量 " + go.GetComponentInChildren<SkinnedMeshRenderer>().bones.Length);
|
|
mi.isReadable = false;
|
|
mi.optimizeGameObjects = true;
|
|
EditorUtility.SetDirty(mi);
|
|
mi.SaveAndReimport();
|
|
|
|
//AssetDatabase.Refresh();
|
|
File.Delete(fullPath);
|
|
File.WriteAllBytes(fullPath, temp);
|
|
}
|
|
|
|
|
|
|
|
void OnSelectionChange()
|
|
{
|
|
|
|
}
|
|
|
|
private static void Init()
|
|
{
|
|
_targetPic = null;
|
|
instance = EditorWindow.GetWindow<ModelChecker>("选项");
|
|
_pathRoot = "Assets/LuaFramework/AssetBundleRes/scene";//object/role/res/model_clothe_101000/model/model_clothe_101000.fbx
|
|
instance.position = new Rect(new Vector2(604, 290), new Vector2(650, 450));
|
|
}
|
|
}
|