Files
tcg-client/Assets/TcgEngine/Scripts/Tools/SpriteLoader.cs
2025-09-23 15:05:32 +08:00

322 lines
10 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// 动态Sprite加载器支持从本地下载的资源中加载图片
/// </summary>
public class SpriteLoader : MonoBehaviour
{
private static SpriteLoader instance;
private Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>();
private Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>();
public static SpriteLoader Instance
{
get
{
if (instance == null)
{
GameObject go = new GameObject("SpriteLoader");
instance = go.AddComponent<SpriteLoader>();
DontDestroyOnLoad(go);
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
/// <summary>
/// 从本地文件加载Sprite
/// </summary>
/// <param name="relativePath">相对于Sprites文件夹的路径</param>
/// <returns>加载的Sprite失败返回null</returns>
public Sprite LoadSprite(string relativePath)
{
if (string.IsNullOrEmpty(relativePath))
{
Debug.LogWarning("[SpriteLoader] Empty relativePath provided");
return null;
}
// Debug.Log($"[SpriteLoader] Loading sprite: {relativePath}");
// 检查缓存
if (spriteCache.ContainsKey(relativePath))
{
// Debug.Log($"[SpriteLoader] Found in cache: {relativePath}");
return spriteCache[relativePath];
}
try
{
// 先尝试从下载的本地资源加载
string localPath = GetLocalSpritePath(relativePath);
Debug.Log($"[SpriteLoader] Checking local path: {localPath}");
if (File.Exists(localPath))
{
Debug.Log($"[SpriteLoader] Local file exists, loading from: {localPath}");
Sprite sprite = LoadSpriteFromFile(localPath);
if (sprite != null)
{
Debug.Log($"[SpriteLoader] Successfully loaded from local file: {relativePath}");
spriteCache[relativePath] = sprite;
return sprite;
}
else
{
Debug.LogWarning($"[SpriteLoader] Failed to load sprite from local file: {localPath}");
}
}
else
{
Debug.LogWarning($"[SpriteLoader] Local file does not exist: {localPath}");
}
// 如果本地文件不存在尝试从Resources加载fallback
Debug.Log($"[SpriteLoader] Trying Resources fallback for: {relativePath}");
Sprite fallbackSprite = LoadSpriteFromResources(relativePath);
if (fallbackSprite != null)
{
Debug.Log($"[SpriteLoader] Successfully loaded from Resources: {relativePath}");
spriteCache[relativePath] = fallbackSprite;
return fallbackSprite;
}
Debug.LogWarning($"[SpriteLoader] Failed to load sprite from both local and Resources: {relativePath}");
return null;
}
catch (Exception e)
{
Debug.LogError($"[SpriteLoader] Error loading sprite {relativePath}: {e.Message}");
return null;
}
}
/// <summary>
/// 从文件系统加载Sprite
/// </summary>
private Sprite LoadSpriteFromFile(string filePath)
{
try
{
// 加载纹理
Texture2D texture = LoadTextureFromFile(filePath);
if (texture == null)
return null;
// 创建Sprite
Sprite sprite = Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
new Vector2(0.5f, 0.5f)
);
return sprite;
}
catch (Exception e)
{
Debug.LogError($"Error loading sprite from file {filePath}: {e.Message}");
return null;
}
}
/// <summary>
/// 从文件加载纹理
/// </summary>
private Texture2D LoadTextureFromFile(string filePath)
{
if (textureCache.ContainsKey(filePath))
{
return textureCache[filePath];
}
try
{
byte[] fileData = File.ReadAllBytes(filePath);
Texture2D texture = new Texture2D(2, 2);
if (texture.LoadImage(fileData))
{
textureCache[filePath] = texture;
return texture;
}
else
{
Destroy(texture);
return null;
}
}
catch (Exception e)
{
Debug.LogError($"Error loading texture from file {filePath}: {e.Message}");
return null;
}
}
/// <summary>
/// 从Resources文件夹加载Spritefallback
/// </summary>
private Sprite LoadSpriteFromResources(string relativePath)
{
try
{
// 移除文件扩展名
string resourcePath = Path.ChangeExtension(relativePath, null);
// 尝试直接加载Sprite
Sprite sprite = Resources.Load<Sprite>(resourcePath);
if (sprite != null)
return sprite;
// 如果直接加载失败尝试加载Texture2D然后转换
Texture2D texture = Resources.Load<Texture2D>(resourcePath);
if (texture != null)
{
return Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
new Vector2(0.5f, 0.5f)
);
}
return null;
}
catch (Exception e)
{
Debug.LogError($"Error loading sprite from resources {relativePath}: {e.Message}");
return null;
}
}
/// <summary>
/// 获取本地Sprite文件路径
/// </summary>
private string GetLocalSpritePath(string relativePath)
{
if (ResourceDownloader.Get() != null)
{
return ResourceDownloader.Get().GetLocalSpritePath(relativePath);
}
// Fallback路径
string basePath = Path.Combine(Application.persistentDataPath, "Sprites");
return Path.Combine(basePath, relativePath);
}
/// <summary>
/// 清理缓存
/// </summary>
public void ClearCache()
{
foreach (var sprite in spriteCache.Values)
{
if (sprite != null)
Destroy(sprite);
}
spriteCache.Clear();
foreach (var texture in textureCache.Values)
{
if (texture != null)
Destroy(texture);
}
textureCache.Clear();
}
/// <summary>
/// 预加载指定目录下的所有图片
/// </summary>
public void PreloadSprites(string directory)
{
try
{
string localDir = GetLocalSpritePath(directory);
if (!Directory.Exists(localDir))
return;
string[] files = Directory.GetFiles(localDir, "*.png", SearchOption.AllDirectories);
foreach (string file in files)
{
string relativePath = GetRelativePath(file);
LoadSprite(relativePath);
}
}
catch (Exception e)
{
Debug.LogError($"Error preloading sprites from {directory}: {e.Message}");
}
}
/// <summary>
/// 获取相对路径
/// </summary>
private string GetRelativePath(string fullPath)
{
string spritesPath = GetLocalSpritePath("");
if (fullPath.StartsWith(spritesPath))
{
return fullPath.Substring(spritesPath.Length + 1);
}
return fullPath;
}
/// <summary>
/// 检查Sprite是否存在
/// </summary>
public bool SpriteExists(string relativePath)
{
if (spriteCache.ContainsKey(relativePath))
return true;
string localPath = GetLocalSpritePath(relativePath);
if (File.Exists(localPath))
return true;
// 检查Resources
string resourcePath = Path.ChangeExtension(relativePath, null);
Sprite sprite = Resources.Load<Sprite>(resourcePath);
if (sprite != null)
{
Resources.UnloadAsset(sprite);
return true;
}
Texture2D texture = Resources.Load<Texture2D>(resourcePath);
if (texture != null)
{
Resources.UnloadAsset(texture);
return true;
}
return false;
}
private void OnDestroy()
{
ClearCache();
}
public static SpriteLoader Get()
{
return Instance;
}
}
}