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 { public Sprite defaultSprite; //包名,图片名 public Dictionary> packagesImages = new(); //包名,图片名 public Dictionary> sprites = new(); public void Init() { if (packagesImages.Count > 0) return; defaultSprite = Resources.Load("Default/DefaultImage"); InitImageDef(); } public void InitImageDef() { var textureCache = new Dictionary(); var imageDef = Managers.DefineManager.Instance.QueryDefinesByType(); 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(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(); // 避免同一包内重复添加(查重) 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(); // if (drawOrderDef == null || drawOrderDef.Length == 0) // { // Debug.LogWarning("No DrawingOrderDef found."); // return; // } // // // 初始化包路径字典 // Dictionary 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(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(); // 创建未分割的精灵 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); } // /// // /// 向 bodyTexture 插入一张 Sprite。 // /// 如果包名、路径或部件名原本不存在,会自动建立对应的 Dictionary。 // /// // /// 包名 // /// 文件路径 // /// 身体部件名 // /// 要插入的 Sprite // 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>(); // bodyTexture[packageName] = pathDict; // } // // // 2) 处理文件路径层级 // if (!pathDict.TryGetValue(filePath, out var partDict)) // { // partDict = new Dictionary(); // pathDict[filePath] = partDict; // } // // // 3) 插入或覆盖部件名 // partDict[bodyPartName] = sprite; // } // /// // /// 查找身体部件的所有Sprite变体(支持带编号的图片) // /// // /// 包名 // /// 文件路径 // /// 身体部件名 // /// 按编号排序的Sprite数组,未找到时返回空数组 // 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(); // } } }