源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

653 lines
20 KiB

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 TextureSizeChecker : EditorWindow
{
private static TextureSizeChecker instance;
List<TextureInfo> _infoList = new List<TextureInfo>();
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 = 200;
static int _foreceHight = 23;
static string splitChar = "\t";
static string _ignore = "Tools,Fonts";
static string[] formatOption = new string[] { "CSV", "xls","txt" };
static int indexOfFormat;
static string[] sortOption = new string[] { "尺寸最大值", "文件体积"};
static int indexOfSort;
static bool _isSotrUp;
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;
[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("UI目录"))
{
_pathRoot = Application.dataPath + "/LuaFramework/AssetBundleRes/ui";
}
if (GUILayout.Button("资源目录"))
{
_pathRoot = Application.dataPath + "/LuaFramework/AssetBundleRes";
}
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
_isCheckEmpty = EditorGUILayout.Toggle("是否检查空白像素", _isCheckEmpty);
EditorGUILayout.HelpBox("检查图片中是否有多余的空白像素并且输出更多信息\n勾选检查将会变慢",MessageType.Info);
if (_isCheckEmpty)
{
_ignore_effect = true;
_ignore_effect = EditorGUILayout.Toggle("是否忽略特效图片", _ignore_effect);
EditorGUILayout.HelpBox("勾选将会在检查空白像素的时候忽略路径中带有 'effect' 的图片\n因为特效贴图有空白像素属于正常现象", MessageType.Info);
}
else
{
_ignore_effect = false;
}
EditorGUILayout.Space();
EditorGUILayout.Space();
indexOfFormat = EditorGUILayout.Popup("储存格式", indexOfFormat, formatOption);
_saveType = (SaveType)indexOfFormat;
if (_saveType == SaveType.csv)
{
splitChar = ",";
}
else if(_saveType == SaveType.xls)
{
splitChar = "\t";
}
else if(_saveType == SaveType.txt)
{
splitChar = "\r\n";
}
indexOfSort = EditorGUILayout.Popup("排序关键字", indexOfSort, sortOption);
_isSotrUp = EditorGUILayout.Toggle("升序", _isSotrUp);
if(_isSotrUp)
{
EditorGUILayout.HelpBox("升序排列", MessageType.Info);
}
else
{
EditorGUILayout.HelpBox("降序排列", MessageType.Info);
}
EditorGUILayout.Space();
EditorGUILayout.Space();
titleStr = "尺寸最大值" + splitChar + "尺寸"+splitChar + "尺寸大小" + splitChar + "文件体积" + splitChar + "是否有空余像素" + splitChar + "非空范围X" + splitChar + "非空范围Y" + splitChar + "特效文件NPOT"+splitChar+"路径";
_rate = EditorGUILayout.IntField("查找文件速度(文件数/帧)", _rate);
_rateImage = EditorGUILayout.IntField("检查文件速度(文件数/帧)", _rateImage);
if (GUILayout.Button("转换"))
{
EditorCoroutineRunner.StartEditorCoroutine(Conver());
}
}
class TextureInfo
{
public Bitmap texture;
public string fileName;
public Vector2 size;
/// <summary>
/// 文件大小,体积
/// </summary>
public double volume;
/// <summary>
/// 图片尺寸,面积
/// </summary>
public int area;
/// <summary>
/// 是否有空余的像素
/// </summary>
public bool hasEmptyArea;
public int emptyAreaX_start;
public int emptyAreaX_end;
public int emptyAreaY_start;
public int emptyAreaY_end;
public bool isEffect;
public bool POT;
public int maxSize;
public TextureInfo(Bitmap pic, string clearPath)
{
texture = pic;
//fileName = clearPath.Replace("Assets", Application.dataPath);
fileName = clearPath;
size = new Vector2(pic.Width, pic.Height);
var fileInfo = new FileInfo(fileName);
volume = System.Math.Ceiling(fileInfo.Length / 1024.0);
area = pic.Width * pic.Height;
isEffect = clearPath.ToLower().Contains("effect");
POT = Get2Flag(pic.Width) && Get2Flag(pic.Height);
maxSize = Mathf.Max(pic.Height, pic.Width);
}
public string GetInfo()
{
string str = "";
str += maxSize + splitChar;
str += size.x + "x" + size.y + splitChar;
str += area + splitChar;
str += volume + " KB" + splitChar;
if(_isCheckEmpty)
{
str += hasEmptyArea + splitChar;
if (hasEmptyArea)
{
str += emptyAreaX_start + "~" + emptyAreaX_end + splitChar;
str += emptyAreaY_start + "~" + emptyAreaY_end + splitChar;
}
else
{
str += splitChar;
str += splitChar;
}
}
else
{
str += splitChar;
str += splitChar;
str += splitChar;
}
if(isEffect)
{
str += POT + splitChar;
}
else
{
str += splitChar;
}
str += fileName + splitChar;
//str += "\n";
return str;
}
}
int CompareDinosBySize(TextureInfo t1, TextureInfo t2)
{
if (indexOfSort == 0)
{
if (t1.area == t2.area)
{
//面积相同比较文件体积
if(_isSotrUp)
{
return (int)(t1.volume - t2.volume);
}
else
{
return (int)(t2.volume - t1.volume);
}
}
else
{
//尺寸大的优先
float max1 = Mathf.Max(t1.size.x, t1.size.y);
float max2 = Mathf.Max(t2.size.x, t2.size.y);
if(_isSotrUp)
{
return (int)(max2 - max1);
}
else
{
return (int)(max1 - max2);
}
}
}
else if(indexOfSort == 1)
{
if(_isSotrUp)
{
return (int)(t2.volume - t1.volume);
}
else
{
return (int)(t1.volume - t2.volume);
}
}
return 1;
}
bool IsIgonrePath(string path)
{
foreach(var flag in _ignore_list)
{
if(path.ToLower().Contains(flag.ToLower()))
{
return true;
}
}
return false;
}
IEnumerator Conver()
{
_infoList.Clear();
var files = Directory.GetFiles(_pathRoot, "*.png*", SearchOption.AllDirectories);
List<string> texturePahts = 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.EndsWith(".png"))
{
var clearPaht = file.Replace(Application.dataPath, "Assets");
texturePahts.Add(clearPaht);
//Debug.Log(clearPaht);
EditorUtility.DisplayProgressBar("查找文件中的PNG···", file, count / files.Length);
}
}
var files2 = Directory.GetFiles(_pathRoot, "*.jpg*", SearchOption.AllDirectories);
count = 0;
foreach (var file in files2)
{
count++;
if (count % _rate == 0)
{
yield return 1;
}
if (IsIgonrePath(file))
{
continue;
}
if (file.EndsWith(".jpg"))
{
var clearPaht = file.Replace(Application.dataPath, "Assets");
texturePahts.Add(clearPaht);
//Debug.Log(clearPaht);
EditorUtility.DisplayProgressBar("查找文件中的JPG···",file, count / files2.Length);
}
}
var files3 = Directory.GetFiles(_pathRoot, "*.tga*", SearchOption.AllDirectories);
count = 0;
foreach (var file in files3)
{
count++;
if (count % _rate == 0)
{
yield return 1;
}
if (IsIgonrePath(file))
{
continue;
}
if (file.EndsWith(".tga"))
{
var clearPaht = file.Replace(Application.dataPath, "Assets");
texturePahts.Add(clearPaht);
//Debug.Log(clearPaht);
EditorUtility.DisplayProgressBar("查找文件中的TGA···", file, count / files3.Length);
}
}
List<string> error_list = new List<string>();
List<string> warning_list = new List<string>();
count = 0;
foreach (var singPath in texturePahts)
{
count++;
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(singPath);
if (texture)
{
try
{
Bitmap pic;
if (singPath.Contains(".tga"))
{
ImageTGA tga = new ImageTGA(singPath);
if(tga.Copy_Error)
{
warning_list.Add(singPath);
}
pic = new Bitmap(tga.Image);
}
else
{
pic = Bitmap.FromFile(singPath) as Bitmap;
}
CheckSingleTexture(pic, singPath);
pic.Dispose();
}
catch (Exception exp)
{
error_list.Add(singPath);
Debug.LogError(singPath + "\n\n" + exp);
}
//var bs = t.EncodeToPNG();
//string lastName = singlePaht.Substring(singlePaht.LastIndexOf("\\"));
//Debug.Log(lastName);
//File.WriteAllBytes(newDir + lastName, bs);
}
if (count % _rateImage == 0)
{
yield return 1;
}
EditorUtility.DisplayProgressBar("检查图片中···(共"+texturePahts.Count+"个)"+count+"/"+texturePahts.Count, singPath, count / texturePahts.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("整理文件中···", info.fileName, count / _infoList.Count);
}
str.Add("以下文件出错");
str.AddRange(error_list);
str.Add("以下文件读取时候出现异常,可能出错");
str.AddRange(warning_list);
EditorUtility.DisplayProgressBar("写入文件中···", "", 0);
string newDir = Application.dataPath.Replace("Assets", "") + "/image_output";
if(_saveType == SaveType.csv)
{
newDir += ".csv";
}
else if(_saveType == SaveType.xls)
{
newDir += ".xls";
}
else if(_saveType == SaveType.txt)
{
newDir += ".txt";
}
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 CheckSingleTexture(Bitmap pic, string path)
{
TextureInfo info = new TextureInfo(pic, path);
_infoList.Add(info);
if (!_isCheckEmpty)
{
return;
}
if(_ignore_effect)
{
if(path.ToLower().Contains("effect"))
{
return;
}
}
Vector2 range_x = new Vector2(1, pic.Width);
Vector2 range_y = new Vector2(1, pic.Height);
bool hasEmpty = false;
//Debug.Log("图片尺寸 " + pic.Width + "," + pic.Width);
bool done = false;
//横轴扫描 从左到右
for (int i = 1; i < pic.Width; i++)
{
if (done)
{
break;
}
for (int j = 1; j < pic.Height; j++)
{
try
{
System.Drawing.Color col = pic.GetPixel(i, j);
// data[i, j] = col;
if (col.A > _alpha_cut_off)
{
range_x.x = i;
//Debug.LogFormat(" 从左到右点 {0},{1},{2}", i, j, col);
hasEmpty = true;
done = true;
break;
}
}
catch
{
Debug.LogErrorFormat("1: {0},{1}", i, j);
}
}
}
done = false;
//横轴扫描 从右到左
for (int i = pic.Width - 1; i > 0; i--)
{
if (done)
{
break;
}
for (int j = 1; j < pic.Height; j++)
{
try
{
System.Drawing.Color col = pic.GetPixel(i, j);
// data[i, j] = col;
if (col.A > _alpha_cut_off)
{
range_x.y = i + 1;
//Debug.LogFormat(" 从右到左点 {0},{1}", i, j);
hasEmpty = true;
done = true;
break;
}
}
catch
{
Debug.LogErrorFormat("2: {0},{1}", i, j);
}
}
}
done = false;
//纵轴扫描 从下到上
for (int i = 1; i < pic.Height; i++)
{
if (done)
{
break;
}
for (int j = 1; j < pic.Width; j++)
{
try
{
System.Drawing.Color col = pic.GetPixel(j, i);
// data[i, j] = col;
if (col.A > _alpha_cut_off)
{
range_y.x = i;
//Debug.LogFormat(" 从下到上点 {0},{1}", j, i);
hasEmpty = true;
done = true;
break;
}
}
catch
{
Debug.LogErrorFormat("3: {0},{1}", i, j);
}
}
}
done = false;
//纵轴扫描 从上到下
for (int i = pic.Height - 1; i > 0; i--)
{
if (done)
{
break;
}
for (int j = 1; j < pic.Width; j++)
{
try
{
System.Drawing.Color col = pic.GetPixel(j, i);
// data[i, j] = col;
if (col.A > _alpha_cut_off)
{
range_y.y = i + 1;
//Debug.LogFormat(" 从上到下点 {0},{1}", j, i);
hasEmpty = true;
done = true;
break;
}
}
catch
{
Debug.LogErrorFormat("4: {0},{1}", i, j);
}
}
}
if (range_x.x > range_x.y)
{
Debug.LogError("查找错误 ");
return;
}
if (range_y.x > range_y.y)
{
Debug.LogError("查找错误 ");
return;
}
range_x.x = Mathf.Clamp(range_x.x, 1, pic.Width);
range_x.y = Mathf.Clamp(range_x.y, 1, pic.Width);
range_y.x = Mathf.Clamp(range_y.x, 1, pic.Height);
range_y.y = Mathf.Clamp(range_y.y, 1, pic.Height);
//Debug.Log(range_x);
//Debug.Log(range_y);
//Debug.LogFormat("最左边的像素:{0},最后边的像素:{1},最上像素:{2},最下的像素:{3}", range_x.x, range_x.y, range_y.x, range_y.y);
info.emptyAreaX_start = (int)range_x.x;
info.emptyAreaY_start = (int)range_y.x;
info.emptyAreaX_end = (int)range_x.y;
info.emptyAreaY_end = (int)range_y.y;
if(range_x.x > 1 || range_x.y < pic.Width)
{
info.hasEmptyArea = true;
}
else if(range_y.x > 1 || range_y.y < pic.Height)
{
info.hasEmptyArea = true;
}
}
void OnSelectionChange()
{
//object[] selection = (object[])Selection.objects;
//Debug.Log(selection .Length);
////判断是否有对象被选中
//if (selection.Length != 1)
// return;
////遍历每一个对象判断不是文件夹
//string objPath = AssetDatabase.GetAssetPath((Object)selection[0]);
//Debug.Log(objPath);
//if( Directory.Exists(objPath) )
//{
// _pathRoot = objPath;
// Repaint();
//}
//else
//{
//}
}
private static void Init()
{
_targetPic = null;
instance = EditorWindow.GetWindow<TextureSizeChecker>("选项");
_pathRoot = Application.dataPath + "/LuaFramework/AssetBundleRes";
instance.position = new Rect(new Vector2(604, 290), new Vector2(650, 400));
}
}