com.alicizax.unity.editor.e.../Editor/Postprocessor/Atlas/AtlasProcessor.cs

211 lines
7.0 KiB
C#
Raw Normal View History

2025-03-11 17:46:52 +08:00
// AtlasProcessor.cs
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
public static class AtlasProcessor
{
private static readonly HashSet<string> DirtyAtlas = new HashSet<string>();
private static readonly Dictionary<string, HashSet<string>> AtlasContents =
new Dictionary<string, HashSet<string>>();
public static void ForceRebuildAtlases(AtlasConfiguration config)
{
InitializeAtlasData(config);
ProcessAllSprites(config);
PackAllAtlases(config);
}
private static void InitializeAtlasData(AtlasConfiguration config)
{
AtlasContents.Clear();
var atlasGuids = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { config.atlasOutputPath });
foreach (var guid in atlasGuids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(path);
if (atlas == null) continue;
var atlasName = Path.GetFileNameWithoutExtension(path);
var packed = atlas.GetPackables();
AtlasContents[atlasName] = new HashSet<string>();
foreach (var obj in packed)
{
var assetPath = AssetDatabase.GetAssetPath(obj);
if (!string.IsNullOrEmpty(assetPath))
{
AtlasContents[atlasName].Add(assetPath);
}
}
}
}
private static void ProcessAllSprites(AtlasConfiguration config)
{
var allSprites = AssetDatabase.FindAssets("t:Sprite", new[] { config.rawUIPath });
foreach (var guid in allSprites)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
ProcessSingleSprite(path, config);
}
}
public static void ProcessSingleSprite(string path, AtlasConfiguration config)
{
if (!path.StartsWith(config.rawUIPath)) return;
var importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer == null) return;
ConfigureTextureImporter(importer, config);
AddToAtlas(path, config);
}
private static void ConfigureTextureImporter(TextureImporter importer, AtlasConfiguration config)
{
var changed = false;
var settings = new TextureImporterSettings();
importer.ReadTextureSettings(settings);
if (importer.textureType != TextureImporterType.Sprite)
{
importer.textureType = TextureImporterType.Sprite;
changed = true;
}
if (settings.spriteGenerateFallbackPhysicsShape)
{
settings.spriteGenerateFallbackPhysicsShape = false;
importer.SetTextureSettings(settings);
changed = true;
}
ApplyPlatformSettings(importer, "Android", config.androidFormat, config);
ApplyPlatformSettings(importer, "iPhone", config.iosFormat, config);
ApplyPlatformSettings(importer, "WebGL", config.webglFormat, config);
if (changed) importer.SaveAndReimport();
}
private static void ApplyPlatformSettings(TextureImporter importer, string platform,
TextureImporterFormat format, AtlasConfiguration config)
{
var settings = importer.GetPlatformTextureSettings(platform);
if (!settings.overridden || settings.format != format ||
settings.compressionQuality != config.compressionQuality)
{
settings.overridden = true;
settings.format = format;
settings.compressionQuality = config.compressionQuality;
importer.SetPlatformTextureSettings(settings);
}
}
private static void AddToAtlas(string spritePath, AtlasConfiguration config)
{
var atlasName = GetAtlasName(spritePath, config);
if (string.IsNullOrEmpty(atlasName)) return;
if (!AtlasContents.TryGetValue(atlasName, out var paths))
{
paths = new HashSet<string>();
AtlasContents[atlasName] = paths;
}
if (paths.Add(spritePath)) DirtyAtlas.Add(atlasName);
}
private static string GetAtlasName(string path, AtlasConfiguration config)
{
var relativePath = path.Replace(config.rawUIPath, "").TrimStart('/');
var directory = Path.GetDirectoryName(relativePath);
return directory?.Replace("/", "_");
}
private static void PackAllAtlases(AtlasConfiguration config)
{
foreach (var atlasName in DirtyAtlas)
{
CreateOrUpdateAtlas(atlasName, config);
}
DirtyAtlas.Clear();
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
AssetDatabase.SaveAssets();
}
private static void CreateOrUpdateAtlas(string atlasName, AtlasConfiguration config)
{
if (!System.IO.Directory.Exists(config.atlasOutputPath))
{
Directory.CreateDirectory(config.atlasOutputPath);
}
var path = $"{config.atlasOutputPath}/{atlasName}.spriteatlas";
var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(path) ?? new SpriteAtlas();
ConfigureAtlasSettings(atlas, config);
AddSpritesToAtlas(atlas, AtlasContents[atlasName]);
if (!AssetDatabase.Contains(atlas))
{
AssetDatabase.CreateAsset(atlas, path);
}
else
{
EditorUtility.SetDirty(atlas);
}
}
private static void ConfigureAtlasSettings(SpriteAtlas atlas, AtlasConfiguration config)
{
// Packing Settings
var packingSettings = new SpriteAtlasPackingSettings
{
padding = config.padding,
enableRotation = config.enableRotation,
blockOffset = config.blockOffset
};
atlas.SetPackingSettings(packingSettings);
// Texture Settings
var textureSettings = new SpriteAtlasTextureSettings
{
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear
};
atlas.SetTextureSettings(textureSettings);
// Platform Settings
SetPlatformFormat(atlas, "Android", config.androidFormat, config);
SetPlatformFormat(atlas, "iPhone", config.iosFormat, config);
SetPlatformFormat(atlas, "WebGL", config.webglFormat, config);
}
private static void SetPlatformFormat(SpriteAtlas atlas, string platform,
TextureImporterFormat format, AtlasConfiguration config)
{
var settings = atlas.GetPlatformSettings(platform);
settings.overridden = true;
settings.format = format;
settings.compressionQuality = config.compressionQuality;
atlas.SetPlatformSettings(settings);
}
private static void AddSpritesToAtlas(SpriteAtlas atlas, IEnumerable<string> spritePaths)
{
var packables = new List<Object>();
foreach (var path in spritePaths)
{
var obj = AssetDatabase.LoadAssetAtPath<Object>(path);
if (obj != null) packables.Add(obj);
}
atlas.Add(packables.ToArray());
}
}