using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using BaseGames.Progression;
namespace BaseGames.Editor.Achievements
{
///
/// AchievementSO 自定义 Inspector(架构 16_SupportingModules §2.4)。
/// 在 conditions 数组中内联展示各 AchievementCondition SO 的关键字段,
/// 并在头部显示条件类型的中文名,提供 Ping 和删除按钮。
///
[CustomEditor(typeof(AchievementSO))]
public class AchievementSOEditor : UnityEditor.Editor
{
private static readonly Dictionary _conditionLabels = new()
{
{ "DefeatedBossCondition", "击败 Boss" },
{ "DefeatedAllBossesCondition", "击败全部 Boss" },
{ "EnteredRegionCondition", "到达区域" },
{ "MapExplorationCondition", "地图探索 %" },
{ "CollectedItemCondition", "收集物品" },
{ "CollectedAllCharmsCondition", "集满全部 Charm" },
{ "UnlockedAllAbilitiesCondition", "解锁全部能力" },
{ "NoHealRunCondition", "无治疗通关" },
{ "TimedBossKillCondition", "限时击败 Boss" },
{ "ParryCountCondition", "弹反 N 次" },
{ "NailClashCountCondition", "拼刀 N 次" },
{ "EventTriggeredCondition", "监听事件" },
};
private SerializedProperty _conditionsProp;
private void OnEnable()
{
_conditionsProp = serializedObject.FindProperty("conditions");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
// 绘制除 conditions 之外的所有默认字段
DrawPropertiesExcluding(serializedObject, "conditions");
EditorGUILayout.Space(8);
EditorGUILayout.LabelField("解锁条件(AND 全部满足)", EditorStyles.boldLabel);
for (int i = 0; i < _conditionsProp.arraySize; i++)
{
var elemProp = _conditionsProp.GetArrayElementAtIndex(i);
var condSO = elemProp.objectReferenceValue as AchievementCondition;
string typeName = condSO?.GetType().Name ?? "";
string label = condSO != null && _conditionLabels.TryGetValue(typeName, out var n)
? $"{n} [{condSO.name}]"
: (condSO != null ? $"{typeName} [{condSO.name}]" : "(未指定条件 SO)");
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// 标题行
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
if (condSO != null && GUILayout.Button("↗", GUILayout.Width(24)))
EditorGUIUtility.PingObject(condSO);
var prevColor = GUI.color;
GUI.color = Color.red * 0.9f;
if (GUILayout.Button("✕", GUILayout.Width(24)))
{
GUI.color = prevColor;
// 先将引用置空再删除,避免删除保留引用的 Unity 行为
_conditionsProp.GetArrayElementAtIndex(i).objectReferenceValue = null;
_conditionsProp.DeleteArrayElementAtIndex(i);
serializedObject.ApplyModifiedProperties();
break;
}
GUI.color = prevColor;
EditorGUILayout.EndHorizontal();
// 内联展开 SO 字段(可编辑)
if (condSO != null)
{
var innerSO = new SerializedObject(condSO);
innerSO.Update();
var prop = innerSO.GetIterator();
prop.NextVisible(true); // 跳过 m_Script
while (prop.NextVisible(false))
EditorGUILayout.PropertyField(prop, true);
if (innerSO.ApplyModifiedProperties())
EditorUtility.SetDirty(condSO);
}
else
{
EditorGUILayout.PropertyField(elemProp, GUIContent.none);
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(2);
}
// 添加按钮
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("+ 添加条件 SO 引用"))
_conditionsProp.arraySize++;
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
}
}