This commit is contained in:
SoulliesOfficial
2026-07-17 17:46:16 -04:00
parent b00ac27e3a
commit 40fa80cd70
1178 changed files with 51090 additions and 0 deletions

View File

@@ -0,0 +1,517 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using System.Collections.Generic;
namespace NBShaderEditor
{
public enum MixedBool
{
False = 0,
True = 1,
Mixed = -1
}
public class ShaderGUIItem
{
public const float MinLabelWidth = 120f;
public const float LabelWidthRatio = 0.4f;
public const float GlobalRectXOffset = -15f;
public const float GlobalRectWidthExpansion = 15f;
public const float UnityEditorGUIIndentWidth = 15f;
public const float EditorGUIIndentWidth = 10f;
public const float FoldOutArrowWidth = UnityEditorGUIIndentWidth;
public const float ControlResetGap = 3f;
public const float ControlIndentCompensation = 10f;
public ShaderPropertyInfo PropertyInfo;
public ShaderGUIItem ParentItem;
public List<ShaderGUIItem> ChildrenItemList = new List<ShaderGUIItem>();
public ShaderGUIRootItem RootItem;
public string PropertyName;
public GUIContent GuiContent;
private static int _parentControlDisabledDepth;
public virtual void InitTriggerByChild()//根Child一定要做这个事情
{
if ( PropertyInfo == null && PropertyName != null)
{
PropertyInfo = RootItem.PropertyInfoDic[PropertyName];
}
CheckIsPropertyModified();
}
public ShaderGUIItem(ShaderGUIRootItem rtItem,ShaderGUIItem parentItem=null)
{
RootItem = rtItem;
if (parentItem != null)
{
ParentItem = parentItem;
if (!parentItem.ChildrenItemList.Contains(this))
{
ParentItem.ChildrenItemList.Add(this);
}
}
}
public Rect BaseRect;
public Rect LabelRect;
public Rect ControlRect;
public Rect ResetRect;
private static readonly GUIContent TempHelpContent = new GUIContent();
public static float ResetButtonSize => EditorGUIUtility.singleLineHeight;
#if !UNITY_2022_1_OR_NEWER
private static Material s_ShaderDefaultIntValueMaterial;
#endif
public static int GetShaderPropertyDefaultIntValue(Shader shader, int propertyIndex)
{
#if UNITY_2022_1_OR_NEWER
return shader.GetPropertyDefaultIntValue(propertyIndex);
#else
if (s_ShaderDefaultIntValueMaterial == null ||
s_ShaderDefaultIntValueMaterial.shader != shader)
{
if (s_ShaderDefaultIntValueMaterial != null)
{
UnityEngine.Object.DestroyImmediate(s_ShaderDefaultIntValueMaterial);
}
// Unity 2021.3 has no int default API; use one hidden material as the shader default-value reader.
s_ShaderDefaultIntValueMaterial = new Material(shader)
{
hideFlags = HideFlags.HideAndDontSave
};
}
return s_ShaderDefaultIntValueMaterial.GetInteger(shader.GetPropertyName(propertyIndex));
#endif
}
public virtual void GetRect(bool applyControlIndentCompensation = true)
{
BaseRect = ApplyGlobalRectCompensation(RootItem.GetControlRect());
SplitLineRect(BaseRect, out LabelRect, out ControlRect, out ResetRect, applyControlIndentCompensation);
}
public static Rect ApplyGlobalRectCompensation(Rect rect)
{
rect.x += GlobalRectXOffset;
rect.width = Mathf.Max(0f, rect.width + GlobalRectWidthExpansion);
return rect;
}
public static Rect ApplyLabelIndentWidth(Rect rect)
{
float indentDelta = EditorGUI.indentLevel * (EditorGUIIndentWidth - UnityEditorGUIIndentWidth);
rect.x += indentDelta;
rect.width = Mathf.Max(0f, rect.width - indentDelta);
return rect;
}
public static Rect ApplyDirectLabelIndentWidth(Rect rect)
{
float indentOffset = EditorGUI.indentLevel * EditorGUIIndentWidth;
rect.x += indentOffset;
rect.width = Mathf.Max(0f, rect.width - indentOffset);
return rect;
}
public static float GetEditorLabelTextX(Rect labelRect)
{
return labelRect.x + EditorGUI.indentLevel * UnityEditorGUIIndentWidth;
}
public static float GetLabelWidth(Rect baseRect)
{
return Mathf.Max(MinLabelWidth, baseRect.width * LabelWidthRatio);
}
public static void SplitLineRect(
Rect baseRect,
out Rect labelRect,
out Rect controlRect,
out Rect resetRect,
bool applyControlIndentCompensation = true)
{
float labelWidth = GetLabelWidth(baseRect);
labelRect = baseRect;
labelRect.width = labelWidth;
labelRect = ApplyLabelIndentWidth(labelRect);
Rect controlAndResetRect = baseRect;
controlAndResetRect.x += labelWidth;
controlAndResetRect.width = Mathf.Max(0f, controlAndResetRect.width - labelWidth);
SplitControlAndResetRect(controlAndResetRect, out controlRect, out resetRect, applyControlIndentCompensation);
}
protected static GUIContent LocalizedContent(
string tableName,
string labelKey,
string labelFallback,
string tooltipKey = null,
string tooltipFallback = "")
{
return ShaderGUILocalization.MakeContent(tableName, labelKey, labelFallback, tooltipKey, tooltipFallback);
}
protected static GUIContent LocalizedInspectorContent(string tableName, string key, string fallback, string tip = "")
{
return ShaderGUILocalization.MakeInspectorContent(tableName, key, fallback, tip);
}
protected static string LocalizedText(string tableName, string key, string fallback = "")
{
return ShaderGUILocalization.GetInspectorText(tableName, key, fallback);
}
protected static string[] LocalizedOptions(string tableName, string key, string[] fallback)
{
return ShaderGUILocalization.GetInspectorOptions(tableName, key, fallback);
}
public static void SplitControlAndResetRect(
Rect baseRect,
out Rect controlRect,
out Rect resetRect,
bool applyControlIndentCompensation = true)
{
resetRect = baseRect;
resetRect.x = baseRect.xMax - ResetButtonSize;
resetRect.width = ResetButtonSize;
float controlIndentCompensation = applyControlIndentCompensation ? ControlIndentCompensation : 0f;
controlRect = baseRect;
controlRect.x -= controlIndentCompensation;
controlRect.width = Mathf.Max(0f, baseRect.width - ResetButtonSize - ControlResetGap + controlIndentCompensation);
}
protected Rect LayoutRect(float height = -1f)
{
return RootItem.GetControlRect(height);
}
protected void LayoutSpace(float height = -1f)
{
RootItem.Space(height);
}
protected void DrawLayoutHelpBox(string message, MessageType messageType)
{
TempHelpContent.text = message;
float width = Mathf.Max(1f, EditorGUIUtility.currentViewWidth + GlobalRectWidthExpansion + GlobalRectXOffset);
float height = Mathf.Max(
EditorGUIUtility.singleLineHeight * 2f,
EditorStyles.helpBox.CalcHeight(TempHelpContent, width));
Rect rect = ApplyGlobalRectCompensation(LayoutRect(height));
EditorGUI.HelpBox(rect, message, messageType);
TempHelpContent.text = string.Empty;
}
public virtual void OnGUI()
{
GetRect();
using (ParentControlDisabledScope())
{
EditorGUI.LabelField(LabelRect, GuiContent);
}
using (ParentControlDisabledScope())
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue;
bool animatedPropertyScope = BeginAnimatedPropertyBackground(BaseRect, PropertyInfo.Property);
using (new EditorGUIIndentLevelScope(0))
{
DrawController();
}
EndAnimatedPropertyBackground(animatedPropertyScope);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
OnEndChange();
}
}
DrawResetButton();
DrawBlock();
}
public void DrawResetButton()//如果重写OnGUI一定要记得调用DrawResetButton
{
CheckIsPropertyModified();
_resetButtonContent.text = HasModified ? "R" : "";
_resetButtonStyle = HasModified ? GUI.skin.button : GUI.skin.label;
using (ParentControlDisabledScope())
{
if (GUI.Button(ResetRect, _resetButtonContent, _resetButtonStyle))
{
ExecuteReset();
}
}
}
public virtual void DrawController()
{
}
protected static bool SetFloatIfDifferent(MaterialProperty property, float value)
{
if (property == null || Mathf.Approximately(property.floatValue, value))
{
return false;
}
property.floatValue = value;
return true;
}
protected static bool SetVectorIfDifferent(MaterialProperty property, Vector4 value)
{
if (property == null || Approximately(property.vectorValue, value))
{
return false;
}
property.vectorValue = value;
return true;
}
protected static bool SetColorIfDifferent(MaterialProperty property, Color value)
{
if (property == null)
{
return false;
}
Color current = property.colorValue;
if (Mathf.Approximately(current.r, value.r) &&
Mathf.Approximately(current.g, value.g) &&
Mathf.Approximately(current.b, value.b) &&
Mathf.Approximately(current.a, value.a))
{
return false;
}
property.colorValue = value;
return true;
}
protected readonly struct EditorGUIIndentLevelScope : System.IDisposable
{
private readonly int _indentLevel;
public EditorGUIIndentLevelScope(int indentLevel)
{
_indentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = indentLevel;
}
public void Dispose()
{
EditorGUI.indentLevel = _indentLevel;
}
}
protected bool IsParentControlDisabled => _parentControlDisabledDepth > 0;
protected EditorGUI.DisabledScope ParentControlDisabledScope(bool disabled = false)
{
return new EditorGUI.DisabledScope(IsParentControlDisabled || disabled);
}
protected readonly struct InheritedControlDisabledScope : System.IDisposable
{
private readonly bool _disabled;
public InheritedControlDisabledScope(bool disabled)
{
_disabled = disabled;
if (_disabled)
{
_parentControlDisabledDepth++;
}
}
public void Dispose()
{
if (_disabled)
{
_parentControlDisabledDepth = Mathf.Max(0, _parentControlDisabledDepth - 1);
}
}
}
public virtual void DrawBlock()
{
}
public virtual void OnEndChange()
{
CheckIsPropertyModified();
}
private readonly Dictionary<string, string> _animationPropertyPathDic = new Dictionary<string, string>();
protected bool BeginAnimatedPropertyBackground(Rect totalPosition, MaterialProperty property)
{
if (property == null || RootItem?.MatEditor == null)
{
return false;
}
RootItem.MatEditor.BeginAnimatedCheck(totalPosition, property);
return true;
}
protected void EndAnimatedPropertyBackground(bool scopeActive)
{
if (scopeActive && RootItem?.MatEditor != null)
{
RootItem.MatEditor.EndAnimatedCheck();
}
}
public bool IsPropertyAnimated(string propertyName, params string[] componentNames)
{
if (propertyName == null) return false;
if (AnimationMode.InAnimationMode())
{
foreach (var r in RootItem.RenderersUsingThisMaterial)
{
if (componentNames != null && componentNames.Length > 0)
{
foreach (string componentName in componentNames)
{
if (AnimationMode.IsPropertyAnimated(r, GetAnimationPropertyPath(propertyName, componentName)))
{
return true;
}
}
}
else if (AnimationMode.IsPropertyAnimated(r, GetAnimationPropertyPath(propertyName, string.Empty)))
{
return true;
}
}
}
return false;
}
private string GetAnimationPropertyPath(string propertyName, string componentName)
{
string key = string.IsNullOrEmpty(componentName) ? propertyName : propertyName + "." + componentName;
if (!_animationPropertyPathDic.TryGetValue(key, out string propertyPath))
{
propertyPath = string.IsNullOrEmpty(componentName)
? "material." + propertyName
: "material." + propertyName + "." + componentName;
_animationPropertyPathDic.Add(key, propertyPath);
}
return propertyPath;
}
#region ResetLogic
private GUIContent _resetButtonContent = new GUIContent("R","重置当前属性及子集属性(如有)");
private GUIStyle _resetButtonStyle;
public bool HasModified = false;
public bool PropertyIsDefaultValue = true;
public virtual void CheckIsPropertyModified(bool isCallByChild = false)
{
if (!isCallByChild)//只有自身Reset了才需要查询自己的状态是否正确
{
bool isDefaultValue = true;
if (PropertyInfo != null)
{
switch (ShaderGUIUnityCompat.GetPropertyType(PropertyInfo.Property))
{
case ShaderPropertyType.Float:
case ShaderPropertyType.Range:
float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index);
isDefaultValue = Mathf.Approximately(PropertyInfo.Property.floatValue, defaultValue);
break;
case ShaderPropertyType.Color:
Vector4 defaultColor = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index);
isDefaultValue = Approximately(PropertyInfo.Property.colorValue, defaultColor);
break;
case ShaderPropertyType.Vector:
Vector4 defaultVector = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index);
isDefaultValue = Approximately(PropertyInfo.Property.vectorValue, defaultVector);
break;
}
}
else
{
isDefaultValue = true;//如果没有Property则是看子集的情况
}
if (isDefaultValue == PropertyIsDefaultValue)
{
return;//如果状态没有改变,就不需要做任何操作
}
else
{
PropertyIsDefaultValue = isDefaultValue;
}
}
HasModified = !PropertyIsDefaultValue;
foreach (var childItem in ChildrenItemList)
{
HasModified |= childItem.HasModified;
}
ParentItem?.CheckIsPropertyModified(true);
}
public virtual void ExecuteReset(bool isCallByParent = false)
{
if (PropertyInfo != null)
{
switch (ShaderGUIUnityCompat.GetPropertyType(PropertyInfo.Property))
{
case ShaderPropertyType.Float:
case ShaderPropertyType.Range:
float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index);
PropertyInfo.Property.floatValue = defaultValue;
break;
case ShaderPropertyType.Color:
PropertyInfo.Property.colorValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index);
break;
case ShaderPropertyType.Vector:
PropertyInfo.Property.vectorValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index);
break;
}
PropertyIsDefaultValue = true;
}
foreach (var childItem in ChildrenItemList)
{
childItem.ExecuteReset(true);
}
HasModified = false;
if (!isCallByParent)//直接由用户触发重置
{
ParentItem?.CheckIsPropertyModified(true);
}
}
protected static bool Approximately(Vector4 a, Vector4 b)
{
return Mathf.Approximately(a.x, b.x) &&
Mathf.Approximately(a.y, b.y) &&
Mathf.Approximately(a.z, b.z) &&
Mathf.Approximately(a.w, b.w);
}
#endregion
}
}