Unity3D材质Shader Graph通用面板

2021-03-29
3477
0

首先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;
    }
}

 

 

转载声明:本文来源于网络,不作任何商业用途

免责声明:本文内部分内容来自网络,所涉绘画作品及文字版权与著作权归原作者,若有侵权或异议请联系我们处理。
收藏

全部评论

您还没登录

暂无留言,赶紧抢占沙发
绘学霸是国内专业的CG数字艺术设计线上线下学习平台,在绘学霸有2D绘画、3D模型、影视后期、动画、特效等数字艺术培训课程,也有学习资源下载,还有行业社区交流。学习、交流,来绘学霸就对了。
绘学霸iOS端二维码

IOS下载

绘学霸安卓端二维码

安卓下载

绘学霸微信小程序二维码

小程序

版权声明
本网站所有产品设计、功能及展示形式,均已受版权或产权保护,任何公司及个人不得以任何方式复制部分或全部,违者将依法追究责任,特此声明。
热线电话
18026259035
咨询时间:9:00~21:00
在线客服
联系网站客服
客服微信:18026259035
公司地址
中国·广州
广州市海珠区晓港中马路130号之19
绘学霸客户端(权限暂无,用于CG资源与教程交流分享)
开发者:广州王氏软件科技有限公司 | 应用版本:Android:6.0,IOS:5.1 | App隐私政策> | 应用权限 | 更新时间:2020.1.6