MeowmentArt/Assets/Editor/Art_Tools/ArtResourcePathFiller.cs
2026-01-27 15:41:53 +08:00

297 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using ArtResource;
using System.Linq;
namespace ArtTools
{
/// <summary>
/// 美术资源路径自动填充工具
///
/// 功能:
/// 1. 在保存SO时自动填充SpritePath和SpineAssetPath
/// 2. 提供手动批量更新所有SO的工具
///
/// 使用方法:
/// - 自动在ArtTableSO的OnValidate或保存时调用FillResourcePaths
/// - 手动:菜单 -> 美术工具 -> 更新所有美术资源路径
/// </summary>
public static class ArtResourcePathFiller
{
/// <summary>
/// 自动填充单个SO的资源路径
/// 应该在ArtTableSO保存时调用
/// </summary>
public static void FillResourcePaths(ArtTableSO table)
{
if (table == null || table.Items == null)
return;
bool hasChanges = false;
foreach (var item in table.Items)
{
// 填充Sprite路径
if (item.Sprite != null)
{
string spritePath = AssetDatabase.GetAssetPath(item.Sprite);
if (!string.IsNullOrEmpty(spritePath) && item.SpritePath != spritePath)
{
item.SpritePath = spritePath;
hasChanges = true;
}
}
else
{
// 引用为空时,清空路径
if (!string.IsNullOrEmpty(item.SpritePath))
{
item.SpritePath = "";
hasChanges = true;
}
}
// 填充Spine路径
if (item.SpineAsset != null)
{
string spinePath = AssetDatabase.GetAssetPath(item.SpineAsset);
if (!string.IsNullOrEmpty(spinePath) && item.SpineAssetPath != spinePath)
{
item.SpineAssetPath = spinePath;
hasChanges = true;
}
}
else
{
// 引用为空时,清空路径
if (!string.IsNullOrEmpty(item.SpineAssetPath))
{
item.SpineAssetPath = "";
hasChanges = true;
}
}
}
if (hasChanges)
{
EditorUtility.SetDirty(table);
Debug.Log($"[ArtResourcePathFiller] 已更新资源路径: {table.TableName} ({table.TableId})");
}
}
/// <summary>
/// 手动批量更新所有ArtTableSO的资源路径
/// </summary>
[MenuItem("美术工具/更新所有美术资源路径")]
public static void UpdateAllArtTablePaths()
{
// 查找所有ArtTableSO
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("[ArtResourcePathFiller] 未找到任何ArtTableSO文件");
return;
}
int updatedCount = 0;
int totalCount = guids.Length;
EditorUtility.DisplayProgressBar("更新美术资源路径", "正在扫描...", 0);
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table != null)
{
EditorUtility.DisplayProgressBar(
"更新美术资源路径",
$"处理: {table.TableName} ({i + 1}/{totalCount})",
(float)i / totalCount
);
FillResourcePaths(table);
updatedCount++;
}
}
EditorUtility.ClearProgressBar();
// 保存所有修改
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"[ArtResourcePathFiller] ✓ 批量更新完成: 处理了 {updatedCount} 个ArtTableSO");
EditorUtility.DisplayDialog(
"更新完成",
$"已更新 {updatedCount} 个美术资源表的路径信息\n\n现在可以在Runtime模式下正常加载资源了",
"确定"
);
}
/// <summary>
/// 验证所有SO的路径完整性
/// </summary>
[MenuItem("美术工具/验证美术资源路径完整性")]
public static void ValidateAllPaths()
{
string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
if (guids.Length == 0)
{
Debug.LogWarning("[ArtResourcePathFiller] 未找到任何ArtTableSO文件");
return;
}
int missingPathCount = 0;
int totalItemCount = 0;
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
if (table == null || table.Items == null)
continue;
foreach (var item in table.Items)
{
totalItemCount++;
// 检查Sprite
if (item.Sprite != null && string.IsNullOrEmpty(item.SpritePath))
{
Debug.LogWarning($"[{table.TableName}] 资源项 '{item.Name}' 有Sprite引用但缺少路径");
missingPathCount++;
}
// 检查Spine
if (item.SpineAsset != null && string.IsNullOrEmpty(item.SpineAssetPath))
{
Debug.LogWarning($"[{table.TableName}] 资源项 '{item.Name}' 有Spine引用但缺少路径");
missingPathCount++;
}
}
}
if (missingPathCount == 0)
{
Debug.Log($"[ArtResourcePathFiller] ✓ 验证通过: 所有 {totalItemCount} 个资源项的路径都完整");
EditorUtility.DisplayDialog(
"验证通过",
$"所有 {totalItemCount} 个资源项的路径都完整\n\n可以正常使用Runtime模式",
"确定"
);
}
else
{
Debug.LogError($"[ArtResourcePathFiller] ✗ 发现 {missingPathCount} 个缺少路径的资源项");
EditorUtility.DisplayDialog(
"发现问题",
$"发现 {missingPathCount} 个缺少路径的资源项\n\n建议运行【美术工具 -> 更新所有美术资源路径】修复",
"确定"
);
}
}
}
/// <summary>
/// ArtTableSO的自定义Inspector
/// 在Inspector底部添加"更新路径"按钮
/// </summary>
[CustomEditor(typeof(ArtTableSO))]
public class ArtTableSOInspector : Editor
{
public override void OnInspectorGUI()
{
// 绘制默认Inspector
DrawDefaultInspector();
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space(5);
var table = target as ArtTableSO;
if (table == null)
return;
// 统计信息
int spriteCount = table.Items.Count(item => item.Sprite != null);
int spineCount = table.Items.Count(item => item.SpineAsset != null);
int missingPathCount = table.Items.Count(item =>
(item.Sprite != null && string.IsNullOrEmpty(item.SpritePath)) ||
(item.SpineAsset != null && string.IsNullOrEmpty(item.SpineAssetPath))
);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField("资源路径状态", EditorStyles.boldLabel);
EditorGUILayout.LabelField($"Sprite数量: {spriteCount}");
EditorGUILayout.LabelField($"Spine数量: {spineCount}");
if (missingPathCount > 0)
{
var oldColor = GUI.contentColor;
GUI.contentColor = Color.red;
EditorGUILayout.LabelField($"⚠️ 缺少路径: {missingPathCount}");
GUI.contentColor = oldColor;
}
else if (spriteCount > 0 || spineCount > 0)
{
var oldColor = GUI.contentColor;
GUI.contentColor = Color.green;
EditorGUILayout.LabelField("✓ 路径完整");
GUI.contentColor = oldColor;
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(5);
// 更新路径按钮
if (GUILayout.Button("🔄 更新此表的资源路径", GUILayout.Height(30)))
{
ArtResourcePathFiller.FillResourcePaths(table);
EditorUtility.SetDirty(table);
AssetDatabase.SaveAssets();
EditorUtility.DisplayDialog("更新完成", $"已更新 {table.TableName} 的资源路径", "确定");
}
EditorGUILayout.Space(5);
EditorGUILayout.HelpBox(
"提示保存SO时会自动更新路径手动点击按钮可强制更新",
MessageType.Info
);
}
}
/// <summary>
/// 资源保存时自动填充路径
/// </summary>
public class ArtTableSOAssetPostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(
string[] importedAssets,
string[] deletedAssets,
string[] movedAssets,
string[] movedFromAssetPaths)
{
foreach (string assetPath in importedAssets)
{
// 只处理ArtTableSO
if (!assetPath.EndsWith(".asset"))
continue;
var table = AssetDatabase.LoadAssetAtPath<ArtTableSO>(assetPath);
if (table != null)
{
ArtResourcePathFiller.FillResourcePaths(table);
}
}
}
}
}
#endif