Unity3D之材质Shader通用面板研究技术代码

技美在调shader的时候可能不太擅长C#编辑面板的代码,所以有了这篇文章。我封装了一个通用的着色器GUI面板,这样就可以不需要写C#代码了,实现的过程中试图解决了这几个问题。
1.视图解决分组面板展开与缩进
2.if标签与原生标签的混合
我看了下编辑器下C#的代码自定义MaterialPropertyDrawer虽然也可以实现分组,但是无法与原生标签嵌套混合,所以改变了一下思路,在面板中如果有if标签,并且Foldout没有展开不进行绘制。
直接上代码
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using UnityEngine.Rendering;
using System;
 
//自定义效果-单行显示图片
internal class SingleLineDrawer : MaterialPropertyDrawer
{
    public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
    {
        editor.TexturePropertySingleLine(label, prop);
    }
    public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
    {
        return 0;
    }
}
//自定义效果-折行显示图片
internal class FoldoutDrawer : MaterialPropertyDrawer
{
    bool showPosition;
    public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor)
    {
        showPosition = EditorGUILayout.Foldout(showPosition, label);
        prop.floatValue = Convert.ToSingle(showPosition);
    }
    public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
    {
        return 0;
    }
}
 
public class CustomShaderGUI : ShaderGUI
{
 
    public class MaterialData
    {
        public MaterialProperty prop;
        public bool indentLevel = false;
    }
    static Dictionary<string, MaterialProperty> s_MaterialProperty = new Dictionary<string, MaterialProperty>();
    static List<MaterialData> s_List = new List<MaterialData>();
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        Shader shader = (materialEditor.target as Material).shader;
        s_List.Clear();
        s_MaterialProperty.Clear();
        for (int i = 0; i < properties.Length; i++)
        {
            var propertie = properties[i];
            s_MaterialProperty[propertie.name] = propertie;
            s_List.Add(new MaterialData() { prop = propertie, indentLevel = false });
            var attributes = shader.GetPropertyAttributes(i);
            foreach (var item in attributes)
            {
                if (item.StartsWith("if"))
                {
                    Match match = Regex.Match(item, @"(\w+)\s*\((.*)\)");
                    if (match.Success)
                    {
                        var name = match.Groups[2].Value.Trim();
                        if (s_MaterialProperty.TryGetValue(name, out var a))
                        {
                            if (a.floatValue == 0f) {
                                //如果有if标签,并且Foldout没有展开不进行绘制
                                s_List.RemoveAt(s_List.Count - 1); 
                                break;
                            }
                            else
                                s_List[s_List.Count - 1].indentLevel = true;
                        }
                    }
                }
            }
        }
 
 
        /*如果不需要展开子节点像右缩进,可以直接调用base方法
         base.OnGUI(materialEditor, s_List.ToArray());*/
 
        PropertiesDefaultGUI(materialEditor, s_List);
    }
    private static int s_ControlHash = "EditorTextField".GetHashCode();
    public void PropertiesDefaultGUI(MaterialEditor materialEditor, List<MaterialData> props)
    {
        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));
            }
        }
        for (int i = 0; i < props.Count; i++)
        {
            MaterialProperty prop = props[i].prop;
            bool indentLevel = props[i].indentLevel;
            if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) == MaterialProperty.PropFlags.None)
            {
                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--;
            }
        }
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        if (SupportedRenderingFeatures.active.editableMaterialRenderQueue)
        {
            materialEditor.RenderQueueField();
        }
        materialEditor.EnableInstancingField();
        materialEditor.DoubleSidedGIField();
    }
 
}
实现展开效果

shader的GUI代码,使用foldout和if标签来实现分组,与原生标签进行混合排版
Properties
    {
        [Foldout]   _MytestName("溶解面板",Range (0,1)) = 0
            [if(_MytestName)] [Toggle] _Mytest ("启动溶解宏", Float) = 0
        [if(_MytestName)] _Value("溶解参数1",Range (0,1)) = 0
        [if(_MytestName)] [SingleLine] _MainTex2 ("溶解图", 2D) = "white" {}
        [if(_MytestName)] [SingleLine] [Normal] _MainTex3 ("溶解图2", 2D) = "white" {}
        [if(_MytestName)] [PowerSlider(3.0)] _Shininess ("溶解参数3", Range (0.01, 1)) = 0.08
        [if(_MytestName)] [IntRange] _Alpha ("溶解参数4", Range (0, 255)) = 100
 
        [Foldout] _Mytest1Name("扰动面板",Range (0,1)) = 0
            [if(_Mytest1Name)] [Toggle] _Mytest1 ("启动扰动宏", Float) = 0
        [if(_Mytest1Name)] _Value1("扰动参数1",Range (0,1)) = 0
        [if(_Mytest1Name)] [SingleLine] _MainTex4 ("扰动图", 2D) = "white" {}
        [if(_Mytest1Name)] [SingleLine] [Normal] _MainTex5 ("扰动图2", 2D) = "white" {}
        [if(_Mytest1Name)] [Header(A group of things)][Space(10)] _Prop1 ("扰动参数2", Float) = 0
        [if(_Mytest1Name)] [KeywordEnum(Red, Green, Blue)] _ColorMode ("扰动颜色枚举", Float) = 0
 
        [Foldout] _Mytest2Name("特殊面板",Range (0,1)) = 0
            [if(_Mytest2Name)] [Toggle] _Mytest2 ("启动特殊宏", Float) = 0
        [if(_Mytest2Name)] _FirstColor("特殊颜色", Color) = (1, 1, 1, 1)
    }

 shader的底部写上 CustomEditor “CustomShaderGUI”  文章来源

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值