材质修改

This commit is contained in:
tianmo committed 2026-10-10 20:12:37 +08:00
1 parent 7c1fedab2c
commit 5d58cb3743
12 files changed
+814 -8

No files matched your search

+195
View File
@@ -0,0 +1,195 @@
using UnityEditor;
using UnityEngine;
// UIMask 的材质面板:分组折叠 + 中文标签。
// shader 里用 CustomEditor "UIMaskShaderGUI" 挂上这个类。
// 折叠状态存在 EditorPrefs(按组名),重编译/重启 Unity 后仍然保持。
// 未在 Groups 里列出的属性(_SrcBlend/_DstBlend/_Cull、硬边溶解、Stencil 等)不绘制。
public class UIMaskShaderGUI : ShaderGUI
{
private const string FoldKeyPrefix = "UIMask.GUI.";
private class Group
{
public string Label;
public string Toggle; // 组的启用开关(没有则为 null)
public string[] Props; // 组内属性,按显示顺序
}
private static readonly Group[] Groups =
{
new Group
{
Label = "基础",
Props = new[] { "_BlendMode", "_RenderFace", "_TintColor", "_GlowScale|_AlphaScale", "_MainTex" }
},
new Group
{
Label = "UV 滚动",
Toggle = "_UseUvAni",
Props = new[] { "_SpeedU|_SpeedV" }
},
new Group
{
Label = "UV 扰乱",
Toggle = "_UseUvDistortion",
Props = new[] { "_UVNoiseTex", "_Distortion", "_NoiseScroll" }
},
new Group
{
Label = "遮罩 Mask",
Toggle = "_UseMask",
Props = new[] { "_UseMaskUvAni", "_Mask", "_MaskChannel", "_MaskSpeedU|_MaskSpeedV" }
},
new Group
{
Label = "溶解",
Toggle = "_UseDissolve",
Props = new[] { "_DissolveTex", "_DissolveChannel", "_Dissolve", "_DissolveWidth" }
},
new Group
{
Label = "UI 裁切",
Toggle = "_UseUIMaskClip",
Props = new[] { "_ClipRect" }
},
new Group
{
Label = "顶点遮罩",
Toggle = "_UseVertexMask",
Props = new[] { "_VertexOffset" }
},
};
public override void OnGUI(MaterialEditor editor, MaterialProperty[] props)
{
foreach (Group group in Groups)
{
DrawGroup(editor, props, group);
}
}
private static void DrawGroup(MaterialEditor editor, MaterialProperty[] props, Group group)
{
MaterialProperty toggle = string.IsNullOrEmpty(group.Toggle)
? null
: FindProperty(group.Toggle, props, false);
string foldKey = FoldKeyPrefix + group.Label;
// 默认只展开"基础",其余收起(收起时右边的勾选状态仍能看出该功能有没有开)
bool expanded = EditorPrefs.GetBool(foldKey, group.Label == "基础");
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.BeginHorizontal();
bool newExpanded = EditorGUILayout.Foldout(expanded, group.Label, true, EditorStyles.foldoutHeader);
if (toggle != null)
{
GUILayout.FlexibleSpace();
editor.ShaderProperty(toggle, GUIContent.none, 0);
}
EditorGUILayout.EndHorizontal();
if (newExpanded != expanded)
{
EditorPrefs.SetBool(foldKey, newExpanded);
}
if (newExpanded)
{
EditorGUI.indentLevel++;
DrawProps(editor, props, group.Props);
EditorGUI.indentLevel--;
}
EditorGUILayout.EndVertical();
}
// group.Props 里一项 = 一行;写 "A|B" 表示这两个单值属性并排在同一行
private static void DrawProps(MaterialEditor editor, MaterialProperty[] props, string[] rows)
{
foreach (string row in rows)
{
int separator = row.IndexOf('|');
if (separator < 0)
{
DrawOne(editor, props, row);
continue;
}
MaterialProperty left = FindProperty(row.Substring(0, separator), props, false);
MaterialProperty right = FindProperty(row.Substring(separator + 1), props, false);
if (left != null && right != null && IsSingleValue(left) && IsSingleValue(right))
{
DrawTwoPerRow(editor, left, right);
}
else
{
// 其中一边不存在或不是单值属性,退回各自一行,避免出错
if (left != null) DrawOne(editor, props, left.name);
if (right != null) DrawOne(editor, props, right.name);
}
}
}
private static void DrawOne(MaterialEditor editor, MaterialProperty[] props, string name)
{
MaterialProperty prop = FindProperty(name, props, false);
if (prop == null)
{
return;
}
if (prop.type == MaterialProperty.PropType.Texture)
{
// Unity 原生贴图选择器(缩略图 + 平铺/偏移都由它画)
bool scaleOffset = (prop.flags & MaterialProperty.PropFlags.NoScaleOffset) == 0;
editor.TextureProperty(prop, prop.displayName, scaleOffset);
return;
}
if (prop.type == MaterialProperty.PropType.Vector)
{
DrawVectorTwoLines(prop);
return;
}
editor.ShaderProperty(prop, prop.displayName);
}
private static bool IsSingleValue(MaterialProperty prop)
{
return prop.type == MaterialProperty.PropType.Float
|| prop.type == MaterialProperty.PropType.Int;
}
// 两个单值属性并排一行;半行放不下默认标签宽度,所以临时收窄标签
private static void DrawTwoPerRow(MaterialEditor editor, MaterialProperty left, MaterialProperty right)
{
Rect row = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
const float gap = 6f;
float half = (row.width - gap) * 0.5f;
float oldLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = Mathf.Min(oldLabelWidth, half * 0.5f);
editor.ShaderProperty(new Rect(row.x, row.y, half, row.height), left, new GUIContent(left.displayName));
editor.ShaderProperty(new Rect(row.x + half + gap, row.y, half, row.height), right, new GUIContent(right.displayName));
EditorGUIUtility.labelWidth = oldLabelWidth;
}
// 四分量向量:属性名独占一行,X/Y/Z/W 单独占下一行(默认是挤在同一行,名字会被切掉)
private static void DrawVectorTwoLines(MaterialProperty prop)
{
EditorGUILayout.LabelField(prop.displayName, EditorStyles.label);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = prop.hasMixedValue;
Vector4 value = EditorGUILayout.Vector4Field(GUIContent.none, prop.vectorValue);
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
prop.vectorValue = value;
}
}
}