Files
zeling_v2/Assets/Scripts/Editor/Equipment/CharmEffectDrawer.cs
2026-05-12 15:34:08 +08:00

119 lines
4.6 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 System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using BaseGames.Equipment;
namespace BaseGames.Editor.Equipment
{
/// <summary>
/// 为 CharmSO.effectsList&lt;ICharmEffect&gt;)提供友好的 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