如果是自定义shader的通用面板可以看我之前的文章 Unity3D研究院之材质Shader通用面板(一百二十一) 这篇文章和它的原理是一样的。
首先shader graph有个很麻烦的问题就是自定义的keyword始终在面板的最下面不能和普通的属性进行排序,而且也无法展开分组的功能。为了实现通用面板,我们要定义一定的规则
XX面板 溶解面板
XX参数1 溶解参数1
XX参数2 溶解参数2
如果命名中包含面板会特意提出来,如果下面的属性包含XX部分则合并在一个分组中,自定义的keyword始终在最下面的问题,有可以根据命名的规则来进行排序,我会始终让宏在分页的第一位。
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
public class CustomShaderGraphGUI : ShaderGUI
{
public class GraphData
{
public string groupName; //组名
public MaterialProperty title; //标题
public List<GraphData> child;//表示有子节点
}
static Dictionary<string, GraphData> s_GraphProperty = new Dictionary<string, GraphData>();
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
Shader shader = (materialEditor.target as Material).shader;
s_GraphProperty.Clear();
for (int i = 0; i < properties.Length; i++)
{
var propertie = properties[i];
var displayName = propertie.displayName;
GraphData data = new GraphData() { title = propertie };
if (TryGetGroupName(displayName, out var groupName))
{
if (!s_GraphProperty.TryGetValue(groupName, out var graph))
{
data.child = new List<GraphData>();
data.groupName = groupName;
s_GraphProperty[groupName] = data;
}
else
{
var attributes = shader.GetPropertyAttributes(i);
bool keyword = Array.FindIndex(attributes, (t) => (t == "Toggle" || t.StartsWith("KeywordEnum"))) >= 0;
if (keyword)
graph.child.Insert(0, data);
else
graph.child.Add(data);
}
}
else
{
s_GraphProperty[displayName] = data;
}
}
PropertiesDefaultGUI(materialEditor);
}
private static int s_ControlHash = "EditorTextField".GetHashCode();
public void PropertiesDefaultGUI(MaterialEditor materialEditor)
{
var f = materialEditor.GetType().GetField("m_InfoMessage", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (f != null)
{
string m_InfoMessage = (string)f.GetValue(materialEditor);
materialEditor.SetDefaultGUIWidths();
if (m_InfoMessage != null)
{
EditorGUILayout.HelpBox(m_InfoMessage, MessageType.Info);
}
else
{
GUIUtility.GetControlID(s_ControlHash, FocusType.Passive, new Rect(0f, 0f, 0f, 0f));
}
}
foreach (var props in s_GraphProperty.Values)
{
MaterialProperty prop = props.title;
if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) == MaterialProperty.PropFlags.None)
{
if(props.child!=null && props.child.Count > 0)
{
//如果发现有面板,使用Foldout来绘制
prop.floatValue = Convert.ToSingle(EditorGUILayout.Foldout(Convert.ToBoolean(prop.floatValue), prop.displayName));
if (prop.floatValue == 1f)
{
foreach (var child in props.child)
{
DrawGUI(materialEditor, child.title, true);
}
}
}
else
{
DrawGUI(materialEditor, prop, false);
}
}
}
EditorGUILayout.Space();
EditorGUILayout.Space();
if (SupportedRenderingFeatures.active.editableMaterialRenderQueue)
{
materialEditor.RenderQueueField();
}
materialEditor.EnableInstancingField();
materialEditor.DoubleSidedGIField();
//unity 2020 新版本功能 ,老版本需要注释掉
materialEditor.EmissionEnabledProperty();
}
void DrawGUI(MaterialEditor materialEditor, MaterialProperty prop, bool indentLevel)
{
float propertyHeight = materialEditor.GetPropertyHeight(prop, prop.displayName);
Rect controlRect = EditorGUILayout.GetControlRect(true, propertyHeight, EditorStyles.layerMaskField);
//如果是面板下面的元素统一向右缩进,否则不向右缩进
if (indentLevel) EditorGUI.indentLevel++;
materialEditor.ShaderProperty(controlRect, prop, prop.displayName);
if (indentLevel) EditorGUI.indentLevel--;
}
const string INSPECTOR_TXT = "面板";
bool TryGetGroupName(string displayName,out string groupName)
{
//根据displayName找到组名
if (displayName.Contains(INSPECTOR_TXT))
{
groupName = Regex.Split(displayName, INSPECTOR_TXT, RegexOptions.IgnoreCase)[0];
return true;
}
foreach (var property in s_GraphProperty.Values)
{
if (!string.IsNullOrEmpty(property.groupName)){
if (displayName.StartsWith(property.groupName))
{
groupName = property.groupName;
return true;
}
}
}
groupName = string.Empty;
return false;
}
}
欢迎大家来测试
- 本文固定链接: https://www.xuanyusong.com/archives/4778
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!


