前言
前段時間給項目壓圖,上千張圖片都是一張張手動壓的,累的要死還沒有意義,於是就萌生了做一個unity壓圖插件的想法。功能邏輯不是很複雜,因爲是第一次研究EditorGUI,大概有一半時間都用在製作插件界面上了。
正文
界面效果:
點擊菜單欄中的 圖片壓縮->打開工具,會彈出插件的界面。
Talk is cheap. Show me the code.
代碼如下:
using System.Collections;
using UnityEngine;
using UnityEditor;
using System.IO;
public class CompressTextureHelper : EditorWindow
{
private enum Platform
{
Android,
iPhone,
Standalone,
WebGL
}
private enum CompressMode
{
普通壓縮, //最保守的壓縮,選擇比最大邊大一號的size壓縮,效果可能會不明顯
智能壓縮, //選擇最大邊接近的size,比普通壓縮壓縮力度大
根據面積壓縮, //根據面積壓縮,選擇比自己面積大一號的,比較保守
根據面積強力壓縮 //根據面積壓縮,選擇與自己最接近的
}
private CompressMode mode = CompressMode.普通壓縮;
private bool isReset;
private bool isAndroid;
private bool isIOS;
private bool isStandalone;
private bool isWebGL;
private TextureImporterFormat format = TextureImporterFormat.ASTC_RGB_6x6;
private TextureImporterPlatformSettings settings;
//存儲路徑
static ArrayList ImagePathlist;
[MenuItem("圖片壓縮/打開工具")]
static void Init()
{
GetWindow(typeof(CompressTextureHelper));
}
private void Awake()
{
settings = new TextureImporterPlatformSettings();
settings.overridden = true;
//settings.resizeAlgorithm = TextureResizeAlgorithm.Mitchell;
//settings.textureCompression = TextureImporterCompression.Uncompressed;
//settings.compressionQuality = 100;
//settings.crunchedCompression = true;
//settings.allowsAlphaSplitting = true;
//settings.androidETC2FallbackOverride = AndroidETC2FallbackOverride.UseBuildSettings;
}
//界面
void OnGUI()
{
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUI.DropShadowLabel(new Rect(0, -5, position.width, 20), "一鍵壓縮工具v1.0");
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(isReset); //與end呼應,中間的都灰色禁用
//GUI.enabled = isReset; //和上面功能類似,結束位置用GUI.enabled = true;
mode = (CompressMode)EditorGUILayout.EnumPopup("壓縮模式", mode);
EditorGUILayout.Space();
format = (TextureImporterFormat)EditorGUILayout.EnumPopup("壓圖格式", format);
EditorGUILayout.Space();
EditorGUI.EndDisabledGroup();
//GUI.enabled = true;
EditorGUILayout.LabelField("壓縮平臺:");
//EditorGUILayout.BeginHorizontal(); //開始水平佈局
isAndroid = EditorGUILayout.Toggle("Android", isAndroid);
isIOS = EditorGUILayout.Toggle("IOS", isIOS);
isStandalone = EditorGUILayout.Toggle("PC,Mac&Linux", isStandalone);
isWebGL = EditorGUILayout.Toggle("WebGL", isWebGL);
//EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
isReset = EditorGUILayout.Toggle("還原爲導入時默認格式", isReset);
EditorGUILayout.Space();
if (GUILayout.Button("一鍵壓縮"))
{
CompressorIma();
}
EditorGUILayout.Space();
if (GUILayout.Button("單個文件夾壓縮"))
{
CompressorIma1();
}
EditorGUILayout.Space();
if (GUILayout.Button("選中圖片壓縮"))
{
CompressorIma2();
}
}
//獲取所有圖片路徑並保存
void GetDirs(string path1)
{
foreach (string path in Directory.GetFiles(path1))
{
//獲取所有文件夾中後綴符合要求對象的路徑
if (System.IO.Path.GetExtension(path) == ".jpg" || System.IO.Path.GetExtension(path) == ".png" || System.IO.Path.GetExtension(path) == ".JPG" || System.IO.Path.GetExtension(path) == ".PNG")
{
ImagePathlist.Add(path.Substring(path.IndexOf(path1)));
}
}
if (Directory.GetDirectories(path1).Length > 0) //遍歷所有文件夾
{
foreach (string path11 in Directory.GetDirectories(path1))
{
GetDirs(path11);
}
}
}
//處理資源
void opImage(string path)
{
TextureImporter ti = (TextureImporter)TextureImporter.GetAtPath(path);
Texture texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
int size = 1024;
GetSize(texture,ref size);
ChoosePlatformAndHandleIma(ti, size);
}
//一鍵壓縮
void CompressorIma()
{
if (!JudgeChoose())
return;
if (ImagePathlist == null)
{
ImagePathlist = new ArrayList();
}
else
{
ImagePathlist.Clear();
}
GetDirs("Assets");
bool temp = EditorUtility.DisplayDialog("提示", "一共需要處理" + ImagePathlist.Count + "張圖片", "確定", "取消");
if (temp)
{
EditorUtility.DisplayProgressBar("進度", "0/" + ImagePathlist.Count, 0);
for (int i = 0; i < ImagePathlist.Count; i++)
{
opImage((string)ImagePathlist[i]);
EditorUtility.DisplayProgressBar("進度", (i + 1) + "/" + ImagePathlist.Count, ((i + 1) / (float)ImagePathlist.Count));
}
EditorUtility.ClearProgressBar();
}
else
{
return;
}
}
//單個文件夾壓縮
void CompressorIma1()
{
if (!JudgeChoose())
return;
object[] selection = (object[])Selection.objects;
//判斷是否有對象被選中 並且是一個對象 不帶後綴的
if (selection.Length != 1)
{
EditorUtility.DisplayDialog("提示", "請選擇要壓縮的文件夾!(要在Project視窗的右側選取)", "確定");
return;
}
string objPath = AssetDatabase.GetAssetPath((Object)selection[0]);
if (objPath.Contains("."))
{
EditorUtility.DisplayDialog("提示", "不是文件夾,請重現選取!(要在Project視窗的右側選取)", "確定");
return;
}
string fullPath = objPath;
if (ImagePathlist == null)
{
ImagePathlist = new ArrayList();
}
else
{
ImagePathlist.Clear();
}
GetDirs(fullPath);
bool temp = EditorUtility.DisplayDialog("提示", "一共需要處理" + ImagePathlist.Count + "張圖片", "確定", "取消");
if (temp)
{
EditorUtility.DisplayProgressBar("進度", "0/" + ImagePathlist.Count, 0);
for (int i = 0; i < ImagePathlist.Count; i++)
{
opImage((string)ImagePathlist[i]);
EditorUtility.DisplayProgressBar("進度", (i + 1) + "/" + ImagePathlist.Count, ((i + 1) / (float)ImagePathlist.Count));
}
EditorUtility.ClearProgressBar();
}
else
{
return;
}
}
//壓縮選中圖片
void CompressorIma2()
{
if (!JudgeChoose())
return;
if (ImagePathlist == null)
{
ImagePathlist = new ArrayList();
}
else
{
ImagePathlist.Clear();
}
object[] selection = (object[])Selection.objects;
if (selection.Length == 0)
{
EditorUtility.DisplayDialog("提示", "請選中要壓縮的圖片!", "確定");
return;
}
foreach (Object obj in selection)
{
string objPath = AssetDatabase.GetAssetPath(obj);
if (objPath.EndsWith(".jpg") || objPath.EndsWith(".png") || objPath.EndsWith(".JPG") || objPath.EndsWith(".PNG"))
{
ImagePathlist.Add(objPath);
}
else
{
EditorUtility.DisplayDialog("提示", "請選擇正確的圖片格式!", "確定");
return;
}
}
if (ImagePathlist.Count > 0)
{
bool temp = EditorUtility.DisplayDialog("提示", "一共需要處理" + ImagePathlist.Count + "張圖片", "確定", "取消");
if (temp)
{
EditorUtility.DisplayProgressBar("進度", "0/" + ImagePathlist.Count, 0);
for (int i = 0; i < ImagePathlist.Count; i++)
{
opImage((string)ImagePathlist[i]);
EditorUtility.DisplayProgressBar("進度", (i + 1) + "/" + ImagePathlist.Count, ((i + 1) / (float)ImagePathlist.Count));
}
EditorUtility.ClearProgressBar();
}
else
{
return;
}
}
}
void GetSize(Texture texture,ref int size)
{
if (isReset)
{
size = 2048;
return;
}
if(mode != CompressMode.根據面積壓縮 && mode != CompressMode.根據面積強力壓縮)
{
float judge = texture.width >= texture.height ? texture.width : texture.height;
if (judge <= 32)
{
size = 32;
}
else if (judge <= 64)
{
size = 64;
}
else if (judge <= 128)
{
size = 128;
}
else if (judge <= 256)
{
size = 256;
}
else if (judge <= 512)
{
size = 512;
}
else if (judge <= 1024)
{
size = 1024;
}
else if (judge <= 2048)
{
size = 2048;
}
else if (judge <= 4096)
{
size = 4096;
}
else if (judge <= 8192)
{
size = 8192;
}
else
{
size = 1024;
}
if (mode == CompressMode.智能壓縮)
{
if (size - judge > judge - size / 2)
size /= 2;
}
return;
}
int texArea = texture.width * texture.height;
if (texArea <= 32 * 32)
{
size = 32;
}
else if (texArea <= 64 * 64)
{
size = 64;
}
else if (texArea <= 128 * 128)
{
size = 128;
}
else if (texArea <= 256 * 256)
{
size = 256;
}
else if (texArea <= 512 * 512)
{
size = 512;
}
else if (texArea <= 1024 * 1024)
{
size = 1024;
}
else if (texArea <= 2048 * 2048)
{
size = 2048;
}
else if (texArea <= 4096 * 4096)
{
size = 4096;
}
else if (texArea <= 8192 * 8192)
{
size = 8192;
}
else
{
size = 1024;
}
if (mode == CompressMode.根據面積強力壓縮)
{
if (size * size - texArea > texArea - size * size / 2)
size /= 2;
Debug.Log(size);
}
}
//根據選擇的平臺處理圖片
void ChoosePlatformAndHandleIma(TextureImporter ti,int size)
{
settings.maxTextureSize = size;
if (isReset)
{
settings.overridden = false;
format = TextureImporterFormat.Automatic;
}
settings.format = format;
if (isAndroid)
{
settings.name = Platform.Android.ToString();
HandleIma(ti);
}
if (isIOS)
{
settings.name = Platform.iPhone.ToString();
HandleIma(ti);
}
if (isStandalone)
{
settings.name = Platform.Standalone.ToString();
HandleIma(ti);
}
if (isWebGL)
{
settings.name = Platform.WebGL.ToString();
HandleIma(ti);
}
}
//處理圖片
void HandleIma(TextureImporter ti)
{
ti.SetPlatformTextureSettings(settings);
ti.SaveAndReimport();
}
//不選擇輸出平臺提醒
bool JudgeChoose()
{
if (!isAndroid && !isIOS && !isStandalone && !isWebGL)
{
EditorUtility.DisplayDialog("提示", "請勾選要壓縮的平臺!", "確定");
return false;
}
return true;
}
}