119 lines
4.6 KiB
C#
119 lines
4.6 KiB
C#
#if UNITY_EDITOR
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using BaseGames.Equipment;
|
||
|
||
namespace BaseGames.Editor.Equipment
|
||
{
|
||
/// <summary>
|
||
/// 为 CharmSO.effects(List<ICharmEffect>)提供友好的 Inspector 体验(架构 09_ProgressionModule §4.1)。
|
||
/// - 下拉菜单选类型(显示中文名而非 C# 全称)
|
||
/// - 每条效果展开显示字段 + GetEffectDescription() 预览文字
|
||
/// - 支持单条删除
|
||
/// </summary>
|
||
[CustomEditor(typeof(CharmSO))]
|
||
public class CharmSOEditor : UnityEditor.Editor
|
||
{
|
||
// 已注册的所有 ICharmEffect 实现类型(反射收集)
|
||
private static readonly Type[] _effectTypes = CollectEffectTypes();
|
||
|
||
// 策划友好名称映射
|
||
private static readonly Dictionary<Type, string> _typeLabels = new()
|
||
{
|
||
{ typeof(StatModifierEffect), "属性加成" },
|
||
{ typeof(AttackSpeedEffect), "攻击速度" },
|
||
{ typeof(OnHitEffect), "命中触发" },
|
||
{ typeof(SoulSpellEffect), "灵魂法术" },
|
||
{ typeof(SkillNumericModifierEffect), "技能数值修改" },
|
||
{ typeof(SkillSlotOverrideEffect), "技能插槽替换" },
|
||
{ typeof(WeaponOverrideEffect), "武器替换" },
|
||
};
|
||
|
||
private SerializedProperty _effectsProp;
|
||
|
||
private void OnEnable()
|
||
=> _effectsProp = serializedObject.FindProperty("effects");
|
||
|
||
public override void OnInspectorGUI()
|
||
{
|
||
serializedObject.Update();
|
||
DrawPropertiesExcluding(serializedObject, "effects");
|
||
|
||
EditorGUILayout.Space(8);
|
||
EditorGUILayout.LabelField("Effects", EditorStyles.boldLabel);
|
||
|
||
if (_effectsProp != null)
|
||
{
|
||
for (int i = 0; i < _effectsProp.arraySize; i++)
|
||
{
|
||
var elemProp = _effectsProp.GetArrayElementAtIndex(i);
|
||
var effect = elemProp.managedReferenceValue as ICharmEffect;
|
||
string label = effect != null && _typeLabels.TryGetValue(effect.GetType(), out var n)
|
||
? n : (effect?.GetType().Name ?? "null");
|
||
|
||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
|
||
|
||
if (GUILayout.Button("✕", GUILayout.Width(24)))
|
||
{
|
||
_effectsProp.DeleteArrayElementAtIndex(i);
|
||
serializedObject.ApplyModifiedProperties();
|
||
break;
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
EditorGUILayout.PropertyField(elemProp, GUIContent.none, true);
|
||
|
||
if (effect != null)
|
||
EditorGUILayout.LabelField(effect.GetEffectDescription(),
|
||
EditorStyles.miniLabel);
|
||
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space(2);
|
||
}
|
||
}
|
||
|
||
// 添加效果按钮(下拉菜单)
|
||
if (GUILayout.Button("+ 添加效果"))
|
||
{
|
||
var menu = new GenericMenu();
|
||
foreach (var t in _effectTypes)
|
||
{
|
||
var captured = t;
|
||
string menuLabel = _typeLabels.GetValueOrDefault(t, t.Name);
|
||
menu.AddItem(new GUIContent(menuLabel), false, () =>
|
||
{
|
||
if (_effectsProp == null) return;
|
||
_effectsProp.arraySize++;
|
||
_effectsProp
|
||
.GetArrayElementAtIndex(_effectsProp.arraySize - 1)
|
||
.managedReferenceValue = Activator.CreateInstance(captured);
|
||
serializedObject.ApplyModifiedProperties();
|
||
});
|
||
}
|
||
menu.ShowAsContext();
|
||
}
|
||
|
||
serializedObject.ApplyModifiedProperties();
|
||
}
|
||
|
||
private static Type[] CollectEffectTypes()
|
||
{
|
||
var baseType = typeof(ICharmEffect);
|
||
return AppDomain.CurrentDomain.GetAssemblies()
|
||
.SelectMany(a =>
|
||
{
|
||
try { return a.GetTypes(); }
|
||
catch { return Array.Empty<Type>(); }
|
||
})
|
||
.Where(t => t.IsClass && !t.IsAbstract && baseType.IsAssignableFrom(t))
|
||
.ToArray();
|
||
}
|
||
}
|
||
}
|
||
#endif
|