Unity一鍵壓圖插件開發

前言

前段時間給項目壓圖,上千張圖片都是一張張手動壓的,累的要死還沒有意義,於是就萌生了做一個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;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章