#if UNITY_EDITOR using Sirenix.OdinInspector.Editor; using UnityEditor; using UnityEngine; namespace SLSUtilities.Feedback.Editor { /// /// 为标记了 [ShakeCurvePreset] 的 AnimationCurve 字段绘制预设按钮组。 /// 按钮紧凑排列在曲线编辑器下方。 /// public sealed class ShakeCurvePresetDrawer : OdinAttributeDrawer { private const float BUTTON_HEIGHT = 18f; private const float BUTTON_SPACING = 2f; protected override void DrawPropertyLayout(GUIContent label) { // 先绘制默认的曲线字段 CallNextDrawer(label); // 绘制预设按钮行 DrawPresetButtons(); } private void DrawPresetButtons() { var presets = ShakeCurvePresets.All; if (presets == null || presets.Length == 0) return; Rect totalRect = EditorGUILayout.GetControlRect(false, BUTTON_HEIGHT); // 计算每个按钮的宽度 float totalSpacing = BUTTON_SPACING * (presets.Length - 1); float buttonWidth = (totalRect.width - totalSpacing) / presets.Length; GUIStyle buttonStyle = new GUIStyle(EditorStyles.miniButton) { fontSize = 8, padding = new RectOffset(1, 1, 1, 1), fixedHeight = BUTTON_HEIGHT }; for (int i = 0; i < presets.Length; i++) { float x = totalRect.x + i * (buttonWidth + BUTTON_SPACING); Rect buttonRect = new Rect(x, totalRect.y, buttonWidth, BUTTON_HEIGHT); if (GUI.Button(buttonRect, presets[i].name, buttonStyle)) { // 记录 Undo 以便撤销 if (Property.Tree.UnitySerializedObject != null) { Undo.RecordObject( Property.Tree.UnitySerializedObject.targetObject, $"Apply Shake Curve Preset: {presets[i].name}" ); } ValueEntry.SmartValue = presets[i].factory(); ValueEntry.ApplyChanges(); } } } } } #endif