namespace UnityEditor
{
internal class LitGUI : ShaderGUI
public abstract class BaseLitGUI : ShaderGUI
public enum SurfaceType
{
Opaque ,
Transparent
}
public enum BlendMode
{
Lerp ,
Add ,
SoftAdd ,
Multiply ,
Premultiply
}
public enum SmoothnessMapChannel
{
MaskAlpha ,
AlbedoAlpha ,
}
public enum EmissiveColorMode
{
UseEmissiveColor ,
UseEmissiveMask ,
}
public enum DoubleSidedMode
{
None ,
DoubleSided ,
DoubleSidedLightingFlip ,
DoubleSidedLightingMirror ,
}
public enum NormalMapSpace
protected static class Styles
TangentSpace ,
ObjectSpace ,
}
public enum HeightmapMode
{
Parallax ,
Displacement ,
}
public enum DetailMapMode
{
DetailWithNormal ,
DetailWithAOHeight ,
}
private static class Styles
{
public enum DetailMapMode
{
DetailWithNormal ,
DetailWithAOHeight ,
}
public static string OptionText = "Options" ;
public static string SurfaceTypeText = "Surface Type" ;
public static string BlendModeText = "Blend Mode" ;
}
MaterialProperty surfaceType = null ;
MaterialProperty blendMode = null ;
public enum SurfaceType
{
Opaque ,
Transparent
}
public enum BlendMode
{
Lerp ,
Add ,
SoftAdd ,
Multiply ,
Premultiply
}
public enum DoubleSidedMode
{
None ,
DoubleSided ,
DoubleSidedLightingFlip ,
DoubleSidedLightingMirror ,
}
void SurfaceTypePopup ( )
{
EditorGUI . showMixedValue = surfaceType . hasMixedValue ;
var mode = ( SurfaceType ) surfaceType . floatValue ;
EditorGUI . BeginChangeCheck ( ) ;
mode = ( SurfaceType ) EditorGUILayout . Popup ( Styles . SurfaceTypeText , ( int ) mode , Styles . surfaceTypeNames ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
m_MaterialEditor . RegisterPropertyChangeUndo ( "Surface Type" ) ;
surfaceType . floatValue = ( float ) mode ;
}
EditorGUI . showMixedValue = false ;
}
protected void ShaderOptionsGUI ( )
{
EditorGUI . indentLevel + + ;
GUILayout . Label ( Styles . OptionText , EditorStyles . boldLabel ) ;
SurfaceTypePopup ( ) ;
if ( ( SurfaceType ) surfaceType . floatValue = = SurfaceType . Transparent )
{
BlendModePopup ( ) ;
}
m_MaterialEditor . ShaderProperty ( alphaCutoffEnable , Styles . alphaCutoffEnableText . text ) ;
if ( alphaCutoffEnable . floatValue = = 1.0 )
{
m_MaterialEditor . ShaderProperty ( alphaCutoff , Styles . alphaCutoffText . text ) ;
}
m_MaterialEditor . ShaderProperty ( doubleSidedMode , Styles . doubleSidedModeText . text ) ;
EditorGUI . indentLevel - - ;
}
private void BlendModePopup ( )
{
EditorGUI . showMixedValue = blendMode . hasMixedValue ;
var mode = ( BlendMode ) blendMode . floatValue ;
EditorGUI . BeginChangeCheck ( ) ;
mode = ( BlendMode ) EditorGUILayout . Popup ( Styles . BlendModeText , ( int ) mode , Styles . blendModeNames ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
m_MaterialEditor . RegisterPropertyChangeUndo ( "Blend Mode" ) ;
blendMode . floatValue = ( float ) mode ;
}
EditorGUI . showMixedValue = false ;
}
protected void FindOptionProperties ( MaterialProperty [ ] props )
{
surfaceType = FindProperty ( kSurfaceType , props ) ;
blendMode = FindProperty ( kBlendMode , props ) ;
alphaCutoff = FindProperty ( kAlphaCutoff , props ) ;
alphaCutoffEnable = FindProperty ( kAlphaCutoffEnabled , props ) ;
doubleSidedMode = FindProperty ( kDoubleSidedMode , props ) ;
FindInputOptionProperties ( props ) ;
}
protected void SetupMaterial ( Material material )
{
bool alphaTestEnable = material . GetFloat ( kAlphaCutoffEnabled ) = = 1.0 ;
SurfaceType surfaceType = ( SurfaceType ) material . GetFloat ( kSurfaceType ) ;
BlendMode blendMode = ( BlendMode ) material . GetFloat ( kBlendMode ) ;
DoubleSidedMode doubleSidedMode = ( DoubleSidedMode ) material . GetFloat ( kDoubleSidedMode ) ;
if ( surfaceType = = SurfaceType . Opaque )
{
material . SetOverrideTag ( "RenderType" , alphaTestEnable ? "TransparentCutout" : "" ) ;
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . Zero ) ;
material . SetInt ( "_ZWrite" , 1 ) ;
material . renderQueue = alphaTestEnable ? ( int ) UnityEngine . Rendering . RenderQueue . AlphaTest : - 1 ;
}
else
{
material . SetOverrideTag ( "RenderType" , "Transparent" ) ;
material . SetInt ( "_ZWrite" , 0 ) ;
material . renderQueue = ( int ) UnityEngine . Rendering . RenderQueue . Transparent ;
switch ( blendMode )
{
case BlendMode . Lerp :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . SrcAlpha ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusSrcAlpha ) ;
break ;
case BlendMode . Add :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
break ;
case BlendMode . SoftAdd :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusDstColor ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
break ;
case BlendMode . Multiply :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . DstColor ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . Zero ) ;
break ;
case BlendMode . Premultiply :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusSrcAlpha ) ;
break ;
}
}
if ( doubleSidedMode = = DoubleSidedMode . None )
{
material . SetInt ( "_CullMode" , ( int ) UnityEngine . Rendering . CullMode . Back ) ;
}
else
{
material . SetInt ( "_CullMode" , ( int ) UnityEngine . Rendering . CullMode . Off ) ;
}
if ( doubleSidedMode = = DoubleSidedMode . DoubleSidedLightingFlip )
{
material . EnableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
else if ( doubleSidedMode = = DoubleSidedMode . DoubleSidedLightingMirror )
{
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . EnableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
else
{
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
SetKeyword ( material , "_ALPHATEST_ON" , alphaTestEnable ) ;
SetupInputMaterial ( material ) ;
}
protected void SetKeyword ( Material m , string keyword , bool state )
{
if ( state )
m . EnableKeyword ( keyword ) ;
else
m . DisableKeyword ( keyword ) ;
}
public void ShaderPropertiesGUI ( Material material )
{
// Use default labelWidth
EditorGUIUtility . labelWidth = 0f ;
// Detect any changes to the material
EditorGUI . BeginChangeCheck ( ) ;
{
ShaderOptionsGUI ( ) ;
EditorGUILayout . Space ( ) ;
ShaderInputOptionsGUI ( ) ;
EditorGUILayout . Space ( ) ;
ShaderInputGUI ( ) ;
}
if ( EditorGUI . EndChangeCheck ( ) )
{
foreach ( var obj in m_MaterialEditor . targets )
SetupMaterial ( ( Material ) obj ) ;
}
}
public override void OnGUI ( MaterialEditor materialEditor , MaterialProperty [ ] props )
{
FindOptionProperties ( props ) ; // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindInputProperties ( props ) ;
m_MaterialEditor = materialEditor ;
Material material = materialEditor . target as Material ;
ShaderPropertiesGUI ( material ) ;
}
protected MaterialEditor m_MaterialEditor ;
private MaterialProperty surfaceType = null ;
private MaterialProperty alphaCutoffEnable = null ;
private MaterialProperty blendMode = null ;
private MaterialProperty alphaCutoff = null ;
private MaterialProperty doubleSidedMode = null ;
private const string kSurfaceType = "_SurfaceType" ;
private const string kBlendMode = "_BlendMode" ;
private const string kAlphaCutoff = "_AlphaCutoff" ;
private const string kAlphaCutoffEnabled = "_AlphaCutoffEnable" ;
private const string kDoubleSidedMode = "_DoubleSidedMode" ;
protected static string [ ] reservedProperties = new string [ ] { kSurfaceType , kBlendMode , kAlphaCutoff , kAlphaCutoffEnabled , kDoubleSidedMode } ;
protected abstract void FindInputProperties ( MaterialProperty [ ] props ) ;
protected abstract void ShaderInputGUI ( ) ;
protected abstract void ShaderInputOptionsGUI ( ) ;
protected abstract void FindInputOptionProperties ( MaterialProperty [ ] props ) ;
protected abstract void SetupInputMaterial ( Material material ) ;
}
class LitGUI : BaseLitGUI
{
public enum SmoothnessMapChannel
{
MaskAlpha ,
AlbedoAlpha ,
}
public enum EmissiveColorMode
{
UseEmissiveColor ,
UseEmissiveMask ,
}
public enum NormalMapSpace
{
TangentSpace ,
ObjectSpace ,
}
public enum HeightmapMode
{
Parallax ,
Displacement ,
}
public enum DetailMapMode
{
DetailWithNormal ,
DetailWithAOHeight ,
}
MaterialProperty alphaCutoff = null ;
MaterialProperty alphaCutoffEnable = null ;
MaterialProperty doubleSidedMode = null ;
MaterialProperty smoothnessMapChannel = null ;
MaterialProperty emissiveColorMode = null ;
MaterialProperty detailMapMode = null ;
// MaterialProperty subSurfaceRadius = null;
// MaterialProperty subSurfaceRadiusMap = null;
protected MaterialEditor m_MaterialEditor ;
protected const string kSurfaceType = "_SurfaceType" ;
protected const string kBlendMode = "_BlendMode" ;
protected const string kAlphaCutoff = "_AlphaCutoff" ;
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable" ;
protected const string kDoubleSidedMode = "_DoubleSidedMode" ;
protected const string kSmoothnessTextureChannelProp = "_SmoothnessTextureChannel" ;
protected const string kEmissiveColorMode = "_EmissiveColorMode" ;
protected const string kNormalMapSpace = "_NormalMapSpace" ;
protected const string kDetailHeightScale = "_DetailHeightScale" ;
protected const string kDetailAOScale = "_DetailAOScale" ;
public void FindOptionProperties ( MaterialProperty [ ] props )
override protected void FindInputOptionProperties ( MaterialProperty [ ] props )
surfaceType = FindProperty ( kSurfaceType , props ) ;
blendMode = FindProperty ( kBlendMode , props ) ;
alphaCutoff = FindProperty ( kAlphaCutoff , props ) ;
alphaCutoffEnable = FindProperty ( kAlphaCutoffEnabled , props ) ;
doubleSidedMode = FindProperty ( kDoubleSidedMode , props ) ;
smoothnessMapChannel = FindProperty ( kSmoothnessTextureChannelProp , props ) ;
emissiveColorMode = FindProperty ( kEmissiveColorMode , props ) ;
normalMapSpace = FindProperty ( kNormalMapSpace , props ) ;
public void FindInputProperties ( MaterialProperty [ ] props )
override protected void FindInputProperties ( MaterialProperty [ ] props )
{
baseColor = FindProperty ( "_BaseColor" , props ) ;
baseColorMap = FindProperty ( "_BaseColorMap" , props ) ;
detailAOScale = FindProperty ( kDetailAOScale , props ) ;
}
public override void OnGUI ( MaterialEditor materialEditor , MaterialProperty [ ] props )
{
FindOptionProperties ( props ) ; // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindInputProperties ( props ) ;
m_MaterialEditor = materialEditor ;
Material material = materialEditor . target as Material ;
ShaderPropertiesGUI ( material ) ;
}
protected void ShaderOptionsGUI ( )
{
EditorGUI . indentLevel + + ;
GUILayout . Label ( Styles . OptionText , EditorStyles . boldLabel ) ;
SurfaceTypePopup ( ) ;
if ( ( SurfaceType ) surfaceType . floatValue = = SurfaceType . Transparent )
{
BlendModePopup ( ) ;
}
m_MaterialEditor . ShaderProperty ( alphaCutoffEnable , Styles . alphaCutoffEnableText . text ) ;
if ( alphaCutoffEnable . floatValue = = 1.0 )
{
m_MaterialEditor . ShaderProperty ( alphaCutoff , Styles . alphaCutoffText . text ) ;
}
m_MaterialEditor . ShaderProperty ( doubleSidedMode , Styles . doubleSidedModeText . text ) ;
EditorGUI . indentLevel - - ;
}
protected void ShaderInputOptionsGUI ( )
override protected void ShaderInputOptionsGUI ( )
{
EditorGUI . indentLevel + + ;
GUILayout . Label ( Styles . InputsOptionsText , EditorStyles . boldLabel ) ;
EditorGUI . indentLevel - - ;
}
protected void ShaderInputGUI ( )
override protected void ShaderInputGUI ( )
{
EditorGUI . indentLevel + + ;
bool smoothnessInAlbedoAlpha = ( SmoothnessMapChannel ) smoothnessMapChannel . floatValue = = SmoothnessMapChannel . AlbedoAlpha ;
GUILayout . Label ( Styles . detailText , EditorStyles . boldLabel ) ;
m_MaterialEditor . TexturePropertySingleLine ( Styles . detailMaskText , detailMask ) ;
m_MaterialEditor . ShaderProperty ( UVDetail , Styles . uvSetLabel . text ) ;
m_MaterialEditor . ShaderProperty ( UVDetail , Styles . uvSetLabel . text ) ;
if ( useDetailMapWithNormal )
{
EditorGUI . indentLevel - - ;
}
public void ShaderPropertiesGUI ( Material material )
{
// Use default labelWidth
EditorGUIUtility . labelWidth = 0f ;
// Detect any changes to the material
EditorGUI . BeginChangeCheck ( ) ;
{
ShaderOptionsGUI ( ) ;
EditorGUILayout . Space ( ) ;
ShaderInputOptionsGUI ( ) ;
EditorGUILayout . Space ( ) ;
ShaderInputGUI ( ) ;
}
if ( EditorGUI . EndChangeCheck ( ) )
{
foreach ( var obj in m_MaterialEditor . targets )
SetupMaterial ( ( Material ) obj ) ;
}
}
// TODO: try to setup minimun value to fall back to standard shaders and reverse
public override void AssignNewShaderToMaterial ( Material material , Shader oldShader , Shader newShader )
{
void SurfaceTypePopup ( )
{
EditorGUI . showMixedValue = surfaceType . hasMixedValue ;
var mode = ( SurfaceType ) surfaceType . floatValue ;
EditorGUI . BeginChangeCheck ( ) ;
mode = ( SurfaceType ) EditorGUILayout . Popup ( Styles . SurfaceTypeText , ( int ) mode , Styles . surfaceTypeNames ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
m_MaterialEditor . RegisterPropertyChangeUndo ( "Surface Type" ) ;
surfaceType . floatValue = ( float ) mode ;
}
EditorGUI . showMixedValue = false ;
}
void BlendModePopup ( )
{
EditorGUI . showMixedValue = blendMode . hasMixedValue ;
var mode = ( BlendMode ) blendMode . floatValue ;
EditorGUI . BeginChangeCheck ( ) ;
mode = ( BlendMode ) EditorGUILayout . Popup ( Styles . BlendModeText , ( int ) mode , Styles . blendModeNames ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
m_MaterialEditor . RegisterPropertyChangeUndo ( "Blend Mode" ) ;
blendMode . floatValue = ( float ) mode ;
}
EditorGUI . showMixedValue = false ;
}
protected virtual void SetupKeywordsForInputMaps ( Material material )
{
SetKeyword ( material , "_NORMALMAP" , material . GetTexture ( kNormalMap ) | | material . GetTexture ( kDetailMap ) ) ; // With details map, we always use a normal map and Unity provide a default (0, 0, 1) normal map for ir
}
}
protected void SetupMaterial ( Material material )
override protected void SetupInputMaterial ( Material material )
bool alphaTestEnable = material . GetFloat ( kAlphaCutoffEnabled ) = = 1.0 ;
SurfaceType surfaceType = ( SurfaceType ) material . GetFloat ( kSurfaceType ) ;
BlendMode blendMode = ( BlendMode ) material . GetFloat ( kBlendMode ) ;
DoubleSidedMode doubleSidedMode = ( DoubleSidedMode ) material . GetFloat ( kDoubleSidedMode ) ;
if ( surfaceType = = SurfaceType . Opaque )
{
material . SetOverrideTag ( "RenderType" , alphaTestEnable ? "TransparentCutout" : "" ) ;
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . Zero ) ;
material . SetInt ( "_ZWrite" , 1 ) ;
material . renderQueue = alphaTestEnable ? ( int ) UnityEngine . Rendering . RenderQueue . AlphaTest : - 1 ;
}
else
{
material . SetOverrideTag ( "RenderType" , "Transparent" ) ;
material . SetInt ( "_ZWrite" , 0 ) ;
material . renderQueue = ( int ) UnityEngine . Rendering . RenderQueue . Transparent ;
switch ( blendMode )
{
case BlendMode . Lerp :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . SrcAlpha ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusSrcAlpha ) ;
break ;
case BlendMode . Add :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
break ;
case BlendMode . SoftAdd :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusDstColor ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
break ;
case BlendMode . Multiply :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . DstColor ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . Zero ) ;
break ;
case BlendMode . Premultiply :
material . SetInt ( "_SrcBlend" , ( int ) UnityEngine . Rendering . BlendMode . One ) ;
material . SetInt ( "_DstBlend" , ( int ) UnityEngine . Rendering . BlendMode . OneMinusSrcAlpha ) ;
break ;
}
}
if ( doubleSidedMode = = DoubleSidedMode . None )
{
material . SetInt ( "_CullMode" , ( int ) UnityEngine . Rendering . CullMode . Back ) ;
}
else
{
material . SetInt ( "_CullMode" , ( int ) UnityEngine . Rendering . CullMode . Off ) ;
}
if ( doubleSidedMode = = DoubleSidedMode . DoubleSidedLightingFlip )
{
material . EnableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
else if ( doubleSidedMode = = DoubleSidedMode . DoubleSidedLightingMirror )
{
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . EnableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
else
{
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_FLIP" ) ;
material . DisableKeyword ( "_DOUBLESIDED_LIGHTING_MIRROR" ) ;
}
SetKeyword ( material , "_ALPHATEST_ON" , alphaTestEnable ) ;
SetKeyword ( material , "_NORMALMAP_TANGENT_SPACE" , ( NormalMapSpace ) material . GetFloat ( kNormalMapSpace ) = = NormalMapSpace . TangentSpace ) ;
SetKeyword ( material , "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A" , ( ( SmoothnessMapChannel ) material . GetFloat ( kSmoothnessTextureChannelProp ) ) = = SmoothnessMapChannel . AlbedoAlpha ) ;
SetKeyword ( material , "_EMISSIVE_COLOR" , ( ( EmissiveColorMode ) material . GetFloat ( kEmissiveColorMode ) ) = = EmissiveColorMode . UseEmissiveColor ) ;
* /
return true ;
}
protected void SetKeyword ( Material m , string keyword , bool state )
{
if ( state )
m . EnableKeyword ( keyword ) ;
else
m . DisableKeyword ( keyword ) ;
}
}
} // namespace UnityEditor