Files
Gen_Hack-and-Slash-Roguelit…/Client/Assets/Scripts/Managers/PackagesImageManager.cs

469 lines
20 KiB
C#
Raw 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 System.Linq;
using Data;
using NUnit.Framework;
using UnityEngine;
namespace Managers
{
public class PackagesImageManager : Utils.Singleton<PackagesImageManager>
{
public Sprite defaultSprite;
//包名,图片名
public Dictionary<string, Dictionary<string, Texture2D>> packagesImages = new();
//包名,图片名
public Dictionary<string, Dictionary<string, Sprite>> sprites = new();
public void Init()
{
if (packagesImages.Count > 0)
return;
defaultSprite = Resources.Load<Sprite>("Default/DefaultImage");
InitImageDef();
}
public void InitImageDef()
{
var textureCache = new Dictionary<string, Texture2D>();
var imageDef = Managers.DefineManager.Instance.QueryDefinesByType<ImageDef>();
foreach (var ima in imageDef)
{
if (string.IsNullOrEmpty(ima.path) || string.IsNullOrEmpty(ima.packID))
continue;
// 解析路径前缀
try
{
string cacheKey;
Texture2D texture;
if (ima.path.StartsWith("res:"))
{
// 处理Resources路径
var resPath = ima.path.Substring(4).Replace('\\', '/').TrimStart('/');
cacheKey = "res://" + resPath.ToLower();
// 检查缓存
if (!textureCache.TryGetValue(cacheKey, out texture))
{
// 去掉扩展名
var cleanPath = Path.ChangeExtension(resPath, null);
texture = Resources.Load<Texture2D>(cleanPath);
if (texture)
textureCache[cacheKey] = texture;
}
}
else if (ima.path.Contains(':'))
{
// 处理其他包ID前缀如 "PackageID:Path"
var splitIndex = ima.path.IndexOf(':');
var packageID = ima.path.Substring(0, splitIndex);
var relativePath = ima.path.Substring(splitIndex + 1);
// 获取包根路径
var packageRoot = Managers.DefineManager.Instance.GetPackagePath(packageID);
if (string.IsNullOrEmpty(packageRoot))
continue;
var fullPath = Path.Combine(packageRoot, relativePath).Replace('\\', '/');
cacheKey = "file://" + fullPath.ToLower();
// 检查缓存
if (!textureCache.TryGetValue(cacheKey, out texture))
{
texture = Configs.ConfigProcessor.LoadTextureByIO(fullPath);
if (texture)
textureCache[cacheKey] = texture;
}
}
else
{
// 无前缀:使用当前定义所在包的路径
var pack = Managers.DefineManager.Instance.GetDefinePackage(ima);
var fullPath = Path.Combine(pack.packRootPath, ima.path).Replace('\\', '/');
cacheKey = "file://" + fullPath.ToLower();
// 检查缓存
if (!textureCache.TryGetValue(cacheKey, out texture))
{
texture = Configs.ConfigProcessor.LoadTextureByIO(fullPath);
if (texture)
textureCache[cacheKey] = texture;
}
}
// 资源加载失败
if (!texture)
{
Debug.LogError($"Failed to load texture: {ima.path} (PackID: {ima.packID}, Name: {ima.name})");
continue;
}
// 存储到包资源字典使用原始packID非路径中的包ID
var packId = ima.packID;
if (!packagesImages.ContainsKey(packId))
packagesImages[packId] = new Dictionary<string, Texture2D>();
// 避免同一包内重复添加(查重)
if (!packagesImages[packId].ContainsKey(ima.name))
packagesImages[packId].Add(ima.name, texture);
else
packagesImages[packId][ima.name] = texture; // 覆盖已存在的引用
// 切分精灵
SplitTextureIntoSprites(packId, ima.name, texture, ima.hCount, ima.wCount, ima.pixelsPerUnit);
}
catch (Exception ex)
{
// 捕获异常并打印详细错误信息
Debug.LogError(
$"Error processing image definition: {ima.name} (Path: {ima.path}, PackID: {ima.packID}). Exception: {ex.Message}");
}
}
}
// public void InitDrawOrder()
// {
// try
// {
// // 查询绘制顺序定义
// var drawOrderDef = Managers.DefineManager.Instance.QueryDefinesByType<DrawingOrderDef>();
// if (drawOrderDef == null || drawOrderDef.Length == 0)
// {
// Debug.LogWarning("No DrawingOrderDef found.");
// return;
// }
//
// // 初始化包路径字典
// Dictionary<string, string> packRootSite = new();
//
// foreach (var drawOrder in drawOrderDef)
// {
// // 检查必要字段是否为空
// if (string.IsNullOrEmpty(drawOrder.texturePath) || string.IsNullOrEmpty(drawOrder.packID))
// {
// Debug.LogWarning(
// $"Skipping invalid drawOrder: texturePath or packID is null or empty. PackID: {drawOrder.packID}");
// continue;
// }
//
// // 获取包路径
// if (!packRootSite.ContainsKey(drawOrder.packID))
// {
// var packagePath = Managers.DefineManager.Instance.GetPackagePath(drawOrder.packID);
// if (string.IsNullOrEmpty(packagePath))
// {
// Debug.LogError($"Package path not found for packID: {drawOrder.packID}");
// continue;
// }
//
// packRootSite[drawOrder.packID] = packagePath;
// }
//
// // 判断是否为 Unity 资源路径
// var isUnityResource = drawOrder.texturePath.StartsWith("res:", StringComparison.OrdinalIgnoreCase);
// var rootPath = packRootSite[drawOrder.packID];
//
// if (isUnityResource)
// {
// // 移除 "res:" 前缀并适配 Unity 资源路径规则
// var resourceFolder = drawOrder.texturePath.Substring(4).TrimStart('/').Replace('\\', '/');
//
// // 加载文件夹下的所有纹理资源
// var textures = Resources.LoadAll<Texture2D>(resourceFolder);
// if (textures == null || textures.Length == 0)
// {
// Debug.LogWarning($"No textures found in Unity resource folder: {resourceFolder}");
// continue;
// }
//
// foreach (var image in textures)
// {
// if (image == null)
// {
// Debug.LogWarning(
// $"Texture loaded from Unity resource folder: {resourceFolder} is null.");
// continue;
// }
//
// // 创建精灵
// try
// {
// var spr = Sprite.Create(
// image,
// new Rect(0, 0, image.width, image.height),
// new Vector2(0.5f, 0.5f), // 中心点
// drawOrder.pixelsPerUnit
// );
// var name = image.name;
//
// // 插入纹理
// InsertBodyTexture(drawOrder.packID, drawOrder.texturePath, name, spr);
// }
// catch (Exception ex)
// {
// Debug.LogError(
// $"Failed to create sprite from Unity resource: {image.name}. Error: {ex.Message}");
// }
// }
// }
// else
// {
// // 文件系统路径处理
// var folderPath = Path.Combine(rootPath, drawOrder.texturePath);
//
// // 获取图像文件列表
// try
// {
// var imagePath = Configs.ConfigProcessor.GetFilesByExtensions(folderPath,
// new[] { "jpg", "jpeg", "png", "tga", "tif", "tiff", "psd", "bmp" });
//
// foreach (var path in imagePath)
// {
// // 加载纹理
// Texture2D image = null;
// try
// {
// image = Configs.ConfigProcessor.LoadTextureByIO(path);
// }
// catch (Exception ex)
// {
// Debug.LogError($"Failed to load texture from path: {path}. Error: {ex.Message}");
// continue;
// }
//
// if (image == null)
// {
// Debug.LogWarning($"Texture loaded from path: {path} is null.");
// continue;
// }
//
// // 创建精灵
// try
// {
// var spr = Sprite.Create(
// image,
// new Rect(0, 0, image.width, image.height),
// new Vector2(0.5f, 0.5f), // 中心点
// drawOrder.pixelsPerUnit
// );
//
// var name = Path.GetFileNameWithoutExtension(path);
//
// // 插入纹理
// InsertBodyTexture(drawOrder.packID, drawOrder.texturePath, name, spr);
// }
// catch (Exception ex)
// {
// Debug.LogError(
// $"Failed to create sprite from texture: {path}. Error: {ex.Message}");
// }
// }
// }
// catch (Exception ex)
// {
// Debug.LogError($"Failed to retrieve files from folder: {folderPath}. Error: {ex.Message}");
// }
// }
// }
// }
// catch (Exception ex)
// {
// Debug.LogError($"An unexpected error occurred in InitDrawOrder: {ex.Message}");
// }
// }
private void SplitTextureIntoSprites(
string packId,
string baseName,
Texture2D texture,
int rows,
int cols,
int pixelsPerUnit)
{
if (!texture)
{
Debug.LogError("Texture is null.");
return;
}
// 如果行数或列数小于1则设为1不分割
rows = Mathf.Max(1, rows);
cols = Mathf.Max(1, cols);
var textureWidth = texture.width;
var textureHeight = texture.height;
// 首先创建一个未分割的精灵,使用原始名称
if (!sprites.ContainsKey(packId))
sprites[packId] = new Dictionary<string, Sprite>();
// 创建未分割的精灵
var fullSpriteRect = new Rect(0, 0, textureWidth, textureHeight);
var fullSprite = Sprite.Create(texture, fullSpriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
fullSprite.name = baseName; // 使用原始名称
sprites[packId][baseName] = fullSprite;
// 如果不分割rows和cols都为1直接返回
if (rows == 1 && cols == 1)
{
return;
}
var tileWidth = textureWidth / cols;
var tileHeight = textureHeight / rows;
if (tileWidth * cols != textureWidth || tileHeight * rows != textureHeight)
{
Debug.LogError("Texture dimensions are not divisible by the specified rows and columns.");
return;
}
// 分割纹理并创建多个精灵
for (var row = 0; row < rows; row++)
{
for (var col = 0; col < cols; col++)
{
Rect spriteRect = new(col * tileWidth, row * tileHeight, tileWidth, tileHeight);
var sprite = Sprite.Create(texture, spriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
var index = (rows - row - 1) * cols + col; // 计算索引
var spriteName = $"{baseName}_{index}";
sprite.name = spriteName;
// 添加到字典中
sprites[packId][spriteName] = sprite;
}
}
}
public void Reload()
{
packagesImages.Clear();
sprites.Clear();
Init();
}
public Sprite GetSprite(ImageDef ima)
{
return GetSprite(ima.packID,ima.name);
}
public Sprite GetSprite(string packID, string name)
{
if (string.IsNullOrEmpty(packID))
{
foreach (var kvp in sprites)
{
if (kvp.Value.TryGetValue(name, out var sprite))
return sprite;
}
}
else if (sprites.TryGetValue(packID, out var dict))
{
if (dict.TryGetValue(name, out var sprite))
return sprite;
}
return defaultSprite;
}
public Sprite GetSprite(string packID, string name, int index)
{
var fullName = $"{name}_{index}";
return GetSprite(packID, fullName);
}
// /// <summary>
// /// 向 bodyTexture 插入一张 Sprite。
// /// 如果包名、路径或部件名原本不存在,会自动建立对应的 Dictionary。
// /// </summary>
// /// <param name="packageName">包名</param>
// /// <param name="filePath">文件路径</param>
// /// <param name="bodyPartName">身体部件名</param>
// /// <param name="sprite">要插入的 Sprite</param>
// public void InsertBodyTexture(string packageName,
// string filePath,
// string bodyPartName,
// Sprite sprite)
// {
// if (sprite == null)
// {
// Debug.LogWarning("InsertBodyTexture: sprite 为 null已忽略。");
// return;
// }
//
// // 1) 处理包名层级
// if (!bodyTexture.TryGetValue(packageName, out var pathDict))
// {
// pathDict = new Dictionary<string, Dictionary<string, Sprite>>();
// bodyTexture[packageName] = pathDict;
// }
//
// // 2) 处理文件路径层级
// if (!pathDict.TryGetValue(filePath, out var partDict))
// {
// partDict = new Dictionary<string, Sprite>();
// pathDict[filePath] = partDict;
// }
//
// // 3) 插入或覆盖部件名
// partDict[bodyPartName] = sprite;
// }
// /// <summary>
// /// 查找身体部件的所有Sprite变体支持带编号的图片
// /// </summary>
// /// <param name="packageName">包名</param>
// /// <param name="filePath">文件路径</param>
// /// <param name="bodyPartName">身体部件名</param>
// /// <returns>按编号排序的Sprite数组未找到时返回空数组</returns>
// public Sprite[] FindBodyTextures(string packageName, string filePath, string bodyPartName)
// {
// // 检查包名是否存在
// if (!bodyTexture.TryGetValue(packageName, out var packageDict))
// {
// Debug.LogWarning($"Package '{packageName}' not found.");
// return new[] { defaultSprite };
// }
//
// // 检查文件路径是否存在
// if (!packageDict.TryGetValue(filePath, out var pathDict))
// {
// Debug.LogWarning($"File path '{filePath}' not found in package '{packageName}'.");
// return new[] { defaultSprite };
// }
//
// // 收集所有匹配的Sprite
// var sprites = new List<(int order, Sprite sprite)>();
//
// // 查找完全匹配的项(无编号)
// if (pathDict.TryGetValue(bodyPartName, out var baseSprite))
// {
// sprites.Add((0, baseSprite));
// }
//
// // 查找带编号的变体
// var prefix = bodyPartName + "_";
// foreach (var (key, value) in pathDict)
// {
// // 检查是否以部件名+下划线开头
// if (key.StartsWith(prefix) && key.Length > prefix.Length)
// {
// var suffix = key.Substring(prefix.Length);
//
// // 尝试解析编号
// if (int.TryParse(suffix, out var number))
// {
// sprites.Add((number, value));
// }
// }
// }
//
// // 按编号排序无编号视为0
// return sprites
// .OrderBy(x => x.order)
// .Select(x => x.sprite)
// .ToArray();
// }
}
}