Files
2026-09-21 12:15:57 +03:00

178 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
#endif
using UnityEngine.U2D;
namespace UnityEngine.AddressableAssets.Utility
{
internal class AssetReferenceUtilities
{
static internal string FormatName(string name)
{
if (name.EndsWith("(Clone)", StringComparison.Ordinal))
name = name.Replace("(Clone)", "");
return name;
}
#if UNITY_EDITOR
static Sprite[] FilterSprites(Object[] objs)
{
var spriteCount = 0;
var sprites = new Sprite[objs.Length];
for (var i = 0; i < objs.Length; i++)
{
if (objs[i] is Sprite s)
{
sprites[spriteCount] = s;
spriteCount++;
}
}
return sprites[0..spriteCount];
}
internal static void GetSpritesFromPackable(Object packable, HashSet<(Sprite, string)> assets)
{
if (packable == null)
{
return;
}
var packablePath = AssetDatabase.GetAssetPath(packable);
if (Directory.Exists(packablePath))
{
// everything gets included
GetSpritesFromDirectory(packablePath, assets);
return;
}
// top level packables are handled somewhat differently. If a texture contains multiple sprites
// if the entire texture is included all sprites will be included. But at the top level a single
// sprite can be picked out of a mutiple sprite texture so only that sprite should be included.
var sprites = FilterSprites(AssetDatabase.LoadAllAssetsAtPath(packablePath));
if (sprites.Length == 0)
{
Addressables.LogError($"unknown packable {packable.name} in {packablePath}");
return;
}
if (sprites.Length == 1)
{
assets.Add((sprites[0], AssetDatabase.AssetPathToGUID(packablePath)));
return;
}
var packableSprite = packable as Sprite;
if (packableSprite == null)
{
Addressables.LogError($"unknown packable type {packable.name} in {packablePath}");
return;
}
// this is using sprite mode multiple
var guid = AssetDatabase.AssetPathToGUID(packablePath);
foreach (var sprite in sprites)
{
if (sprite is Sprite s)
{
if (s.name == packableSprite.name)
{
assets.Add((s, guid));
}
}
}
}
// Currently the 3 types of packable assets are Sprite, Texture2D, and DefaultAssets that are Folders
internal static void GetSpritesFromDirectory(string folderPath, HashSet<(Sprite, string)> assets)
{
if (!Directory.Exists(folderPath))
{
// we only want to add explicitly added paths if they're sprites
var sprites = AssetDatabase.LoadAllAssetsAtPath(folderPath);
if (sprites.Length > 0)
{
var guid = AssetDatabase.AssetPathToGUID(folderPath);
foreach (var sprite in sprites)
{
if (sprite is Sprite s)
{
assets.Add((s, s.GetSpriteID().ToString()));
}
}
}
return;
}
var assetGuids = AssetDatabase.FindAssets("t:Sprite", new[] { folderPath });
foreach(var guid in assetGuids)
{
var sprites = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GUIDToAssetPath(guid));
foreach (var sprite in sprites)
{
if (sprite is Sprite s)
{
assets.Add((s, guid));
}
}
}
// texture2Ds can be set to sprite type multiple so we need to check if they have any sprite children
assetGuids = AssetDatabase.FindAssets("t:Texture2D", new[] { folderPath });
foreach (var guid in assetGuids)
{
Object[] data = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GUIDToAssetPath(guid));
if (data != null)
{
foreach (Object obj in data)
{
if (obj is Sprite s)
{
assets.Add((s, guid));
}
}
}
}
assetGuids = AssetDatabase.FindAssets("t:DefaultAsset", new[] { folderPath });
foreach(var guid in assetGuids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (Directory.Exists(path))
{
GetSpritesFromDirectory(path, assets);
}
}
}
internal static HashSet<(Sprite, string)> GetAtlasSpritesAndPackables(ref SpriteAtlas atlas)
{
var guids = new HashSet<(Sprite, string)>();
if (atlas.isVariant)
atlas = atlas.GetMasterAtlas();
Object[] atlasPackables = atlas.GetPackables();
foreach (var packable in atlasPackables)
{
GetSpritesFromPackable(packable, guids);
}
if (guids.Count != atlas.spriteCount)
{
Addressables.LogError($"Count mismatch between packables ({guids.Count}) and sprites in Atlas ({atlas.spriteCount}).");
return guids;
}
return guids;
}
#endif
}
}