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

682 lines
21 KiB
C#
Raw Normal View History

2026-04-20 14:24:54 +08:00
#if UNITY_EDITOR
2025-03-14 16:02:36 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
public static class EditorSpriteSaveInfo
{
2026-04-20 14:24:54 +08:00
private static readonly HashSet<string> DirtyAtlasNames = new HashSet<string>(StringComparer.Ordinal);
private static readonly Dictionary<string, HashSet<string>> AtlasMap =
new Dictionary<string, HashSet<string>>(StringComparer.Ordinal);
private static readonly List<string> ProcessBuffer = new List<string>();
private static readonly List<string> PendingV2ImporterPaths = new List<string>();
2025-03-14 16:02:36 +08:00
private static bool _initialized;
2026-04-20 14:24:54 +08:00
private static bool _isProcessing;
private static bool _isScanning;
private static bool _processScheduled;
2025-03-14 16:02:36 +08:00
private static AtlasConfiguration Config => AtlasConfiguration.Instance;
static EditorSpriteSaveInfo()
{
Initialize();
}
2026-04-20 14:24:54 +08:00
private static string NormalizedSourceRoot => NormalizePath(Config.sourceAtlasRoot).TrimEnd('/');
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
public static bool PrepareSpriteImporter(TextureImporter importer, string assetPath)
2025-03-27 17:00:12 +08:00
{
2026-04-20 14:24:54 +08:00
if (importer == null || !ShouldProcess(assetPath))
return false;
2025-03-27 17:00:12 +08:00
2026-04-20 14:24:54 +08:00
var modified = false;
if (importer.textureType != TextureImporterType.Sprite)
2025-03-27 17:00:12 +08:00
{
2026-04-20 14:24:54 +08:00
importer.textureType = TextureImporterType.Sprite;
modified = true;
2025-03-27 17:00:12 +08:00
}
2026-04-20 14:24:54 +08:00
if (importer.spriteImportMode != SpriteImportMode.Single)
2025-03-27 17:00:12 +08:00
{
2026-04-20 14:24:54 +08:00
importer.spriteImportMode = SpriteImportMode.Single;
modified = true;
2025-03-27 17:00:12 +08:00
}
2026-04-20 14:24:54 +08:00
var settings = new TextureImporterSettings();
importer.ReadTextureSettings(settings);
if (settings.spriteGenerateFallbackPhysicsShape)
2025-03-27 17:00:12 +08:00
{
2026-04-20 14:24:54 +08:00
settings.spriteGenerateFallbackPhysicsShape = false;
importer.SetTextureSettings(settings);
modified = true;
2025-03-27 17:00:12 +08:00
}
2026-04-20 14:24:54 +08:00
return modified;
}
public static void ConvertToSprite(string assetPath)
{
if (!ShouldProcess(assetPath))
return;
2025-05-13 10:40:21 +08:00
2026-04-20 14:24:54 +08:00
var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer == null)
return;
if (PrepareSpriteImporter(importer, assetPath))
importer.SaveAndReimport();
2025-03-27 17:00:12 +08:00
}
2025-03-14 16:02:36 +08:00
public static void OnImportSprite(string assetPath)
{
2026-04-20 14:24:54 +08:00
if (!ShouldProcess(assetPath))
return;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
EnsureInitialized();
2025-03-27 17:00:12 +08:00
2025-03-14 16:02:36 +08:00
var atlasName = GetAtlasName(assetPath);
2026-04-20 14:24:54 +08:00
if (string.IsNullOrEmpty(atlasName))
return;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
AddSpritePath(atlasName, assetPath);
MarkDirty(atlasName);
MarkParentAtlasesDirty(assetPath);
QueueProcessDirtyAtlases();
2025-03-14 16:02:36 +08:00
}
public static void OnDeleteSprite(string assetPath)
{
2026-04-20 14:24:54 +08:00
if (!ShouldProcess(assetPath))
return;
EnsureInitialized();
2025-03-14 16:02:36 +08:00
var atlasName = GetAtlasName(assetPath);
2026-04-20 14:24:54 +08:00
if (string.IsNullOrEmpty(atlasName))
return;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
if (AtlasMap.TryGetValue(atlasName, out var spritePaths))
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
spritePaths.Remove(assetPath);
if (spritePaths.Count == 0)
AtlasMap.Remove(atlasName);
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
MarkDirty(atlasName);
MarkParentAtlasesDirty(assetPath);
QueueProcessDirtyAtlases();
2025-03-14 16:02:36 +08:00
}
2026-04-17 14:21:51 +08:00
[MenuItem("AlicizaX/Extension/图集工具/ForceGenerateAll")]
2025-03-14 16:02:36 +08:00
public static void ForceGenerateAll()
{
2026-04-20 14:24:54 +08:00
RebuildCache(markDirty: true);
ProcessDirtyAtlases(force: true);
2025-03-14 16:02:36 +08:00
}
public static void ClearCache()
{
2026-04-20 14:24:54 +08:00
DirtyAtlasNames.Clear();
AtlasMap.Clear();
ProcessBuffer.Clear();
PendingV2ImporterPaths.Clear();
_initialized = false;
_processScheduled = false;
2025-03-14 16:02:36 +08:00
}
public static void MarkParentAtlasesDirty(string assetPath)
{
2026-04-20 14:24:54 +08:00
var currentPath = NormalizePath(Path.GetDirectoryName(assetPath));
var rootPath = NormalizedSourceRoot;
while (!string.IsNullOrEmpty(currentPath) &&
currentPath.StartsWith(rootPath + "/", StringComparison.Ordinal))
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var atlasName = GetAtlasNameForDirectory(currentPath);
if (!string.IsNullOrEmpty(atlasName))
MarkDirty(atlasName);
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
currentPath = NormalizePath(Path.GetDirectoryName(currentPath));
2025-03-14 16:02:36 +08:00
}
}
2026-04-20 14:24:54 +08:00
public static bool ShouldProcess(string assetPath)
{
return IsImageFile(assetPath) && !IsExcluded(assetPath) && IsUnderSourceRoot(assetPath);
}
private static void Initialize()
{
if (_initialized)
return;
RebuildCache(markDirty: false);
}
private static void EnsureInitialized()
{
if (!_initialized)
Initialize();
}
private static void RebuildCache(bool markDirty)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
DirtyAtlasNames.Clear();
AtlasMap.Clear();
ScanExistingSprites();
if (markDirty)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
foreach (var atlasName in AtlasMap.Keys)
DirtyAtlasNames.Add(atlasName);
MarkExistingOutputAtlasesDirty();
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
_initialized = true;
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void ScanExistingSprites()
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var sourceRoot = NormalizedSourceRoot;
if (string.IsNullOrEmpty(sourceRoot))
return;
_isScanning = true;
2025-03-14 16:02:36 +08:00
try
{
2026-04-20 14:24:54 +08:00
var guids = AssetDatabase.FindAssets("t:Sprite", new[] { sourceRoot });
foreach (var guid in guids)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var path = AssetDatabase.GUIDToAssetPath(guid);
if (!ShouldProcess(path))
continue;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
var atlasName = GetAtlasName(path);
if (!string.IsNullOrEmpty(atlasName))
AddSpritePath(atlasName, path);
2025-03-14 16:02:36 +08:00
}
}
finally
{
2026-04-20 14:24:54 +08:00
_isScanning = false;
2025-03-14 16:02:36 +08:00
}
}
2026-04-20 14:24:54 +08:00
private static void MarkExistingOutputAtlasesDirty()
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var outputDir = NormalizePath(Config.outputAtlasDir).TrimEnd('/');
if (string.IsNullOrEmpty(outputDir) || !AssetDatabase.IsValidFolder(outputDir))
return;
var guids = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { outputDir });
foreach (var guid in guids)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var path = AssetDatabase.GUIDToAssetPath(guid);
var atlasName = Path.GetFileNameWithoutExtension(path);
if (!string.IsNullOrEmpty(atlasName))
DirtyAtlasNames.Add(atlasName);
}
}
private static void QueueProcessDirtyAtlases()
{
if (_isScanning || _processScheduled || DirtyAtlasNames.Count == 0)
return;
_processScheduled = true;
EditorApplication.delayCall += DelayedProcessDirtyAtlases;
}
private static void DelayedProcessDirtyAtlases()
{
_processScheduled = false;
if (_isProcessing || DirtyAtlasNames.Count == 0)
return;
if (EditorApplication.isCompiling || EditorApplication.isUpdating)
{
QueueProcessDirtyAtlases();
return;
}
ProcessDirtyAtlases();
}
private static void ProcessDirtyAtlases(bool force = false)
{
if (DirtyAtlasNames.Count == 0)
return;
EnsureOutputDirectory();
_isProcessing = true;
try
{
while (DirtyAtlasNames.Count > 0)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
ProcessBuffer.Clear();
ProcessBuffer.AddRange(DirtyAtlasNames);
DirtyAtlasNames.Clear();
PendingV2ImporterPaths.Clear();
AssetDatabase.StartAssetEditing();
try
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
foreach (var atlasName in ProcessBuffer)
{
if (force || ShouldUpdateAtlas(atlasName))
GenerateAtlas(atlasName);
}
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
finally
{
AssetDatabase.StopAssetEditing();
}
ApplyPendingV2ImportSettings();
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
AssetDatabase.SaveAssets();
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
finally
{
ProcessBuffer.Clear();
PendingV2ImporterPaths.Clear();
_isProcessing = false;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
if (DirtyAtlasNames.Count > 0)
QueueProcessDirtyAtlases();
}
}
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
private static void GenerateAtlas(string atlasName)
{
var outputPath = GetAtlasOutputPath(atlasName);
var packables = LoadValidSprites(atlasName);
if (packables.Count == 0)
2025-03-14 16:02:36 +08:00
{
DeleteAtlas(outputPath);
2026-04-20 14:24:54 +08:00
DeleteAtlas(GetLegacyAtlasOutputPath(atlasName));
2025-03-14 16:02:36 +08:00
return;
}
2026-04-20 14:24:54 +08:00
DeleteAtlas(GetLegacyAtlasOutputPath(atlasName));
var spriteObjects = packables.ToArray();
2025-03-14 16:02:36 +08:00
if (Config.enableV2)
{
2026-04-20 14:24:54 +08:00
GenerateAtlasV2(outputPath, spriteObjects);
2025-03-14 16:02:36 +08:00
}
else
{
2026-04-20 14:24:54 +08:00
GenerateAtlasV1(outputPath, spriteObjects);
2025-03-14 16:02:36 +08:00
}
if (Config.enableLogging)
2026-04-20 14:24:54 +08:00
Debug.Log($"Generated atlas: {atlasName} ({spriteObjects.Length} sprites)");
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void GenerateAtlasV2(string outputPath, UnityEngine.Object[] spriteObjects)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(outputPath);
var spriteAtlasAsset = atlas == null ? new SpriteAtlasAsset() : SpriteAtlasAsset.Load(outputPath);
2025-07-31 14:27:47 +08:00
2026-04-20 14:24:54 +08:00
if (atlas != null)
{
var oldPackables = atlas.GetPackables();
if (oldPackables != null && oldPackables.Length > 0)
spriteAtlasAsset.Remove(oldPackables);
}
2025-07-31 14:27:47 +08:00
2026-04-20 14:24:54 +08:00
#if !UNITY_2022_1_OR_NEWER
ConfigureAtlasV2Settings(spriteAtlasAsset);
#endif
spriteAtlasAsset.Add(spriteObjects);
SpriteAtlasAsset.Save(spriteAtlasAsset, outputPath);
2025-07-31 14:27:47 +08:00
2026-04-20 14:24:54 +08:00
#if UNITY_2022_1_OR_NEWER
PendingV2ImporterPaths.Add(outputPath);
#endif
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void GenerateAtlasV1(string outputPath, UnityEngine.Object[] spriteObjects)
2025-03-27 17:00:12 +08:00
{
2026-04-20 14:24:54 +08:00
var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(outputPath);
if (atlas == null)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
atlas = new SpriteAtlas();
ConfigureAtlasSettings(atlas);
atlas.Add(spriteObjects);
atlas.SetIsVariant(false);
AssetDatabase.CreateAsset(atlas, outputPath);
return;
2025-03-27 17:00:12 +08:00
}
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
var oldPackables = atlas.GetPackables();
if (oldPackables != null && oldPackables.Length > 0)
atlas.Remove(oldPackables);
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
ConfigureAtlasSettings(atlas);
atlas.Add(spriteObjects);
atlas.SetIsVariant(false);
EditorUtility.SetDirty(atlas);
2025-03-27 17:00:12 +08:00
}
2026-04-20 14:24:54 +08:00
private static List<UnityEngine.Object> LoadValidSprites(string atlasName)
{
var sprites = new List<UnityEngine.Object>();
if (!AtlasMap.TryGetValue(atlasName, out var spritePaths) || spritePaths.Count == 0)
return sprites;
foreach (var assetPath in spritePaths)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
if (sprite != null)
2025-03-14 19:58:50 +08:00
{
2026-04-20 14:24:54 +08:00
sprites.Add(sprite);
continue;
2025-03-14 19:58:50 +08:00
}
2026-04-20 14:24:54 +08:00
var subAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetPath);
foreach (var subAsset in subAssets)
{
if (subAsset is Sprite subSprite)
sprites.Add(subSprite);
}
}
return sprites;
}
private static void ApplyPendingV2ImportSettings()
{
#if UNITY_2022_1_OR_NEWER
foreach (var outputPath in PendingV2ImporterPaths)
{
var importer = AssetImporter.GetAtPath(outputPath) as SpriteAtlasImporter;
if (importer == null)
continue;
if (ConfigureAtlasV2Settings(importer))
{
AssetDatabase.WriteImportSettingsIfDirty(outputPath);
importer.SaveAndReimport();
}
else
{
AssetDatabase.ImportAsset(outputPath, ImportAssetOptions.ForceSynchronousImport);
}
}
#endif
}
2025-03-14 19:58:50 +08:00
2026-04-20 14:24:54 +08:00
#if UNITY_2022_1_OR_NEWER
private static bool ConfigureAtlasV2Settings(SpriteAtlasImporter atlasImporter)
{
var modified = false;
modified |= SetPlatform(atlasImporter, "Android", Config.androidFormat);
modified |= SetPlatform(atlasImporter, "iPhone", Config.iosFormat);
modified |= SetPlatform(atlasImporter, "WebGL", Config.webglFormat);
var packingSettings = atlasImporter.packingSettings;
if (packingSettings.padding != Config.padding ||
packingSettings.enableRotation != Config.enableRotation ||
packingSettings.blockOffset != Config.blockOffset ||
packingSettings.enableTightPacking != Config.tightPacking ||
!packingSettings.enableAlphaDilation)
{
atlasImporter.packingSettings = new SpriteAtlasPackingSettings
2025-03-14 19:58:50 +08:00
{
padding = Config.padding,
enableRotation = Config.enableRotation,
blockOffset = Config.blockOffset,
enableTightPacking = Config.tightPacking,
enableAlphaDilation = true
};
2026-04-20 14:24:54 +08:00
modified = true;
2025-03-14 19:58:50 +08:00
}
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
return modified;
}
private static bool SetPlatform(SpriteAtlasImporter atlasImporter, string platform, TextureImporterFormat format)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var settings = atlasImporter.GetPlatformSettings(platform);
if (settings == null)
return false;
if (settings.overridden &&
settings.format == format &&
settings.compressionQuality == Config.compressionQuality)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
return false;
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
settings.overridden = true;
settings.format = format;
settings.compressionQuality = Config.compressionQuality;
atlasImporter.SetPlatformSettings(settings);
return true;
}
#else
private static void ConfigureAtlasV2Settings(SpriteAtlasAsset spriteAtlasAsset)
{
SetPlatform(spriteAtlasAsset, "Android", Config.androidFormat);
SetPlatform(spriteAtlasAsset, "iPhone", Config.iosFormat);
SetPlatform(spriteAtlasAsset, "WebGL", Config.webglFormat);
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
spriteAtlasAsset.SetPackingSettings(new SpriteAtlasPackingSettings
2025-03-14 16:02:36 +08:00
{
padding = Config.padding,
enableRotation = Config.enableRotation,
blockOffset = Config.blockOffset,
2025-03-14 19:58:50 +08:00
enableTightPacking = Config.tightPacking,
2026-04-20 14:24:54 +08:00
enableAlphaDilation = true
});
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void SetPlatform(SpriteAtlasAsset spriteAtlasAsset, string platform, TextureImporterFormat format)
{
var settings = spriteAtlasAsset.GetPlatformSettings(platform);
if (settings == null)
return;
settings.overridden = true;
settings.format = format;
settings.compressionQuality = Config.compressionQuality;
spriteAtlasAsset.SetPlatformSettings(settings);
}
#endif
private static void ConfigureAtlasSettings(SpriteAtlas atlas)
{
SetPlatform(atlas, "Android", Config.androidFormat);
SetPlatform(atlas, "iPhone", Config.iosFormat);
SetPlatform(atlas, "WebGL", Config.webglFormat);
atlas.SetPackingSettings(new SpriteAtlasPackingSettings
{
padding = Config.padding,
enableRotation = Config.enableRotation,
blockOffset = Config.blockOffset,
enableTightPacking = Config.tightPacking
});
}
private static void SetPlatform(SpriteAtlas atlas, string platform, TextureImporterFormat format)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var settings = atlas.GetPlatformSettings(platform);
settings.overridden = true;
settings.format = format;
settings.compressionQuality = Config.compressionQuality;
atlas.SetPlatformSettings(settings);
}
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
private static string GetAtlasName(string assetPath)
{
var normalizedPath = NormalizePath(assetPath);
var rootPath = NormalizedSourceRoot;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
if (!normalizedPath.StartsWith(rootPath + "/", StringComparison.Ordinal))
return null;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
var relativePath = normalizedPath.Substring(rootPath.Length + 1).Split('/');
if (relativePath.Length < 2)
return null;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
var atlasNamePart = string.Join("_", relativePath, 0, relativePath.Length - 1);
2025-03-14 16:02:36 +08:00
var rootFolderName = Path.GetFileName(rootPath);
2026-04-20 14:24:54 +08:00
return $"{rootFolderName}_{atlasNamePart}";
}
private static string GetAtlasNameForDirectory(string directoryPath)
{
var normalizedPath = NormalizePath(directoryPath);
var rootPath = NormalizedSourceRoot;
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
if (!normalizedPath.StartsWith(rootPath + "/", StringComparison.Ordinal))
return null;
var relativePath = normalizedPath.Substring(rootPath.Length + 1).Split('/');
if (relativePath.Length == 0)
return null;
var atlasNamePart = string.Join("_", relativePath);
var rootFolderName = Path.GetFileName(rootPath);
2025-03-14 16:02:36 +08:00
return $"{rootFolderName}_{atlasNamePart}";
}
2026-04-20 14:24:54 +08:00
private static void AddSpritePath(string atlasName, string assetPath)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
if (!AtlasMap.TryGetValue(atlasName, out var spritePaths))
{
spritePaths = new HashSet<string>(StringComparer.Ordinal);
AtlasMap[atlasName] = spritePaths;
}
spritePaths.Add(assetPath);
2025-03-14 16:02:36 +08:00
}
private static bool IsExcluded(string path)
{
2026-04-20 14:24:54 +08:00
var normalizedPath = NormalizePath(path);
var excludeFolders = Config.excludeFolders;
if (excludeFolders != null)
{
foreach (var folder in excludeFolders)
{
if (!string.IsNullOrEmpty(folder) &&
normalizedPath.StartsWith(NormalizePath(folder), StringComparison.Ordinal))
{
return true;
}
}
}
var excludeKeywords = Config.excludeKeywords;
if (excludeKeywords != null)
{
foreach (var keyword in excludeKeywords)
{
if (!string.IsNullOrEmpty(keyword) &&
normalizedPath.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
}
}
return false;
2025-03-14 16:02:36 +08:00
}
private static bool IsImageFile(string path)
{
2026-04-20 14:24:54 +08:00
var extension = Path.GetExtension(path);
if (string.IsNullOrEmpty(extension))
return false;
switch (extension.ToLowerInvariant())
{
case ".png":
case ".jpg":
case ".jpeg":
return true;
default:
return false;
}
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static bool IsUnderSourceRoot(string assetPath)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var normalizedPath = NormalizePath(assetPath);
var rootPath = NormalizedSourceRoot;
return !string.IsNullOrEmpty(rootPath) &&
normalizedPath.StartsWith(rootPath + "/", StringComparison.Ordinal);
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void MarkDirty(string atlasName)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
if (!string.IsNullOrEmpty(atlasName))
DirtyAtlasNames.Add(atlasName);
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static bool ShouldUpdateAtlas(string atlasName)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
return !string.IsNullOrEmpty(atlasName);
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static void DeleteAtlas(string assetPath)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
if (!string.IsNullOrEmpty(assetPath) && !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(assetPath)))
AssetDatabase.DeleteAsset(assetPath);
2025-03-14 16:02:36 +08:00
}
private static void EnsureOutputDirectory()
{
2026-04-20 14:24:54 +08:00
var outputPath = NormalizePath(Config.outputAtlasDir).TrimEnd('/');
if (string.IsNullOrEmpty(outputPath) || AssetDatabase.IsValidFolder(outputPath))
return;
var pathParts = outputPath.Split('/');
if (pathParts.Length == 0 || pathParts[0] != "Assets")
return;
var currentPath = pathParts[0];
for (var i = 1; i < pathParts.Length; i++)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var nextPath = $"{currentPath}/{pathParts[i]}";
if (!AssetDatabase.IsValidFolder(nextPath))
AssetDatabase.CreateFolder(currentPath, pathParts[i]);
currentPath = nextPath;
2025-03-14 16:02:36 +08:00
}
}
2026-04-20 14:24:54 +08:00
private static string GetAtlasOutputPath(string atlasName)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var extension = Config.enableV2 ? ".spriteatlasv2" : ".spriteatlas";
return $"{NormalizePath(Config.outputAtlasDir).TrimEnd('/')}/{atlasName}{extension}";
2025-03-14 16:02:36 +08:00
}
2026-04-20 14:24:54 +08:00
private static string GetLegacyAtlasOutputPath(string atlasName)
2025-03-14 16:02:36 +08:00
{
2026-04-20 14:24:54 +08:00
var legacyExtension = Config.enableV2 ? ".spriteatlas" : ".spriteatlasv2";
return $"{NormalizePath(Config.outputAtlasDir).TrimEnd('/')}/{atlasName}{legacyExtension}";
}
2025-03-14 16:02:36 +08:00
2026-04-20 14:24:54 +08:00
private static string NormalizePath(string path)
{
return string.IsNullOrEmpty(path) ? string.Empty : path.Replace("\\", "/");
2025-03-14 16:02:36 +08:00
}
}
#endif