using Godot; using System.IO; using System.Linq; using System.Collections.Generic; using System.Diagnostics; namespace Cosmobox { public static class CharacterLoader { // 支持的部件目录列表 private static readonly string[] ComponentFolders = { "body", "clothing", "hair", "hairBackground", "head", "leftEar", "rightEar" }; // 方向关键词映射到索引位置 private static readonly Dictionary DirectionMapping = new Dictionary(System.StringComparer.OrdinalIgnoreCase) { {"south", 0}, // 南方向 - 索引0 {"north", 1}, // 北方向 - 索引1 {"east", 2}, // 东方向 - 索引2 {"west", 2} // 西方向也映射到索引2(共用东方向的纹理) }; /// /// 加载角色所有部件的纹理 /// public static Dictionary LoadCharacterTextures(string rootPath) { var textures = new Dictionary(); // GD.Print($"开始加载角色纹理资源,根目录: {rootPath}"); // 检查根目录是否存在 if (!DirAccess.DirExistsAbsolute(rootPath)) { // GD.PrintErr($"错误:资源根目录不存在 - {rootPath}"); return textures; } using (var dir = DirAccess.Open(rootPath)) { if (dir == null) { GD.PrintErr($"错误:无法打开根目录 - {rootPath}"); return textures; } // GD.Print($"找到根目录,开始扫描部件文件夹..."); // 遍历所有支持的部件目录 foreach (string component in ComponentFolders) { string componentPath = Path.Combine(rootPath, component); // GD.Print($"检查部件: {component},路径: {componentPath}"); if (DirAccess.DirExistsAbsolute(componentPath)) { // GD.Print($"找到部件文件夹: {component}"); Texture2D[] componentTextures = LoadComponentTextures(componentPath); if (componentTextures != null && componentTextures.Length == 3) { // GD.Print($"成功加载部件: {component},纹理数量: 3"); textures[component] = componentTextures; } else { GD.PrintErr($"警告:部件{component}纹理加载不完整,实际数量: {componentTextures?.Length ?? 0}"); } } else { // GD.Print($"部件文件夹不存在: {component}"); } } } // GD.Print($"资源加载完成,成功部件: {textures.Count}/{ComponentFolders.Length}"); return textures; } /// /// 加载单个部件的所有方向纹理 /// private static Texture2D[] LoadComponentTextures(string folderPath) { Texture2D[] textures = new Texture2D[3]; var foundFiles = new List<(string path, int index)>(); // GD.Print($"加载部件文件夹: {folderPath}"); using (var dir = DirAccess.Open(folderPath)) { if (dir == null) { GD.PrintErr($"错误:无法打开部件目录 - {folderPath}"); return textures; } var status = dir.ListDirBegin(); if (status != Error.Ok) { GD.PrintErr($"错误:无法开始文件列表 ({status}) - {folderPath}"); return textures; } string fileName = dir.GetNext(); int fileCount = 0; int matchedCount = 0; List unmatchedFiles = new List(); // GD.Print($"开始扫描文件..."); while (!string.IsNullOrEmpty(fileName)) { fileCount++; if (!dir.CurrentIsDir()) { string filePath = Path.Combine(folderPath, fileName); // GD.Print($"处理文件 #{fileCount}: {fileName}"); // 检查文件扩展名 if (!IsImageFile(fileName)) { // GD.Print($"跳过非图片文件: {fileName}"); fileName = dir.GetNext(); continue; } bool matched = false; // 检测方向关键词 foreach (var kv in DirectionMapping) { if (fileName.Contains(kv.Key, System.StringComparison.OrdinalIgnoreCase)) { // GD.Print($"找到方向关键词 '{kv.Key}' -> 索引 {kv.Value}"); foundFiles.Add((filePath, kv.Value)); matched = true; matchedCount++; break; } } if (!matched) { GD.PrintErr($"警告:无法识别的方向名称 - {fileName}"); unmatchedFiles.Add(fileName); } } else { // GD.Print($"跳过子目录: {fileName}"); } fileName = dir.GetNext(); } dir.ListDirEnd(); // GD.Print($"文件夹扫描完成:"); // GD.Print($"- 总文件: {fileCount}"); // GD.Print($"- 匹配文件: {matchedCount}"); if (unmatchedFiles.Count > 0) { GD.PrintErr($"警告: {unmatchedFiles.Count} 个文件未包含方向关键词(south/north/east/west):"); foreach (var f in unmatchedFiles) { GD.PrintErr($" - {f}"); } } } // 检查是否所有方向都找到了文件 bool[] foundDirections = new bool[3]; // 加载纹理 foreach (var (path, index) in foundFiles) { if (index >= 0 && index < textures.Length) { if (textures[index] == null) { // GD.Print($"加载纹理: {Path.GetFileName(path)} -> 方向索引 {index}"); textures[index] = ResourceLoader.Load(path); foundDirections[index] = true; if (textures[index] == null) { GD.PrintErr($"错误:无法加载纹理资源 - {path}"); } } else { GD.Print($"跳过纹理: {Path.GetFileName(path)} -> 方向索引 {index}(已有更优先的纹理)"); } } else { GD.PrintErr($"错误:无效方向索引 {index} - {path}"); } } // 检查缺失的方向 for (int i = 0; i < foundDirections.Length; i++) { if (!foundDirections[i]) { string direction; if (i == 0) direction = "south"; else if (i == 1) direction = "north"; else direction = "east"; GD.PrintErr($"警告:缺少{direction}方向纹理"); } } return textures; } /// /// 检查文件是否是图片格式 /// private static bool IsImageFile(string fileName) { string ext = Path.GetExtension(fileName).ToLower(); return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".bmp"; } } }