using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering.Universal.ShaderGUI
{
internal class CP_XXXOutLineGUI
{
public static class Styles{}
public struct LitProperties
{
public LitProperties(MaterialProperty[] properties){}
}
public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor){}
public static void SetMaterialKeywords(Material material){}
}
}
internal class CP_XXXLitShader : BaseShaderGUI
{
//声明子面板属性
private CP_XXXOutLineGUI.LitProperties litXXXOutLineProperties;
public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
}
public override void FindProperties(MaterialProperty[] properties)
{
base.FindProperties(properties);
// 新建子面板属性
litXXXOutLineProperties = new CP_XXXOutLineGUI.LitProperties(properties);
}
}
FillAdditionalFoldouts(MaterialHeaderScopeList)
会在继承BaseShaderGUI
的类中由系统自动调用,它传入当前材质GUI的列表实例,我们通过RegisterHeaderScope
可以添加新的列表项目。
public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
materialScopesList.RegisterHeaderScope(LitDetailGUI.Styles.detailInputs, Expandable.Details, _ => LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor));
}
注册函数:materialScopesList.RegisterHeaderScope
public GUIContent(...);
- string text 文本
- Texture image 图片
- string tooltip 鼠标指针当前悬停在其上或具有键盘焦点的控件的工具提示。
internal class CP_XXXOutLineGUI{
public static class Styles
{
public static readonly GUIContent OutLineInputs = new GUIContent("Outline Inputs",
"This Let You Open The OutLine Panel");
}
}
掩码设置要求,掩码按照位来设置,每个掩码占一个位字节。
如:在URP内置代码BaseShaderGUI:ShaderGUI
类中已经设置了部分掩码
[URPHelpURL("shaders-in-universalrp")]
protected enum Expandable
{
SurfaceOptions = 1 << 0,
SurfaceInputs = 1 << 1,
Advanced = 1 << 2,
Details = 1 << 3,
}
其中SurfaceOptions、SurfaceInputs、Advanced 都已被系统注册,在URPShader的LitShader(其他Shader中可能也有)中,Details也在重写函数FillAdditionalFoldouts中被注册
materialScopesList.RegisterHeaderScope(
LitDetailGUI.Styles.detailInputs,
Expandable.Details,
_ => LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor)
);
我们仿照URP标准库中的写法,添加自定义掩码的扩展
在CP_XXXLitShader中自定义
protected enum AdditionalExpandable
{
...其他掩码(16、32、64、128、256)
OutlineMask = 512,
}
public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
materialScopesList.RegisterHeaderScope(
CP_XXXOutLineGUI.Styles.OutLineInputs,
AdditionalExpandable.OutlineMask,
_ => CP_XXXOutLineGUI.DoDetailArea(litXXXOutLineProperties, materialEditor));
}
现在返回Unity,查看Shader列表。发现已经有了列表头显示。
首先OutLine需要的参数有OutLineColor和OutLineSize。
首先在LitProperties中声明该属性,并绑定该属性的Shader名称。
public struct LitProperties
{
public MaterialProperty OutLineColor;
public MaterialProperty OutLineSize;
public LitProperties(MaterialProperty[] properties)
{
OutLineColor = BaseShaderGUI.FindProperty("_OutlineColor", properties, false);//false-->未找到不抛出异常
OutLineSize = BaseShaderGUI.FindProperty("_OutlineSize", properties, false);
}
}
当展开OutLine下拉框时:调用public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
函数
public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
{
materialEditor.ColorProperty(properties.OutLineColor, Styles.OutLineColorContent.text);
materialEditor.FloatProperty(properties.OutLineSize, Styles.OutLineSizeContent.text);
}
展开显示
修改属性,Shader中参数被修改。
// 按钮类型
bool depthFadeEnabled = EditorGUILayout.Toggle(Styles.depthFadeEnabledText, properties.depthFadeEnabled.floatValue > 0.5f);
properties.depthFadeEnabled.floatValue = depthFadeEnabled ? 1.0f : 0.0f;
//滑轮类型
properties.depthFadeDist.floatValue =
EditorGUILayout.Slider(Styles.depthFadeDistText, properties.depthFadeDist.floatValue, 0.01f, 10.0f);
其他参照Unity官方文档
https://docs.unity.cn/cn/2019.4/ScriptReference/EditorGUILayout.html
using System;
using UnityEngine;
using UnityEditor;
namespace UnityEditor.Rendering.Universal.ShaderGUI
{
internal class CP_DragonLitShader : BaseShaderGUI
{
protected enum AdditionalExpandable
{
SnowInputs = 16,
DepthFadeInputs = 32,
。。。
}
private LitGUI.LitProperties litProperties;
private CP_LitDetailGUI.LitProperties litDetailProperties;
private CP_SnowGUI.LitProperties litSnowProperties;
。。。
public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
materialScopesList.RegisterHeaderScope(CP_LitDetailGUI.Styles.detailInputs, Expandable.Details, _ => CP_LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor));
materialScopesList.RegisterHeaderScope(CP_DragonColorGUI.Styles.inputs, AdditionalExpandable.DragonColorInputs, _ => CP_DragonColorGUI.DoDetailArea(litDragonColorProperties, materialEditor));
materialScopesList.RegisterHeaderScope(CP_SnowGUI.Styles.snowInputs, AdditionalExpandable.SnowInputs, _ => CP_SnowGUI.DoDetailArea(litSnowProperties, materialEditor));
。。。
}
// collect properties from the material properties
public override void FindProperties(MaterialProperty[] properties)
{
base.FindProperties(properties);
litProperties = new LitGUI.LitProperties(properties);
litDetailProperties = new CP_LitDetailGUI.LitProperties(properties);
litDragonColorProperties = new CP_DragonColorGUI.LitProperties(properties);
litSnowProperties = new CP_SnowGUI.LitProperties(properties);
。。。
}
// material changed check
public override void ValidateMaterial(Material material)
{
SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, CP_LitDetailGUI.SetMaterialKeywords);
CP_SnowGUI.SetMaterialKeywords(material);
。。。
}
// material main surface options
public override void DrawSurfaceOptions(Material material)
{
if (material == null)
throw new ArgumentNullException("material");
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
if (litProperties.workflowMode != null)
{
DoPopup(LitGUI.Styles.workflowModeText, litProperties.workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in blendModeProp.targets)
MaterialChanged((Material)obj);
}
base.DrawSurfaceOptions(material);
}
// material main surface inputs
public override void DrawSurfaceInputs(Material material)
{
base.DrawSurfaceInputs(material);
LitGUI.Inputs(litProperties, materialEditor, material);
DrawEmissionProperties(material, true);
DrawTileOffset(materialEditor, baseMapProp);
}
// material main advanced options
public override void DrawAdvancedOptions(Material material)
{
if (litProperties.reflections != null && litProperties.highlights != null)
{
EditorGUI.BeginChangeCheck();
materialEditor.ShaderProperty(litProperties.highlights, LitGUI.Styles.highlightsText);
materialEditor.ShaderProperty(litProperties.reflections, LitGUI.Styles.reflectionsText);
if (EditorGUI.EndChangeCheck())
{
MaterialChanged(material);
}
}
base.DrawAdvancedOptions(material);
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
if (material == null)
throw new ArgumentNullException("material");
// _Emission property is lost after assigning Standard shader to the material
// thus transfer it before assigning the new shader
if (material.HasProperty("_Emission"))
{
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
}
base.AssignNewShaderToMaterial(material, oldShader, newShader);
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
{
SetupMaterialBlendMode(material);
return;
}
SurfaceType surfaceType = SurfaceType.Opaque;
BlendMode blendMode = BlendMode.Alpha;
if (oldShader.name.Contains("/Transparent/Cutout/"))
{
surfaceType = SurfaceType.Opaque;
material.SetFloat("_AlphaClip", 1);
}
else if (oldShader.name.Contains("/Transparent/"))
{
// NOTE: legacy shaders did not provide physically based transparency
// therefore Fade mode
surfaceType = SurfaceType.Transparent;
blendMode = BlendMode.Alpha;
}
material.SetFloat("_Surface", (float)surfaceType);
material.SetFloat("_Blend", (float)blendMode);
if (oldShader.name.Equals("Standard (Specular setup)"))
{
material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Specular);
Texture texture = material.GetTexture("_SpecGlossMap");
if (texture != null)
material.SetTexture("_MetallicSpecGlossMap", texture);
}
else
{
material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Metallic);
Texture texture = material.GetTexture("_MetallicGlossMap");
if (texture != null)
material.SetTexture("_MetallicSpecGlossMap", texture);
}
MaterialChanged(material);
}
}
}