232 lines
8.5 KiB
C#
232 lines
8.5 KiB
C#
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<string, int> DirectionMapping = new Dictionary<string, int>(System.StringComparer.OrdinalIgnoreCase)
|
||
{
|
||
{"south", 0}, // 南方向 - 索引0
|
||
{"north", 1}, // 北方向 - 索引1
|
||
{"east", 2}, // 东方向 - 索引2
|
||
{"west", 2} // 西方向也映射到索引2(共用东方向的纹理)
|
||
};
|
||
|
||
/// <summary>
|
||
/// 加载角色所有部件的纹理
|
||
/// </summary>
|
||
public static Dictionary<string, Texture2D[]> LoadCharacterTextures(string rootPath)
|
||
{
|
||
var textures = new Dictionary<string, Texture2D[]>();
|
||
// 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载单个部件的所有方向纹理
|
||
/// </summary>
|
||
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<string> unmatchedFiles = new List<string>();
|
||
|
||
// 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<Texture2D>(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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查文件是否是图片格式
|
||
/// </summary>
|
||
private static bool IsImageFile(string fileName)
|
||
{
|
||
string ext = Path.GetExtension(fileName).ToLower();
|
||
return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".bmp";
|
||
}
|
||
}
|
||
|
||
} |