升级水插件

This commit is contained in:
2026-01-08 22:30:55 +08:00
parent febff82d24
commit ca68084264
415 changed files with 18138 additions and 7134 deletions

View File

@@ -1,4 +1,4 @@
// Crest Water System
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using System.Diagnostics.CodeAnalysis;
@@ -15,7 +15,7 @@ namespace WaveHarmonic.Crest.Editor
/// <summary>
/// Provides general helper functions for the editor.
/// </summary>
static class EditorHelpers
static partial class EditorHelpers
{
internal static ComputeShader s_VisualizeNegativeValuesShader;
internal static ComputeShader VisualizeNegativeValuesShader
@@ -227,27 +227,6 @@ namespace WaveHarmonic.Crest.Editor
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
}
}
static readonly MethodInfo s_ButtonWithDropdownList = typeof(EditorGUI).GetMethod
(
"ButtonWithDropdownList",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
null,
new System.Type[] { typeof(GUIContent), typeof(string[]), typeof(GenericMenu.MenuFunction2), typeof(GUILayoutOption[]) },
null
);
static readonly GUILayoutOption[] s_GUILayoutOptionsZero;
public static bool ButtonWithDropdownList(GUIContent name, string[] names, GenericMenu.MenuFunction2 callback)
{
if (names == null)
{
return GUILayout.Button(name);
}
return (bool)s_ButtonWithDropdownList.Invoke(null, new object[] { name, names, callback, s_GUILayoutOptionsZero });
}
}
static partial class Extensions
@@ -269,4 +248,241 @@ namespace WaveHarmonic.Crest.Editor
return tag.name;
}
}
static partial class EditorHelpers
{
const int k_ButtonDropDownWidth = 15;
static readonly GUIContent s_ButtonDropDownIcon = new(EditorGUIUtility.FindTexture("icon dropdown@2x"));
static readonly PropertyInfo s_TopLevel = typeof(GUILayoutUtility).GetProperty("topLevel", BindingFlags.NonPublic | BindingFlags.Static);
static readonly MethodInfo s_GetLast = typeof(GUILayoutUtility).Assembly.GetType("UnityEngine.GUILayoutGroup").GetMethod("GetLast", BindingFlags.Public | BindingFlags.Instance);
// Only way to identify the caller is its rect.
static Rect s_ButtonChooser;
static int s_ButtonChoice = -2;
// Normal button or split button with dropdown.
public static bool Button
(
GUIContent label,
out int choice,
string[] labels,
bool disableMain = false,
bool disableDropDown = false,
bool centerLabel = false,
bool expandWidth = true,
int minimumWidth = 0
)
{
choice = -2;
var chosen = false;
var hasDropDown = labels?.Length > 0;
var skin = GUI.skin.button;
using (new EditorGUI.DisabledGroupScope(disableMain))
{
var style = new GUIStyle(hasDropDown ? EditorStyles.miniButtonLeft : EditorStyles.miniButton)
{
padding = skin.padding,
stretchHeight = skin.stretchHeight,
fixedHeight = skin.fixedHeight
};
var width = style.CalcSize(label).x + style.padding.left +
style.padding.right + style.border.left + style.border.right;
width = Mathf.Max(width, minimumWidth);
// TODO: Add option to disable this (consistent width).
if (!hasDropDown && minimumWidth > 0) width += k_ButtonDropDownWidth;
if (centerLabel && hasDropDown) style.padding.left += k_ButtonDropDownWidth;
if (GUILayout.Button(label, style, expandWidth ? GUILayout.ExpandWidth(true) : GUILayout.Width(width)))
{
choice = -1;
chosen = true;
}
}
if (hasDropDown)
{
using (new EditorGUI.DisabledGroupScope(disableDropDown))
{
// TODO: color interior border same as exterior (lighten).
var style = new GUIStyle(EditorStyles.miniButtonRight)
{
padding = new(1, 1, 3, 3),
stretchHeight = skin.stretchHeight,
fixedHeight = skin.fixedHeight
};
var rect = (Rect)s_GetLast.Invoke(s_TopLevel.GetValue(null), null);
rect.width += k_ButtonDropDownWidth;
if (s_ButtonChoice > -1 && s_ButtonChooser == rect)
{
choice = s_ButtonChoice;
chosen = true;
s_ButtonChoice = -2;
s_ButtonChooser = Rect.zero;
}
if (GUILayout.Button(s_ButtonDropDownIcon, style, GUILayout.Width(k_ButtonDropDownWidth), GUILayout.ExpandHeight(true)))
{
var menu = new GenericMenu();
for (var i = 0; i < labels.Length; i++)
{
menu.AddItem(new(labels[i]), false, x => { s_ButtonChoice = (int)x; s_ButtonChooser = rect; }, i);
}
menu.DropDown(rect);
}
}
}
return chosen;
}
}
static partial class EditorHelpers
{
// Adapted from (public API may support this in future):
// com.unity.splines@2.7.2/Editor/Components/SplineContainerEditor.cs
static GUIStyle s_HelpLabelStyle;
static GUIStyle HelpLabelStyle => s_HelpLabelStyle ??= new(EditorStyles.label)
{
wordWrap = EditorStyles.helpBox.wordWrap,
fontSize = EditorStyles.helpBox.fontSize,
padding = new(-2, 0, 0, 0),
richText = true,
};
static readonly MethodInfo s_GetHelpIcon = typeof(EditorGUIUtility).GetMethod("GetHelpIcon", BindingFlags.Static | BindingFlags.NonPublic);
internal static int? HelpBox
(
GUIContent message,
MessageType type,
GUIContent button = null,
string[] buttons = null,
bool buttonCenterLabel = false,
int buttonMinimumWidth = 0
)
{
return HelpBox
(
message,
new GUIContent((Texture2D)s_GetHelpIcon.Invoke(null, new object[] { type })),
button,
buttons,
buttonCenterLabel,
buttonMinimumWidth
);
}
internal static int? HelpBox
(
GUIContent message,
GUIContent icon,
GUIContent button = null,
string[] buttons = null,
bool buttonCenterLabel = false,
int buttonMinimumWidth = 0
)
{
int? result = null;
// Box
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
// Icon
EditorGUIUtility.SetIconSize(new(32f, 32f));
EditorGUILayout.LabelField(icon, GUILayout.Width(34), GUILayout.MinHeight(34), GUILayout.ExpandHeight(true));
EditorGUIUtility.SetIconSize(Vector2.zero);
// Text
EditorGUILayout.LabelField(message, HelpLabelStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
// Button
if (button != null)
{
GUILayout.FlexibleSpace();
EditorGUILayout.BeginVertical();
GUILayout.FlexibleSpace();
EditorGUILayout.BeginHorizontal();
if (Button(button, out var choice, buttons, centerLabel: buttonCenterLabel, minimumWidth: buttonMinimumWidth, expandWidth: false))
{
result = choice;
}
EditorGUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndHorizontal();
return result;
}
}
namespace Internal
{
static class Extensions
{
// Recursively find the field owner (instance).
public static bool FindOwner(this FieldInfo field, ref object target)
{
if (field.DeclaringType.IsAssignableFrom(target.GetType()))
{
return true;
}
return field.FindOwnerInFields(ref target);
}
public static bool FindOwnerInFields(this FieldInfo targetField, ref object target)
{
if (target == null)
{
return false;
}
var fields = target.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var field in fields)
{
if (field.GetCustomAttribute<SerializeReference>() == null)
{
continue;
}
var value = field.GetValue(target);
if (value == null)
{
continue;
}
if (targetField.DeclaringType.IsAssignableFrom(value.GetType()))
{
target = value;
return true;
}
if (FindOwnerInFields(targetField, ref value))
{
return true;
}
}
return false;
}
}
}
}