首先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) {
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();
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) {
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;
}
}
转载声明:本文来源于网络,不作任何商业用途
IOS下载
安卓下载
小程序