From 65252cb36d28f94c5ac0a3b8a49b250454eab7e6 Mon Sep 17 00:00:00 2001 From: Genkins Date: Tue, 28 Jul 2020 17:57:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BE=E7=89=87=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Editor/TextureSizeOptTools.cs | 363 ++++++++++++++++++ .../Editor/TextureSizeOptTools.cs.meta | 11 + 2 files changed, 374 insertions(+) create mode 100644 Assets/Scripts/Editor/TextureSizeOptTools.cs create mode 100644 Assets/Scripts/Editor/TextureSizeOptTools.cs.meta diff --git a/Assets/Scripts/Editor/TextureSizeOptTools.cs b/Assets/Scripts/Editor/TextureSizeOptTools.cs new file mode 100644 index 0000000000..fe17600006 --- /dev/null +++ b/Assets/Scripts/Editor/TextureSizeOptTools.cs @@ -0,0 +1,363 @@ +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Collections.Generic; +using System.Text; + +namespace LJ_OptTools +{ + public class TextureSizeOptUtilities + { + public struct TextureSizeData + { + public int width; + public int height; + public SpriteMetaData[] spDatas; + } + + public static bool NeedExtend(Texture2D tex, TextureImporter ti) + { + if (tex == null ||//用packingTag打图集 和 本身就是2的整数幂的 不需要处理 + (ti.textureType == TextureImporterType.Sprite && !string.IsNullOrEmpty(ti.spritePackingTag)) + ) return false; + var oWidth = tex.width; + var oHeight = tex.height; + if (oWidth <= 0 || oHeight <= 0) return false; + + var tarW = (oWidth / 4 + ((oWidth % 4 > 0) ? 1 : 0)) * 4; + var tarH = (oHeight / 4 + ((oHeight % 4 > 0) ? 1 : 0)) * 4; + + return oWidth != tarW || oHeight != tarH; + } + + public static TextureSizeData CalcTextureSize(Texture tex, TextureImporter ti) + { + var ret = new TextureSizeData(); + + var oWidth = tex.width; + var oHeight = tex.height; + #region Get Sprites Data + if (ti.spriteImportMode == SpriteImportMode.Multiple && ti.spritesheet.Length > 0) //精灵表单 + { + var spData = ti.spritesheet; + var length = spData.Length; + ret.spDatas = new SpriteMetaData[length]; + for (var i = 0; i < length; i++) + { + ret.spDatas[i] = spData[i]; + } + } + + #endregion + + //图片大小调整为4的整数倍 + var tarW = (oWidth / 4 + ((oWidth % 4 > 0) ? 1 : 0)) * 4; + var tarH = (oHeight / 4 + ((oHeight % 4 > 0) ? 1 : 0)) * 4; + + ret.width = tarW; + ret.height = tarH; + return ret; + } + + public static bool ExtendTexture( string path) + { + var tex = AssetDatabase.LoadAssetAtPath(path); + var ti = AssetImporter.GetAtPath(path) as TextureImporter; + if (!NeedExtend(tex, ti)) return false; //不是4的整数倍的才进行处理 + + var sizeData = CalcTextureSize(tex, ti); + + var oWidth = tex.width; + var oHeight = tex.height; + + var texName = tex.name; + var texFormat = ti.DoesSourceTextureHaveAlpha() ? TextureFormat.RGBA32 : TextureFormat.RGB24; + + Color[] texPixels = null; + + if (tex.isReadable) + { + texPixels = tex.GetPixels(0, 0, oWidth, oHeight); + } + else + { + Texture2D tmpTex = null; + var tmpRT = RenderTexture.GetTemporary(oWidth, oHeight, 0, RenderTextureFormat.ARGB32); + Graphics.Blit(tex, tmpRT); + Resources.UnloadAsset(tex); + RenderTexture.active = tmpRT; + tmpTex = new Texture2D(oWidth, oHeight, TextureFormat.ARGB32, false); + tmpTex.ReadPixels(new Rect(0, 0, oWidth, oHeight), 0, 0); + tmpTex.Apply(false, false); + RenderTexture.active = null; + RenderTexture.ReleaseTemporary(tmpRT); + texPixels = tmpTex.GetPixels(0, 0, oWidth, oHeight); + Object.DestroyImmediate(tmpTex); + } + + var tarW = sizeData.width; + var tarH = sizeData.height; + + var newTex = new Texture2D(tarW, tarH, texFormat, false, true); + var defaultPixels = new Color32[tarW * tarH]; + for (int j = 0, jmax = tarH * tarW; j < jmax; ++j) + { + defaultPixels[j] = Color.clear; + } + newTex.SetPixels32(defaultPixels); + newTex.Apply(true, false); + + + newTex.SetPixels(0, 0, oWidth, oHeight, texPixels); + newTex.Apply(true, false); + + var ext = Path.GetExtension(path).ToLower(); + + switch (ext) + { + case ".png": + File.WriteAllBytes(path, newTex.EncodeToPNG()); + break; + case ".jpg": + File.WriteAllBytes(path, newTex.EncodeToJPG()); + break; + case ".tga": + File.WriteAllBytes(path, newTex.EncodeToTGA()); + break; + } + Object.DestroyImmediate(newTex); + AssetDatabase.ImportAsset(path); + + ti = AssetImporter.GetAtPath(path) as TextureImporter; + + ti.spriteImportMode = SpriteImportMode.Multiple; + if (sizeData.spDatas == null || sizeData.spDatas.Length < 1) + { + var spData = new SpriteMetaData[1]; + spData[0].name = texName; + spData[0].rect = new Rect(0f, 0f, oWidth, oHeight); + spData[0].border = Vector4.zero; + spData[0].alignment = 0; + ti.spritesheet = spData; + } + else + { + var newSPSheet = new SpriteMetaData[sizeData.spDatas.Length]; + for (int i = 0; i < sizeData.spDatas.Length; i++) + { + newSPSheet[i] = sizeData.spDatas[i]; + } + ti.spritesheet = newSPSheet; + } + AssetDatabase.WriteImportSettingsIfDirty(path); + AssetDatabase.ImportAsset(path); + return true; + } + + public static void SettingPlantformTex(TextureImporter ti, TextureImporterPlatformSettings setting, bool useCrunched, bool pot) + { + + if (!setting.overridden) + { + setting.overridden = true; + } + //带透明通道 压缩格式测试完更改 + if (ti.DoesSourceTextureHaveAlpha()) + { + if (useCrunched) + { + if (setting.format != TextureImporterFormat.ETC2_RGBA8Crunched) + setting.format = TextureImporterFormat.ETC2_RGBA8Crunched; + } + else + { + if (setting.format != TextureImporterFormat.ASTC_RGBA_5x5) + setting.format = TextureImporterFormat.ASTC_RGBA_5x5; + } + + } + else //不带透明通道 + { + if (useCrunched) + { + if (pot && setting.format != TextureImporterFormat.ETC_RGB4Crunched) + setting.format = TextureImporterFormat.ETC_RGB4Crunched; + else + setting.format = TextureImporterFormat.ETC2_RGBA8Crunched; + } + else + { + if (setting.format != TextureImporterFormat.ASTC_RGB_5x5) + setting.format = TextureImporterFormat.ASTC_RGB_5x5; + } + } + + if (setting.compressionQuality < 100) + { + setting.compressionQuality = 100; + } + + } + + public static void SetTextureFormat( string path, bool useCrunched) + { + if (string.IsNullOrEmpty(path)) return; + var ti = AssetImporter.GetAtPath(path) as TextureImporter; + if (ti == null) + { + Debug.LogWarning("Can load TextureImporter:" + path); + return; + } + if (ti.textureShape != TextureImporterShape.Texture2D) + { + return; + } + var pAndSetting = ti.GetPlatformTextureSettings("Android"); + var piPSetting = ti.GetPlatformTextureSettings("iPhone"); + var tex = AssetDatabase.LoadAssetAtPath(path); + bool pot = Mathf.IsPowerOfTwo(tex.width) && Mathf.IsPowerOfTwo(tex.height); + SettingPlantformTex(ti, pAndSetting, useCrunched,pot); + ti.SetPlatformTextureSettings(pAndSetting); + SettingPlantformTex(ti, piPSetting, useCrunched, pot); + ti.SetPlatformTextureSettings(piPSetting); + + AssetDatabase.WriteImportSettingsIfDirty(path); + } + + } + + + public class TextureSizeOptTool + { + [MenuItem("Tools/图片优化/优化选中文件夹中的图片-ASTC", priority = 1)] + public static void OnMenuItem_ASTC() + { + OptUITexSelectTex(false); + } + + [MenuItem("Tools/图片优化/优化选中文件夹中的图片-Crunched", priority = 2)] + public static void OnMenuItem_Crunched() + { + OptUITexSelectTex(true); + } + + public static void OptUITexSelectTex(bool useCrunched) + { + + var guids = Selection.assetGUIDs; + var filePaths = new List(); + foreach (var id in guids) + { + var path = AssetDatabase.GUIDToAssetPath(id); + //可判断文件是否存在 + if (File.Exists(path)) + { + if (!filePaths.Contains(path)) + filePaths.Add(path); + + } //可判断文件路径是否存在 + else if (Directory.Exists(path)) + { + var subFileGuids = AssetDatabase.FindAssets("t:Texture", new string[] { path }); + if (subFileGuids != null && subFileGuids.Length > 0) + { + foreach (var subId in subFileGuids) + { + var subPath = AssetDatabase.GUIDToAssetPath(subId); + if (!filePaths.Contains(subPath)) + filePaths.Add(subPath); + } + } + } + } + + if (filePaths.Count < 1) return; + + for (int i = 0; i < filePaths.Count; i++) + { + string path = filePaths[i]; + EditorUtility.DisplayProgressBar( + string.Format("Opt UI Texture({0}/{1})", i, filePaths.Count) + , path + , i * 1f / filePaths.Count + ); + TextureSizeOptUtilities.ExtendTexture( path); + TextureSizeOptUtilities.SetTextureFormat(path, useCrunched); + } + AssetDatabase.Refresh(); + AssetDatabase.SaveAssets(); + + EditorUtility.ClearProgressBar(); + } + + [MenuItem("Tools/图片优化/检查ManagedResources中所有图片格式", priority = 0)] + public static void OnMenuItem_Check() + { + var guid = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/ManagedResources" }); + List floders = new List(); + int errorTexCount = 0; + for (int i = 0; i < guid.Length; i++) + { + string id = guid[i]; + var path = AssetDatabase.GUIDToAssetPath(id); + + if ( + path.StartsWith("Assets/ManagedResources/Atlas") + ) continue; + + EditorUtility.DisplayProgressBar( + string.Format("Check Texture({0}/{1})", i, guid.Length) + , path + , i * 1f / guid.Length + ); + var floder = Path.GetDirectoryName(path); + var ti = AssetImporter.GetAtPath(path) as TextureImporter; + if (ti == null) + { + //Debug.LogError("No TextureImporter:" + path); + continue; + } + var tex = AssetDatabase.LoadAssetAtPath(path); + + var pAndSetting = ti.GetPlatformTextureSettings("Android"); + var piPSetting = ti.GetPlatformTextureSettings("iPhone"); + + if (!pAndSetting.overridden || !piPSetting.overridden) + { + if (!floders.Contains(floder)) floders.Add(floder); + ++errorTexCount; + continue; + } + + if (pAndSetting.format < TextureImporterFormat.ASTC_RGB_4x4 || piPSetting.format < TextureImporterFormat.ASTC_RGB_4x4) + { + if (!floders.Contains(floder)) floders.Add(floder); + ++errorTexCount; + continue; + } + + if (tex.width % 4 != 0 || tex.height % 4 != 0) + { + if (!floders.Contains(floder)) floders.Add(floder); + ++errorTexCount; + continue; + } + } + if (floders.Count > 0) + { + Debug.Log("Error Tex Count:" + errorTexCount); + StringBuilder sb = new StringBuilder(); + foreach (var f in floders) + { + sb.AppendLine(f); + } + Debug.Log(sb.ToString()); + } + EditorUtility.ClearProgressBar(); + } + + } + + + +} diff --git a/Assets/Scripts/Editor/TextureSizeOptTools.cs.meta b/Assets/Scripts/Editor/TextureSizeOptTools.cs.meta new file mode 100644 index 0000000000..00744761a6 --- /dev/null +++ b/Assets/Scripts/Editor/TextureSizeOptTools.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0b25c9e7b8af7f49a106f68f3d14da5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: