297 lines
10 KiB
C#
297 lines
10 KiB
C#
#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
|