using System.Net; using System.Linq; using UnityEditor; using UnityEngine; using UnityEngine.U2D; using UnityEditor.U2D; using System.Collections.Generic; using BF; using System.IO; using System; namespace BFEditor.Resource { public static class MainAtlasTools { private static HashSet waitHashSet = new HashSet(); const string ATLAS_PATH = "Assets/arts/atlas"; const string SPRITE_PATH = "Assets/arts/textures"; const string MONSTER_FOLDER_PATH = "Assets/arts/models/characters"; const string BATTLE_PET_FOLDER_PATH = "Assets/arts/models/battle"; public static void UpdateMainAtlas() { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget); Debug.Log("[bfinfo]更新图集..."); BFEditorUtils.EnsureDirPathExists(ATLAS_PATH); string[] dirList = { "/ui", "/icon" }; foreach (var str in dirList) { UpdateAtlas(SPRITE_PATH + str); } DeleteUselessAtlas(); waitHashSet.Clear(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); watch.Stop(); Debug.Log("[bfinfo]UpdateMainAtlas,耗时: " + BFEditorUtils.GetTimeStr(watch.ElapsedMilliseconds)); } public static void UpdateAtlas(string path) { path = path.Replace('\\', '/'); var dirs = Directory.GetDirectories(path); for (var i = 0; i < dirs.Length; i++) { UpdateAtlas(dirs[i]); } EditorUtility.DisplayProgressBar("提示", "正在更新 " + path, 1); var sprites = GetSprites(path); if (sprites.Count > 0) { // unity spriteAtlas图集 var spriteAtlas = EnsureSpriteAtlas(path); EditorUtility.SetDirty(spriteAtlas); // 项目加载图片所用的atlas var atlas = EnsureAtlas(path); atlas.Clear(); // 排个序 sprites.Sort((x, y) => x.CompareTo(y)); for (var i = 0; i < sprites.Count; i++) { var sprite = AssetDatabase.LoadAssetAtPath(sprites[i]); atlas.AddSprite(sprite); } EditorUtility.SetDirty(atlas); } EditorUtility.ClearProgressBar(); } public static Atlas EnsureAtlas(string spriteDirPath) { var index = spriteDirPath.LastIndexOf("/"); var atlasName = spriteDirPath.Substring(index + 1, spriteDirPath.Length - index - 1); var relativePath = spriteDirPath.Substring(7, index - 7).Remove(0, 14); var atlasDir = ATLAS_PATH + "/" + relativePath; BFEditorUtils.EnsureDirPathExists(atlasDir); var atlasPath = atlasDir + "/" + atlasName + ".asset"; if (!File.Exists(atlasPath)) { AssetDatabase.CreateAsset(ScriptableObject.CreateInstance(), atlasPath); } return AssetDatabase.LoadAssetAtPath(atlasPath, typeof(Atlas)) as Atlas; } public static SpriteAtlas EnsureSpriteAtlas(string spriteDirPath) { var index = spriteDirPath.LastIndexOf("/"); var spriteAtlasName = spriteDirPath.Substring(index + 1, spriteDirPath.Length - index - 1); var relativePath = spriteDirPath.Substring(7, index - 7).Remove(0, 14); var spriteAtlasDir = ATLAS_PATH + "/" + relativePath; BFEditorUtils.EnsureDirPathExists(spriteAtlasDir); var spriteAtlasPath = spriteAtlasDir + "/" + spriteAtlasName + ".spriteatlas"; if (!File.Exists(spriteAtlasPath)) { SpriteAtlas atlas = new SpriteAtlas(); SpriteAtlasTextureSettings textureSetting = new SpriteAtlasTextureSettings() { readable = false, generateMipMaps = false, sRGB = true, filterMode = FilterMode.Bilinear, }; atlas.SetTextureSettings(textureSetting); SpriteAtlasPackingSettings packingSettings = new SpriteAtlasPackingSettings() { enableTightPacking = false, padding = 4 }; atlas.SetPackingSettings(packingSettings); TextureImporterPlatformSettings platformSettingAndroid = new TextureImporterPlatformSettings() { name = "Android", overridden = true, maxTextureSize = 2048, format = TextureImporterFormat.ETC2_RGBA8, compressionQuality = 50, }; atlas.SetPlatformSettings(platformSettingAndroid); TextureImporterPlatformSettings platformSettingIphone = new TextureImporterPlatformSettings() { name = "iPhone", overridden = true, maxTextureSize = 2048, format = TextureImporterFormat.ASTC_6x6, compressionQuality = 50, }; atlas.SetPlatformSettings(platformSettingIphone); // 将文件夹添加到图集里 UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(spriteDirPath, typeof(UnityEngine.Object)); atlas.Add(new[] {obj}); AssetDatabase.CreateAsset(atlas, spriteAtlasPath); } return AssetDatabase.LoadAssetAtPath(spriteAtlasPath, typeof(SpriteAtlas)) as SpriteAtlas; } static List GetSprites(string path) { var result = new List(); var dirInfo = new DirectoryInfo(path); var files = dirInfo.GetFiles(); if (files.Length != 0) { foreach (var file in files) { if (".png".IndexOf(file.Extension.ToLower(), StringComparison.Ordinal) >= 0) { var resPath = "Assets" + file.FullName.Remove(0, Application.dataPath.Length); result.Add(resPath); } } } return result; } static void DeleteUselessAtlas() { const string START = "Assets/arts/atlas"; const string END = ".asset"; const string NEW_STAER = "Assets/arts/textures"; var atlasPaths = BFEditorUtils.GetAssetPathsWithSuffix(ATLAS_PATH, ".asset"); foreach (var item in atlasPaths) { var relativePath = item.Replace(START, ""); relativePath = relativePath.Replace(END, ""); relativePath = NEW_STAER + relativePath; if (!Directory.Exists(relativePath)) { AssetDatabase.DeleteAsset(item); } } } public static void TryChangeAtlas(string spritePath) { var dirName = Path.GetDirectoryName(spritePath).Replace("\\", "/"); waitHashSet.TryAdd(dirName); } public static void CheckWaitList() { if (Application.isPlaying) { return; } if(waitHashSet.Count <= 0) { return; } SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget); foreach(var dirName in waitHashSet) { UpdateAtlas(dirName); } waitHashSet.Clear(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static void UpdateMonsterAtlas() { Debug.Log("[bfinfo]更新怪物3渲2图集..."); var dirs = Directory.GetDirectories(MONSTER_FOLDER_PATH); for (var i = 0; i < dirs.Length; i++) { var name = dirs[i].Replace("\\", "/").Replace(MONSTER_FOLDER_PATH, ""); if(name.StartsWith("/m00")) { var dirInfo = new DirectoryInfo(dirs[i]); var files = dirInfo.GetFiles(); var resPath = string.Empty; if (files.Length != 0) { foreach (var file in files) { if (file.Extension.ToLower() == ".png" || file.Extension.ToLower() == ".tga") { resPath = "Assets" + file.FullName.Remove(0, Application.dataPath.Length); } } } if (!string.IsNullOrEmpty(resPath)) { EnsureMonsterAtlas(resPath); } } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static void UpdateBattlePetAtlas() { Debug.Log("[bfinfo]更新宠物3渲2图集..."); var dirs = Directory.GetDirectories(BATTLE_PET_FOLDER_PATH); for (var i = 0; i < dirs.Length; i++) { var name = dirs[i].Replace("\\", "/").Replace(BATTLE_PET_FOLDER_PATH, ""); if(name.StartsWith("/pet")) { var dirInfo = new DirectoryInfo(dirs[i]); var files = dirInfo.GetFiles(); var resPath = string.Empty; if (files.Length != 0) { foreach (var file in files) { if (file.Extension.ToLower() == ".png" || file.Extension.ToLower() == ".tga") { resPath = "Assets" + file.FullName.Remove(0, Application.dataPath.Length); } } } if (!string.IsNullOrEmpty(resPath)) { EnsureMonsterAtlas(resPath); } } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static void EnsureMonsterAtlas(string pngPath) { Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(pngPath).OfType().ToArray(); if (sprites == null) { Debug.LogError(pngPath + "生成asset失败"); return; } var atlasPath = pngPath.Substring(0, pngPath.LastIndexOf(".") + 1) + "asset"; if (!File.Exists(atlasPath)) { AssetDatabase.CreateAsset(ScriptableObject.CreateInstance(), atlasPath); } SimpleAtlas simpleAtlas = AssetDatabase.LoadAssetAtPath(atlasPath); if (CheckSprite(sprites, simpleAtlas)) { return; } simpleAtlas.Clear(); int count = sprites.Length; for (int i = 0; i < count; i++) { simpleAtlas.AddSprite(sprites[i]); } EditorUtility.SetDirty(simpleAtlas); } public static bool CheckSprite(Sprite[] sprites, SimpleAtlas simpleAtlas) { int count = sprites.Length; for (int i = 0; i < count; i++) { if (simpleAtlas.GetSprite(i) != sprites[i]) { return false; } } return true; } } }