347 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using System.Linq;
using UnityEngine.Rendering;
// Include material common properties names
using static UnityEngine.Rendering.HighDefinition.HDMaterialProperties;
// We share the name of the properties in the UI to avoid duplication
using static UnityEditor.Rendering.HighDefinition.DecalSurfaceOptionsUIBlock.Styles;
namespace UnityEditor.Rendering.HighDefinition
{
/// <summary>The UI block that represents the surface inputs for decal materials.</summary>
public class DecalSurfaceInputsUIBlock : MaterialUIBlock
{
internal class Styles
{
public const string header = "Surface Inputs";
public static GUIContent baseColorText = new GUIContent("Base Map", "Specify the base color (RGB) and opacity (A) of the decal.");
public static GUIContent baseColorText2 = new GUIContent("Opacity", "Specify the opacity (A) of the decal.");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Specifies the normal map for this Material (BC7/BC5/DXT5(nm)).");
public static GUIContent decalBlendText = new GUIContent("Global Opacity", "Controls the opacity of the entire decal.");
public static GUIContent normalOpacityChannelText = new GUIContent("Normal Opacity Channel", "Specifies the source this Material uses as opacity for its Normal Map.");
public static GUIContent smoothnessRemappingText = new GUIContent("Smoothness Remapping", "Controls a remap for the smoothness channel in the Mask Map.");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Controls the smoothness of the decal.");
public static GUIContent metallicRemappingText = new GUIContent("Metallic Remapping", "Controls a remap for the metallic channel in the Mask Map.");
public static GUIContent metallicText = new GUIContent("Metallic", "Controls the metallic of the decal.");
public static GUIContent aoRemappingText = new GUIContent("Ambient Occlusion Remapping", "Controls a remap for the ambient occlusion channel in the Mask Map.");
public static GUIContent aoText = new GUIContent("Ambient Occlusion", "Controls the ambient occlusion of the decal.");
public static GUIContent maskOpacityChannelText = new GUIContent("Mask Opacity Channel", "Specifies the source this Material uses as opacity for its Mask Map.");
public static GUIContent maskMapBlueScaleText = new GUIContent("Scale Mask Map Blue Channel", "Controls the scale of the blue channel of the Mask Map. You can use this as opacity depending on the blend source you choose.");
public static GUIContent opacityBlueScaleText = new GUIContent("Mask Opacity", "Controls the opacity of the Mask (Metallic, Ambient Occlusion, Smoothness). You can use this as opacity depending on the blend source you choose.");
public static GUIContent useEmissionIntensityText = new GUIContent("Use Emission Intensity", "When enabled, this Material separates emission color and intensity. This makes the Emission Map into an LDR color and exposes the Emission Intensity property.");
public static GUIContent emissionMapText = new GUIContent("Emission Map", "Specifies a map (RGB) that the Material uses for emission.");
public static GUIContent emissiveIntensityText = new GUIContent("Emission Intensity", "Sets the overall strength of the emission effect.");
public static GUIContent emissiveExposureWeightText = new GUIContent("Exposure weight", "Controls how the camera exposure influences the perceived intensity of the emissivity. A weight of 0 means that the emissive intensity is calculated ignoring the exposure; increasing this weight progressively increases the influence of exposure on the final emissive value.");
public static GUIContent decalLayerText = new GUIContent("Decal Layer", "Specifies the current Decal Layers that the Decal affects.This Decal affect corresponding Material with the same Decal Layer flags.");
public static GUIContent maskMapText = new GUIContent("Mask Map", "Specifies the Mask Map for this Material - Metal(R), Ambient Occlusion(G), Opacity(B), Smoothness(A)");
}
ExpandableBit m_ExpandableBit;
enum BlendSource
{
BaseColorMapAlpha,
MaskMapBlue
}
string[] blendSourceNames = Enum.GetNames(typeof(BlendSource));
string[] blendSourceNamesNoMap = new string[] { "BaseColorMapAlpha", "Mask Opacity" };
string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
MaterialProperty baseColorMap = new MaterialProperty();
const string kBaseColorMap = "_BaseColorMap";
MaterialProperty baseColor = new MaterialProperty();
const string kBaseColor = "_BaseColor";
MaterialProperty normalMap = new MaterialProperty();
const string kNormalMap = "_NormalMap";
MaterialProperty maskMap = new MaterialProperty();
const string kMaskMap = "_MaskMap";
MaterialProperty decalBlend = new MaterialProperty();
const string kDecalBlend = "_DecalBlend";
MaterialProperty normalBlendSrc = new MaterialProperty();
const string kNormalBlendSrc = "_NormalBlendSrc";
MaterialProperty maskBlendSrc = new MaterialProperty();
const string kMaskBlendSrc = "_MaskBlendSrc";
MaterialProperty maskmapMetal = new MaterialProperty();
const string kMaskmapMetal = "_MaskmapMetal";
MaterialProperty maskmapAO = new MaterialProperty();
const string kMaskmapAO = "_MaskmapAO";
MaterialProperty maskmapSmoothness = new MaterialProperty();
const string kMaskmapSmoothness = "_MaskmapSmoothness";
MaterialProperty metallicRemapMin = new MaterialProperty();
const string kMetallicRemapMin = "_MetallicRemapMin";
MaterialProperty metallicRemapMax = new MaterialProperty();
const string kMetallicRemapMax = "_MetallicRemapMax";
MaterialProperty AORemapMin = new MaterialProperty();
const string kAORemapMin = "_AORemapMin";
MaterialProperty AORemapMax = new MaterialProperty();
const string kAORemapMax = "_AORemapMax";
MaterialProperty smoothnessRemapMin = new MaterialProperty();
const string kSmoothnessRemapMin = "_SmoothnessRemapMin";
MaterialProperty smoothnessRemapMax = new MaterialProperty();
const string kSmoothnessRemapMax = "_SmoothnessRemapMax";
MaterialProperty AO = new MaterialProperty();
const string kAO = "_AO";
MaterialProperty smoothness = new MaterialProperty();
const string kSmoothness = "_Smoothness";
MaterialProperty metallic = new MaterialProperty();
const string kMetallic = "_Metallic";
MaterialProperty maskMapBlueScale = new MaterialProperty();
const string kMaskMapBlueScale = "_DecalMaskMapBlueScale";
MaterialProperty emissiveColor = new MaterialProperty();
const string kEmissiveColor = "_EmissiveColor";
MaterialProperty emissiveColorMap = new MaterialProperty();
const string kEmissiveColorMap = "_EmissiveColorMap";
MaterialProperty affectEmission = new MaterialProperty();
MaterialProperty emissiveIntensity = null;
const string kEmissiveIntensity = "_EmissiveIntensity";
MaterialProperty emissiveIntensityUnit = null;
const string kEmissiveIntensityUnit = "_EmissiveIntensityUnit";
MaterialProperty useEmissiveIntensity = null;
const string kUseEmissiveIntensity = "_UseEmissiveIntensity";
MaterialProperty emissiveColorLDR = null;
const string kEmissiveColorLDR = "_EmissiveColorLDR";
MaterialProperty emissiveColorHDR = null;
const string kEmissiveColorHDR = "_EmissiveColorHDR";
MaterialProperty emissiveExposureWeight = null;
const string kEmissiveExposureWeight = "_EmissiveExposureWeight";
/// <summary>
/// Constructs a DecalSurfaceInputsUIBlock based on the parameters.
/// </summary>
/// <param name="expandableBit">Bit index used to store the foldout state</param>
public DecalSurfaceInputsUIBlock(ExpandableBit expandableBit)
{
m_ExpandableBit = expandableBit;
}
/// <summary>
/// Loads the material properties for the block.
/// </summary>
public override void LoadMaterialProperties()
{
baseColor = FindProperty(kBaseColor);
baseColorMap = FindProperty(kBaseColorMap);
normalMap = FindProperty(kNormalMap);
maskMap = FindProperty(kMaskMap);
decalBlend = FindProperty(kDecalBlend);
normalBlendSrc = FindProperty(kNormalBlendSrc);
maskBlendSrc = FindProperty(kMaskBlendSrc);
maskmapMetal = FindProperty(kMaskmapMetal);
maskmapAO = FindProperty(kMaskmapAO);
maskmapSmoothness = FindProperty(kMaskmapSmoothness);
metallicRemapMin = FindProperty(kMetallicRemapMin);
metallicRemapMax = FindProperty(kMetallicRemapMax);
AORemapMin = FindProperty(kAORemapMin);
AORemapMax = FindProperty(kAORemapMax);
smoothnessRemapMin = FindProperty(kSmoothnessRemapMin);
smoothnessRemapMax = FindProperty(kSmoothnessRemapMax);
AO = FindProperty(kAO);
smoothness = FindProperty(kSmoothness);
metallic = FindProperty(kMetallic);
maskMapBlueScale = FindProperty(kMaskMapBlueScale);
// TODO: move emission to the EmissionUIBlock ?
emissiveColor = FindProperty(kEmissiveColor);
emissiveColorMap = FindProperty(kEmissiveColorMap);
affectEmission = FindProperty(kAffectEmission);
useEmissiveIntensity = FindProperty(kUseEmissiveIntensity);
emissiveIntensityUnit = FindProperty(kEmissiveIntensityUnit);
emissiveIntensity = FindProperty(kEmissiveIntensity);
emissiveColorLDR = FindProperty(kEmissiveColorLDR);
emissiveColorHDR = FindProperty(kEmissiveColorHDR);
emissiveExposureWeight = FindProperty(kEmissiveExposureWeight);
// always instanced
SerializedProperty instancing = materialEditor.serializedObject.FindProperty("m_EnableInstancingVariants");
instancing.boolValue = true;
}
/// <summary>
/// Renders the properties in the block.
/// </summary>
public override void OnGUI()
{
using (var header = new MaterialHeaderScope(Styles.header, (uint)m_ExpandableBit, materialEditor))
{
if (header.expanded)
{
DrawDecalGUI();
}
}
}
void DrawDecalGUI()
{
bool perChannelMask = false;
HDRenderPipelineAsset hdrp = HDRenderPipeline.currentAsset;
if (hdrp != null)
{
perChannelMask = hdrp.currentPlatformRenderPipelineSettings.decalSettings.perChannelMask;
}
bool allMaskMap = materials.All(m => m.GetTexture(kMaskMap));
materialEditor.TexturePropertySingleLine((materials[0].GetFloat(kAffectAlbedo) == 1.0f) ? Styles.baseColorText : Styles.baseColorText2, baseColorMap, baseColor);
materialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap);
if (materials.All(m => m.GetTexture(kNormalMap)))
{
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
var normalBlendSrcValue = (int)normalBlendSrc.floatValue;
normalBlendSrcValue = EditorGUILayout.Popup(Styles.normalOpacityChannelText, normalBlendSrcValue, allMaskMap ? blendSourceNames : blendSourceNamesNoMap);
if (EditorGUI.EndChangeCheck())
normalBlendSrc.floatValue = normalBlendSrcValue;
EditorGUI.indentLevel--;
}
materialEditor.TexturePropertySingleLine(Styles.maskMapText, maskMap);
EditorGUI.indentLevel++;
if (allMaskMap)
{
if (perChannelMask)
{
float MetalRemapMinValue = metallicRemapMin.floatValue;
float MetalRemapMaxValue = metallicRemapMax.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(Styles.metallicRemappingText, ref MetalRemapMinValue, ref MetalRemapMaxValue, 0.0f, 1.0f);
if (EditorGUI.EndChangeCheck())
{
metallicRemapMin.floatValue = MetalRemapMinValue;
metallicRemapMax.floatValue = MetalRemapMaxValue;
}
float AORemapMinValue = AORemapMin.floatValue;
float AORemapMaxValue = AORemapMax.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(Styles.aoRemappingText, ref AORemapMinValue, ref AORemapMaxValue, 0.0f, 1.0f);
if (EditorGUI.EndChangeCheck())
{
AORemapMin.floatValue = AORemapMinValue;
AORemapMax.floatValue = AORemapMaxValue;
}
}
float smoothnessRemapMinValue = smoothnessRemapMin.floatValue;
float smoothnessRemapMaxValue = smoothnessRemapMax.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(Styles.smoothnessRemappingText, ref smoothnessRemapMinValue, ref smoothnessRemapMaxValue, 0.0f, 1.0f);
if (EditorGUI.EndChangeCheck())
{
smoothnessRemapMin.floatValue = smoothnessRemapMinValue;
smoothnessRemapMax.floatValue = smoothnessRemapMaxValue;
}
}
else
{
if (perChannelMask)
{
materialEditor.ShaderProperty(metallic, Styles.metallicText);
materialEditor.ShaderProperty(AO, Styles.aoText);
}
materialEditor.ShaderProperty(smoothness, Styles.smoothnessText);
}
EditorGUI.BeginChangeCheck();
var maskBlendSrcValue = (int)maskBlendSrc.floatValue;
maskBlendSrcValue = EditorGUILayout.Popup(Styles.maskOpacityChannelText, maskBlendSrcValue, allMaskMap ? blendSourceNames : blendSourceNamesNoMap);
if (EditorGUI.EndChangeCheck())
maskBlendSrc.floatValue = maskBlendSrcValue;
EditorGUI.indentLevel--;
materialEditor.ShaderProperty(maskMapBlueScale, allMaskMap ? Styles.maskMapBlueScaleText : Styles.opacityBlueScaleText);
materialEditor.ShaderProperty(decalBlend, Styles.decalBlendText);
//if (affectEmission.floatValue == 1.0f) // Always show emissive part
using (var scope = new EditorGUI.ChangeCheckScope())
{
materialEditor.ShaderProperty(useEmissiveIntensity, Styles.useEmissionIntensityText);
if (useEmissiveIntensity.floatValue == 1.0f)
{
materialEditor.TexturePropertySingleLine(Styles.emissionMapText, emissiveColorMap, emissiveColorLDR);
using (new EditorGUILayout.HorizontalScope())
{
EmissiveIntensityUnit unit = (EmissiveIntensityUnit)emissiveIntensityUnit.floatValue;
if (unit == EmissiveIntensityUnit.Nits)
materialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
else
{
float evValue = LightUtils.ConvertLuminanceToEv(emissiveIntensity.floatValue);
evValue = EditorGUILayout.FloatField(Styles.emissiveIntensityText, evValue);
emissiveIntensity.floatValue = LightUtils.ConvertEvToLuminance(evValue);
}
emissiveIntensityUnit.floatValue = (float)(EmissiveIntensityUnit)EditorGUILayout.EnumPopup(unit);
}
}
else
{
materialEditor.TexturePropertySingleLine(Styles.emissionMapText, emissiveColorMap, emissiveColorHDR);
}
materialEditor.ShaderProperty(emissiveExposureWeight, Styles.emissiveExposureWeightText);
// If anything change, update the emission value
if (scope.changed)
{
if (useEmissiveIntensity.floatValue == 1.0f)
{
materialEditor.serializedObject.ApplyModifiedProperties();
foreach (Material target in materials)
{
target.UpdateEmissiveColorFromIntensityAndEmissiveColorLDR();
}
materialEditor.serializedObject.Update();
}
else
{
emissiveColor.colorValue = emissiveColorHDR.colorValue;
}
}
}
}
}
}