材质修改
This commit is contained in:
1 parent
7c1fedab2c
commit
5d58cb3743
12 files changed
+814
-8
No files matched your search
@@ -0,0 +1,101 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
// UIMask 材质面板的"下拉框 -> 隐藏属性"绘制器基类。
|
||||
// ShaderLab 的 Blend / Cull 只接受数字属性,没法用枚举直接切换,
|
||||
// 所以由绘制器把下拉框的选项写进隐藏属性。
|
||||
// 每次绘制面板都会同步一次,所以从其它 shader(例如 URP/Lit 也有同名的
|
||||
// _SrcBlend / _DstBlend / _Cull)切过来的材质会被自动纠正。
|
||||
// 注意:attribute 的名字必须是子类的简单类名,Unity 按类名查找绘制器。
|
||||
public abstract class UIMaskEnumDrawer : MaterialPropertyDrawer
|
||||
{
|
||||
protected abstract string[] Options { get; }
|
||||
|
||||
// 把下拉框当前选项同步到材质上的隐藏属性
|
||||
protected abstract void Apply(MaterialEditor editor, int index);
|
||||
|
||||
public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int index = Mathf.Clamp(Mathf.RoundToInt(prop.floatValue), 0, Options.Length - 1);
|
||||
index = EditorGUI.Popup(position, label, index, Options);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
prop.floatValue = index;
|
||||
}
|
||||
|
||||
Apply(editor, index);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
protected void SetValue(MaterialEditor editor, string propertyName, float value)
|
||||
{
|
||||
foreach (Object target in editor.targets)
|
||||
{
|
||||
var material = target as Material;
|
||||
if (material == null || !material.HasProperty(propertyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Mathf.Approximately(material.GetFloat(propertyName), value))
|
||||
{
|
||||
material.SetFloat(propertyName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 混合模式:加色 / 普通混合
|
||||
// 数值对应 UnityEngine.Rendering.BlendMode:SrcAlpha=5, One=1, OneMinusSrcAlpha=10
|
||||
public class UIMaskBlendMode : UIMaskEnumDrawer
|
||||
{
|
||||
private static readonly string[] Items = { "Additive", "AlphaBlend" };
|
||||
|
||||
protected override string[] Options => Items;
|
||||
|
||||
protected override void Apply(MaterialEditor editor, int index)
|
||||
{
|
||||
SetValue(editor, "_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
SetValue(editor, "_DstBlend", index == 0
|
||||
? (float)UnityEngine.Rendering.BlendMode.One
|
||||
: (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染面:只渲染前面 / 只渲染后面 / 双面
|
||||
// ShaderLab 的 Cull 取值:Off=0(双面)、Front=1(剔除正面,即只渲染后面)、Back=2(剔除背面,即只渲染前面)
|
||||
public class UIMaskRenderFace : UIMaskEnumDrawer
|
||||
{
|
||||
private const float CullOff = 0f;
|
||||
private const float CullFront = 1f;
|
||||
private const float CullBack = 2f;
|
||||
|
||||
private static readonly string[] Items = { "前面", "背面", "双面" };
|
||||
|
||||
protected override string[] Options => Items;
|
||||
|
||||
protected override void Apply(MaterialEditor editor, int index)
|
||||
{
|
||||
float cull = index == 0 ? CullBack : (index == 1 ? CullFront : CullOff);
|
||||
SetValue(editor, "_Cull", cull);
|
||||
}
|
||||
}
|
||||
|
||||
// 贴图通道:R / G / B / A(值直接被 shader 采样时使用,不需要写隐藏属性)
|
||||
// 默认 A(index = 3)
|
||||
public class UIMaskChannel : UIMaskEnumDrawer
|
||||
{
|
||||
private static readonly string[] Items = { "R 通道", "G 通道", "B 通道", "A 通道" };
|
||||
|
||||
protected override string[] Options => Items;
|
||||
|
||||
protected override void Apply(MaterialEditor editor, int index)
|
||||
{
|
||||
// 下拉框的值本身就是要采样的通道号,无需同步到别的属性
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de421d7ff241b44acba639824a11e4b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 621d15512511a4cbdaf5fc4e9f99dfa3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user