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";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|