171 lines
6.6 KiB
C#
171 lines
6.6 KiB
C#
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using OfficeOpenXml;
|
||
using ArtResource;
|
||
|
||
namespace DesignTools
|
||
{
|
||
/// <summary>
|
||
/// 一次性工具:将 Emoji.xlsx / Face.xlsx / Avatar.xlsx 的 Icon 字段从 ArtItemData.Id 迁移为 ArtItemData.Name
|
||
/// 使用完毕后可删除此文件
|
||
/// </summary>
|
||
public static class MigrateIconFormatTool
|
||
{
|
||
private static readonly string[] SO_SEARCH_PATHS = new[]
|
||
{
|
||
"Assets/Art_SubModule/Art_SO",
|
||
"Assets/Art_SubModule/Art_SO/Collections"
|
||
};
|
||
|
||
private struct MigrationTarget
|
||
{
|
||
public string ExcelName;
|
||
public string SheetName;
|
||
public string SOTableName;
|
||
}
|
||
|
||
private static readonly MigrationTarget[] Targets = new[]
|
||
{
|
||
new MigrationTarget { ExcelName = "Emoji.xlsx", SheetName = "Emoji", SOTableName = "EmojiResource" },
|
||
new MigrationTarget { ExcelName = "Face.xlsx", SheetName = "Face", SOTableName = "HeadResource" },
|
||
new MigrationTarget { ExcelName = "Avatar.xlsx", SheetName = "Avatar", SOTableName = "HeadFrameResource" },
|
||
};
|
||
|
||
[MenuItem("策划工具/一次性迁移/Icon格式 ID→Name (Emoji+Face+Avatar)")]
|
||
public static void Execute()
|
||
{
|
||
// 1. 选择 Docs/config 目录
|
||
string configDir = EditorUtility.OpenFolderPanel("选择 Docs/config 目录(包含 Emoji.xlsx、Face.xlsx、Avatar.xlsx)", "", "");
|
||
if (string.IsNullOrEmpty(configDir)) return;
|
||
|
||
// 2. 加载所有 ArtTableSO
|
||
var allArtTables = new List<ArtTableSO>();
|
||
foreach (string searchPath in SO_SEARCH_PATHS)
|
||
{
|
||
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO", new[] { searchPath });
|
||
foreach (string guid in guids)
|
||
{
|
||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||
var so = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
|
||
if (so != null && !allArtTables.Any(x => x.TableName == so.TableName))
|
||
allArtTables.Add(so);
|
||
}
|
||
}
|
||
|
||
if (allArtTables.Count == 0)
|
||
{
|
||
EditorUtility.DisplayDialog("错误", "未找到任何 ArtTableSO 资源", "确定");
|
||
return;
|
||
}
|
||
|
||
int totalMigrated = 0;
|
||
int totalSkipped = 0;
|
||
int totalErrors = 0;
|
||
var allMessages = new List<string>();
|
||
|
||
foreach (var target in Targets)
|
||
{
|
||
string excelPath = Path.Combine(configDir, target.ExcelName);
|
||
if (!File.Exists(excelPath))
|
||
{
|
||
allMessages.Add($"[{target.ExcelName}] 文件不存在,跳过");
|
||
continue;
|
||
}
|
||
|
||
var tableSO = allArtTables.FirstOrDefault(x => x.TableName == target.SOTableName);
|
||
if (tableSO == null)
|
||
{
|
||
allMessages.Add($"[{target.ExcelName}] 未找到 ArtTableSO: {target.SOTableName},跳过");
|
||
totalErrors++;
|
||
continue;
|
||
}
|
||
|
||
// 备份
|
||
string backupPath = excelPath + ".bak";
|
||
File.Copy(excelPath, backupPath, true);
|
||
|
||
int migrated = 0, skipped = 0, errors = 0;
|
||
|
||
using (var package = new ExcelPackage(new FileInfo(excelPath)))
|
||
{
|
||
var ws = package.Workbook.Worksheets[target.SheetName];
|
||
if (ws == null)
|
||
{
|
||
allMessages.Add($"[{target.ExcelName}] 未找到 Sheet: {target.SheetName},跳过");
|
||
totalErrors++;
|
||
continue;
|
||
}
|
||
|
||
// 找 Icon 列和 Id 列
|
||
int iconCol = -1, idCol = -1;
|
||
int colCount = ws.Dimension?.Columns ?? 0;
|
||
for (int c = 1; c <= colCount; c++)
|
||
{
|
||
string h = ws.Cells[1, c].Text;
|
||
if (h == "Icon") iconCol = c;
|
||
else if (h == "Id") idCol = c;
|
||
}
|
||
|
||
if (iconCol < 0)
|
||
{
|
||
allMessages.Add($"[{target.ExcelName}] 未找到 Icon 列,跳过");
|
||
totalErrors++;
|
||
continue;
|
||
}
|
||
|
||
int rowCount = ws.Dimension?.Rows ?? 0;
|
||
for (int row = 3; row <= rowCount; row++)
|
||
{
|
||
string iconText = ws.Cells[row, iconCol].Text.Trim();
|
||
if (string.IsNullOrEmpty(iconText))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// 判断是否是旧格式(纯数字)
|
||
if (!int.TryParse(iconText, out int artItemId))
|
||
{
|
||
// 已经是Name格式
|
||
skipped++;
|
||
continue;
|
||
}
|
||
|
||
string rowId = idCol > 0 ? ws.Cells[row, idCol].Text : row.ToString();
|
||
|
||
var artItem = tableSO.Items.FirstOrDefault(x => x.Id == artItemId);
|
||
if (artItem == null)
|
||
{
|
||
errors++;
|
||
allMessages.Add($"[{target.ExcelName}] Row {row} Id={rowId}: {target.SOTableName} 中无 ArtItemId={artItemId}");
|
||
continue;
|
||
}
|
||
|
||
ws.Cells[row, iconCol].Value = artItem.Name;
|
||
migrated++;
|
||
}
|
||
|
||
package.Save();
|
||
}
|
||
|
||
totalMigrated += migrated;
|
||
totalSkipped += skipped;
|
||
totalErrors += errors;
|
||
allMessages.Add($"[{target.ExcelName}] 成功: {migrated}, 跳过: {skipped}, 错误: {errors} (备份: {backupPath})");
|
||
}
|
||
|
||
// 报告
|
||
string msg = $"Icon 迁移完成!\n\n" +
|
||
$"总计成功: {totalMigrated} 条\n" +
|
||
$"已是新格式(跳过): {totalSkipped} 条\n" +
|
||
$"错误: {totalErrors} 条\n\n" +
|
||
string.Join("\n", allMessages);
|
||
|
||
EditorUtility.DisplayDialog("迁移结果", msg, "确定");
|
||
Debug.Log(msg);
|
||
}
|
||
}
|
||
}
|