620 lines
27 KiB
C#
620 lines
27 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
using UnityEditor.Rendering.Universal;
|
||
|
||
namespace UnityEditor
|
||
{
|
||
public abstract class BaseShaderGUI : ShaderGUI
|
||
{
|
||
#region EnumsAndClasses
|
||
|
||
public enum SurfaceType
|
||
{
|
||
Opaque,
|
||
Transparent
|
||
}
|
||
|
||
public enum BlendMode
|
||
{
|
||
Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency
|
||
Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply
|
||
Additive,
|
||
Multiply
|
||
}
|
||
|
||
public enum SmoothnessSource
|
||
{
|
||
BaseAlpha,
|
||
SpecularAlpha
|
||
}
|
||
|
||
public enum RenderFace
|
||
{
|
||
Front = 2,
|
||
Back = 1,
|
||
Both = 0
|
||
}
|
||
|
||
protected class Styles
|
||
{
|
||
// Catergories
|
||
public static readonly GUIContent SurfaceOptions =
|
||
new GUIContent("Surface Options", "Controls how Universal RP renders the Material on a screen.");
|
||
|
||
public static readonly GUIContent SurfaceInputs = new GUIContent("Surface Inputs",
|
||
"These settings describe the look and feel of the surface itself.");
|
||
|
||
public static readonly GUIContent AdvancedLabel = new GUIContent("Advanced",
|
||
"These settings affect behind-the-scenes rendering and underlying calculations.");
|
||
|
||
public static readonly GUIContent surfaceType = new GUIContent("Surface Type",
|
||
"Select a surface type for your texture. Choose between Opaque or Transparent.");
|
||
|
||
public static readonly GUIContent blendingMode = new GUIContent("Blending Mode",
|
||
"Controls how the color of the Transparent surface blends with the Material color in the background.");
|
||
|
||
public static readonly GUIContent cullingText = new GUIContent("Render Face",
|
||
"Specifies which faces to cull from your geometry. Front culls front faces. Back culls backfaces. None means that both sides are rendered.");
|
||
|
||
public static readonly GUIContent alphaClipText = new GUIContent("Alpha Clipping",
|
||
"Makes your Material act like a Cutout shader. Use this to create a transparent effect with hard edges between opaque and transparent areas.");
|
||
|
||
public static readonly GUIContent alphaClipThresholdText = new GUIContent("Threshold",
|
||
"Sets where the Alpha Clipping starts. The higher the value is, the brighter the effect is when clipping starts.");
|
||
|
||
public static readonly GUIContent receiveShadowText = new GUIContent("Receive Shadows",
|
||
"When enabled, other GameObjects can cast shadows onto this GameObject.");
|
||
|
||
public static readonly GUIContent baseMap = new GUIContent("Base Map",
|
||
"Specifies the base Material and/or Color of the surface. If you’ve selected Transparent or Alpha Clipping under Surface Options, your Material uses the Texture’s alpha channel or color.");
|
||
|
||
public static readonly GUIContent emissionMap = new GUIContent("Emission Map",
|
||
"Sets a Texture map to use for emission. You can also select a color with the color picker. Colors are multiplied over the Texture.");
|
||
|
||
public static readonly GUIContent normalMapText =
|
||
new GUIContent("Normal Map", "Assigns a tangent-space normal map.");
|
||
|
||
public static readonly GUIContent bumpScaleNotSupported =
|
||
new GUIContent("Bump scale is not supported on mobile platforms");
|
||
|
||
public static readonly GUIContent fixNormalNow = new GUIContent("Fix now",
|
||
"Converts the assigned texture to be a normal map format.");
|
||
|
||
public static readonly GUIContent queueSlider = new GUIContent("Priority",
|
||
"Determines the chronological rendering order for a Material. High values are rendered first.");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Variables
|
||
|
||
protected MaterialEditor materialEditor { get; set; }
|
||
|
||
protected MaterialProperty surfaceTypeProp { get; set; }
|
||
|
||
protected MaterialProperty blendModeProp { get; set; }
|
||
|
||
protected MaterialProperty cullingProp { get; set; }
|
||
|
||
protected MaterialProperty alphaClipProp { get; set; }
|
||
|
||
protected MaterialProperty alphaCutoffProp { get; set; }
|
||
|
||
protected MaterialProperty receiveShadowsProp { get; set; }
|
||
|
||
// Common Surface Input properties
|
||
|
||
protected MaterialProperty baseMapProp { get; set; }
|
||
|
||
protected MaterialProperty baseColorProp { get; set; }
|
||
|
||
protected MaterialProperty emissionMapProp { get; set; }
|
||
|
||
protected MaterialProperty emissionColorProp { get; set; }
|
||
|
||
protected MaterialProperty queueOffsetProp { get; set; }
|
||
|
||
public bool m_FirstTimeApply = true;
|
||
|
||
private const string k_KeyPrefix = "UniversalRP:Material:UI_State:";
|
||
|
||
private string m_HeaderStateKey = null;
|
||
|
||
protected string headerStateKey { get { return m_HeaderStateKey; } }
|
||
|
||
// Header foldout states
|
||
|
||
SavedBool m_SurfaceOptionsFoldout;
|
||
|
||
SavedBool m_SurfaceInputsFoldout;
|
||
|
||
SavedBool m_AdvancedFoldout;
|
||
|
||
#endregion
|
||
|
||
private const int queueOffsetRange = 50;
|
||
////////////////////////////////////
|
||
// General Functions //
|
||
////////////////////////////////////
|
||
#region GeneralFunctions
|
||
|
||
public abstract void MaterialChanged(Material material);
|
||
|
||
public virtual void FindProperties(MaterialProperty[] properties)
|
||
{
|
||
surfaceTypeProp = FindProperty("_Surface", properties);
|
||
blendModeProp = FindProperty("_Blend", properties);
|
||
cullingProp = FindProperty("_Cull", properties);
|
||
alphaClipProp = FindProperty("_AlphaClip", properties);
|
||
alphaCutoffProp = FindProperty("_Cutoff", properties);
|
||
receiveShadowsProp = FindProperty("_ReceiveShadows", properties, false);
|
||
baseMapProp = FindProperty("_BaseMap", properties, false);
|
||
baseColorProp = FindProperty("_BaseColor", properties, false);
|
||
emissionMapProp = FindProperty("_EmissionMap", properties, false);
|
||
emissionColorProp = FindProperty("_EmissionColor", properties, false);
|
||
queueOffsetProp = FindProperty("_QueueOffset", properties, false);
|
||
}
|
||
|
||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||
{
|
||
if (materialEditorIn == null)
|
||
throw new ArgumentNullException("materialEditorIn");
|
||
|
||
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
|
||
materialEditor = materialEditorIn;
|
||
Material material = materialEditor.target as Material;
|
||
|
||
// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
|
||
// material to a universal shader.
|
||
if (m_FirstTimeApply)
|
||
{
|
||
OnOpenGUI(material, materialEditorIn);
|
||
m_FirstTimeApply = false;
|
||
}
|
||
|
||
ShaderPropertiesGUI(material);
|
||
}
|
||
|
||
public virtual void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||
{
|
||
// Foldout states
|
||
m_HeaderStateKey = k_KeyPrefix + material.shader.name; // Create key string for editor prefs
|
||
m_SurfaceOptionsFoldout = new SavedBool($"{m_HeaderStateKey}.SurfaceOptionsFoldout", true);
|
||
m_SurfaceInputsFoldout = new SavedBool($"{m_HeaderStateKey}.SurfaceInputsFoldout", true);
|
||
m_AdvancedFoldout = new SavedBool($"{m_HeaderStateKey}.AdvancedFoldout", false);
|
||
|
||
foreach (var obj in materialEditor.targets)
|
||
MaterialChanged((Material)obj);
|
||
}
|
||
|
||
public void ShaderPropertiesGUI(Material material)
|
||
{
|
||
if (material == null)
|
||
throw new ArgumentNullException("material");
|
||
|
||
EditorGUI.BeginChangeCheck();
|
||
|
||
m_SurfaceOptionsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceOptionsFoldout.value, Styles.SurfaceOptions);
|
||
if (m_SurfaceOptionsFoldout.value)
|
||
{
|
||
DrawSurfaceOptions(material);
|
||
EditorGUILayout.Space();
|
||
}
|
||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||
|
||
m_SurfaceInputsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceInputsFoldout.value, Styles.SurfaceInputs);
|
||
if (m_SurfaceInputsFoldout.value)
|
||
{
|
||
DrawSurfaceInputs(material);
|
||
EditorGUILayout.Space();
|
||
}
|
||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||
|
||
DrawAdditionalFoldouts(material);
|
||
|
||
m_AdvancedFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_AdvancedFoldout.value, Styles.AdvancedLabel);
|
||
if (m_AdvancedFoldout.value)
|
||
{
|
||
DrawAdvancedOptions(material);
|
||
EditorGUILayout.Space();
|
||
}
|
||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
foreach (var obj in materialEditor.targets)
|
||
MaterialChanged((Material)obj);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
////////////////////////////////////
|
||
// Drawing Functions //
|
||
////////////////////////////////////
|
||
#region DrawingFunctions
|
||
|
||
public virtual void DrawSurfaceOptions(Material material)
|
||
{
|
||
DoPopup(Styles.surfaceType, surfaceTypeProp, Enum.GetNames(typeof(SurfaceType)));
|
||
if ((SurfaceType)material.GetFloat("_Surface") == SurfaceType.Transparent)
|
||
DoPopup(Styles.blendingMode, blendModeProp, Enum.GetNames(typeof(BlendMode)));
|
||
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = cullingProp.hasMixedValue;
|
||
var culling = (RenderFace)cullingProp.floatValue;
|
||
culling = (RenderFace)EditorGUILayout.EnumPopup(Styles.cullingText, culling);
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
materialEditor.RegisterPropertyChangeUndo(Styles.cullingText.text);
|
||
cullingProp.floatValue = (float)culling;
|
||
material.doubleSidedGI = (RenderFace)cullingProp.floatValue != RenderFace.Front;
|
||
}
|
||
|
||
EditorGUI.showMixedValue = false;
|
||
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = alphaClipProp.hasMixedValue;
|
||
var alphaClipEnabled = EditorGUILayout.Toggle(Styles.alphaClipText, alphaClipProp.floatValue == 1);
|
||
if (EditorGUI.EndChangeCheck())
|
||
alphaClipProp.floatValue = alphaClipEnabled ? 1 : 0;
|
||
EditorGUI.showMixedValue = false;
|
||
|
||
if (alphaClipProp.floatValue == 1)
|
||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||
|
||
if (receiveShadowsProp != null)
|
||
{
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = receiveShadowsProp.hasMixedValue;
|
||
var receiveShadows =
|
||
EditorGUILayout.Toggle(Styles.receiveShadowText, receiveShadowsProp.floatValue == 1.0f);
|
||
if (EditorGUI.EndChangeCheck())
|
||
receiveShadowsProp.floatValue = receiveShadows ? 1.0f : 0.0f;
|
||
EditorGUI.showMixedValue = false;
|
||
}
|
||
}
|
||
|
||
public virtual void DrawSurfaceInputs(Material material)
|
||
{
|
||
DrawBaseProperties(material);
|
||
}
|
||
|
||
public virtual void DrawAdvancedOptions(Material material)
|
||
{
|
||
materialEditor.EnableInstancingField();
|
||
DrawQueueOffsetField();
|
||
}
|
||
|
||
protected void DrawQueueOffsetField()
|
||
{
|
||
if (queueOffsetProp != null)
|
||
{
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = queueOffsetProp.hasMixedValue;
|
||
var queue = EditorGUILayout.IntSlider(Styles.queueSlider, (int)queueOffsetProp.floatValue, -queueOffsetRange, queueOffsetRange);
|
||
if (EditorGUI.EndChangeCheck())
|
||
queueOffsetProp.floatValue = queue;
|
||
EditorGUI.showMixedValue = false;
|
||
}
|
||
}
|
||
|
||
public virtual void DrawAdditionalFoldouts(Material material) {}
|
||
|
||
public virtual void DrawBaseProperties(Material material)
|
||
{
|
||
if (baseMapProp != null && baseColorProp != null) // Draw the baseMap, most shader will have at least a baseMap
|
||
{
|
||
materialEditor.TexturePropertySingleLine(Styles.baseMap, baseMapProp, baseColorProp);
|
||
// TODO Temporary fix for lightmapping, to be replaced with attribute tag.
|
||
if (material.HasProperty("_MainTex"))
|
||
{
|
||
material.SetTexture("_MainTex", baseMapProp.textureValue);
|
||
var baseMapTiling = baseMapProp.textureScaleAndOffset;
|
||
material.SetTextureScale("_MainTex", new Vector2(baseMapTiling.x, baseMapTiling.y));
|
||
material.SetTextureOffset("_MainTex", new Vector2(baseMapTiling.z, baseMapTiling.w));
|
||
}
|
||
}
|
||
}
|
||
|
||
protected virtual void DrawEmissionProperties(Material material, bool keyword)
|
||
{
|
||
var emissive = true;
|
||
var hadEmissionTexture = emissionMapProp.textureValue != null;
|
||
|
||
if (!keyword)
|
||
{
|
||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp,
|
||
false);
|
||
}
|
||
else
|
||
{
|
||
// Emission for GI?
|
||
emissive = materialEditor.EmissionEnabledProperty();
|
||
|
||
EditorGUI.BeginDisabledGroup(!emissive);
|
||
{
|
||
// Texture and HDR color controls
|
||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp,
|
||
emissionColorProp,
|
||
false);
|
||
}
|
||
EditorGUI.EndDisabledGroup();
|
||
}
|
||
|
||
// If texture was assigned and color was black set color to white
|
||
var brightness = emissionColorProp.colorValue.maxColorComponent;
|
||
if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f)
|
||
emissionColorProp.colorValue = Color.white;
|
||
|
||
// UniversalRP does not support RealtimeEmissive. We set it to bake emissive and handle the emissive is black right.
|
||
if (emissive)
|
||
{
|
||
var oldFlags = material.globalIlluminationFlags;
|
||
var newFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
|
||
|
||
if (brightness <= 0f)
|
||
newFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||
|
||
if (newFlags != oldFlags)
|
||
material.globalIlluminationFlags = newFlags;
|
||
}
|
||
}
|
||
|
||
public static void DrawNormalArea(MaterialEditor materialEditor, MaterialProperty bumpMap, MaterialProperty bumpMapScale = null)
|
||
{
|
||
if (bumpMapScale != null)
|
||
{
|
||
materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap,
|
||
bumpMap.textureValue != null ? bumpMapScale : null);
|
||
if (bumpMapScale.floatValue != 1 &&
|
||
UnityEditorInternal.InternalEditorUtility.IsMobilePlatform(
|
||
EditorUserBuildSettings.activeBuildTarget))
|
||
if (materialEditor.HelpBoxWithButton(Styles.bumpScaleNotSupported, Styles.fixNormalNow))
|
||
bumpMapScale.floatValue = 1;
|
||
}
|
||
else
|
||
{
|
||
materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap);
|
||
}
|
||
}
|
||
|
||
protected static void DrawTileOffset(MaterialEditor materialEditor, MaterialProperty textureProp)
|
||
{
|
||
materialEditor.TextureScaleOffsetProperty(textureProp);
|
||
}
|
||
|
||
#endregion
|
||
////////////////////////////////////
|
||
// Material Data Functions //
|
||
////////////////////////////////////
|
||
#region MaterialDataFunctions
|
||
|
||
public static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null, Action<Material> shaderFunc = null)
|
||
{
|
||
// Clear all keywords for fresh start
|
||
material.shaderKeywords = null;
|
||
|
||
// Setup blending - consistent across all Universal RP shaders
|
||
SetupMaterialBlendMode(material);
|
||
|
||
// Receive Shadows
|
||
if (material.HasProperty("_ReceiveShadows"))
|
||
CoreUtils.SetKeyword(material, "_RECEIVE_SHADOWS_OFF", material.GetFloat("_ReceiveShadows") == 0.0f);
|
||
|
||
// Emission
|
||
if (material.HasProperty("_EmissionColor"))
|
||
MaterialEditor.FixupEmissiveFlag(material);
|
||
bool shouldEmissionBeEnabled =
|
||
(material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
|
||
if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled)
|
||
shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f;
|
||
CoreUtils.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
|
||
|
||
// Normal Map
|
||
if (material.HasProperty("_BumpMap"))
|
||
CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
|
||
|
||
// Shader specific keyword functions
|
||
shadingModelFunc?.Invoke(material);
|
||
shaderFunc?.Invoke(material);
|
||
}
|
||
|
||
public static void SetupMaterialBlendMode(Material material)
|
||
{
|
||
if (material == null)
|
||
throw new ArgumentNullException("material");
|
||
|
||
bool alphaClip = false;
|
||
if (material.HasProperty("_AlphaClip"))
|
||
alphaClip = material.GetFloat("_AlphaClip") >= 0.5;
|
||
|
||
if (alphaClip)
|
||
{
|
||
material.EnableKeyword("_ALPHATEST_ON");
|
||
}
|
||
else
|
||
{
|
||
material.DisableKeyword("_ALPHATEST_ON");
|
||
}
|
||
|
||
if (material.HasProperty("_Surface"))
|
||
{
|
||
SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
|
||
if (surfaceType == SurfaceType.Opaque)
|
||
{
|
||
if (alphaClip)
|
||
{
|
||
material.renderQueue = (int)RenderQueue.AlphaTest;
|
||
material.SetOverrideTag("RenderType", "TransparentCutout");
|
||
}
|
||
else
|
||
{
|
||
material.renderQueue = (int)RenderQueue.Geometry;
|
||
material.SetOverrideTag("RenderType", "Opaque");
|
||
}
|
||
|
||
material.renderQueue += material.HasProperty("_QueueOffset") ? (int)material.GetFloat("_QueueOffset") : 0;
|
||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||
material.SetFloat("_ZWrite", 1.0f);
|
||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||
material.SetShaderPassEnabled("ShadowCaster", true);
|
||
}
|
||
else
|
||
{
|
||
BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
|
||
|
||
// Specific Transparent Mode Settings
|
||
switch (blendMode)
|
||
{
|
||
case BlendMode.Alpha:
|
||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||
break;
|
||
case BlendMode.Premultiply:
|
||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
|
||
break;
|
||
case BlendMode.Additive:
|
||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||
break;
|
||
case BlendMode.Multiply:
|
||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.DstColor);
|
||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||
material.EnableKeyword("_ALPHAMODULATE_ON");
|
||
break;
|
||
}
|
||
|
||
// General Transparent Material Settings
|
||
material.SetOverrideTag("RenderType", "Transparent");
|
||
material.SetFloat("_ZWrite", 0.0f);
|
||
material.renderQueue = (int)RenderQueue.Transparent;
|
||
material.renderQueue += material.HasProperty("_QueueOffset") ? (int)material.GetFloat("_QueueOffset") : 0;
|
||
material.SetShaderPassEnabled("ShadowCaster", false);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
////////////////////////////////////
|
||
// Helper Functions //
|
||
////////////////////////////////////
|
||
#region HelperFunctions
|
||
|
||
public static void TwoFloatSingleLine(GUIContent title, MaterialProperty prop1, GUIContent prop1Label,
|
||
MaterialProperty prop2, GUIContent prop2Label, MaterialEditor materialEditor, float labelWidth = 30f)
|
||
{
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = prop1.hasMixedValue || prop2.hasMixedValue;
|
||
Rect rect = EditorGUILayout.GetControlRect();
|
||
EditorGUI.PrefixLabel(rect, title);
|
||
var indent = EditorGUI.indentLevel;
|
||
var preLabelWidth = EditorGUIUtility.labelWidth;
|
||
EditorGUI.indentLevel = 0;
|
||
EditorGUIUtility.labelWidth = labelWidth;
|
||
Rect propRect1 = new Rect(rect.x + preLabelWidth, rect.y,
|
||
(rect.width - preLabelWidth) * 0.5f, EditorGUIUtility.singleLineHeight);
|
||
var prop1val = EditorGUI.FloatField(propRect1, prop1Label, prop1.floatValue);
|
||
|
||
Rect propRect2 = new Rect(propRect1.x + propRect1.width, rect.y,
|
||
propRect1.width, EditorGUIUtility.singleLineHeight);
|
||
var prop2val = EditorGUI.FloatField(propRect2, prop2Label, prop2.floatValue);
|
||
|
||
EditorGUI.indentLevel = indent;
|
||
EditorGUIUtility.labelWidth = preLabelWidth;
|
||
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
materialEditor.RegisterPropertyChangeUndo(title.text);
|
||
prop1.floatValue = prop1val;
|
||
prop2.floatValue = prop2val;
|
||
}
|
||
|
||
EditorGUI.showMixedValue = false;
|
||
}
|
||
|
||
public void DoPopup(GUIContent label, MaterialProperty property, string[] options)
|
||
{
|
||
DoPopup(label, property, options, materialEditor);
|
||
}
|
||
|
||
public static void DoPopup(GUIContent label, MaterialProperty property, string[] options, MaterialEditor materialEditor)
|
||
{
|
||
if (property == null)
|
||
throw new ArgumentNullException("property");
|
||
|
||
EditorGUI.showMixedValue = property.hasMixedValue;
|
||
|
||
var mode = property.floatValue;
|
||
EditorGUI.BeginChangeCheck();
|
||
mode = EditorGUILayout.Popup(label, (int)mode, options);
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
materialEditor.RegisterPropertyChangeUndo(label.text);
|
||
property.floatValue = mode;
|
||
}
|
||
|
||
EditorGUI.showMixedValue = false;
|
||
}
|
||
|
||
// Helper to show texture and color properties
|
||
public static Rect TextureColorProps(MaterialEditor materialEditor, GUIContent label, MaterialProperty textureProp, MaterialProperty colorProp, bool hdr = false)
|
||
{
|
||
Rect rect = EditorGUILayout.GetControlRect();
|
||
EditorGUI.showMixedValue = textureProp.hasMixedValue;
|
||
materialEditor.TexturePropertyMiniThumbnail(rect, textureProp, label.text, label.tooltip);
|
||
EditorGUI.showMixedValue = false;
|
||
|
||
if (colorProp != null)
|
||
{
|
||
EditorGUI.BeginChangeCheck();
|
||
EditorGUI.showMixedValue = colorProp.hasMixedValue;
|
||
int indentLevel = EditorGUI.indentLevel;
|
||
EditorGUI.indentLevel = 0;
|
||
Rect rectAfterLabel = new Rect(rect.x + EditorGUIUtility.labelWidth, rect.y,
|
||
EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight);
|
||
var col = EditorGUI.ColorField(rectAfterLabel, GUIContent.none, colorProp.colorValue, true,
|
||
false, hdr);
|
||
EditorGUI.indentLevel = indentLevel;
|
||
if (EditorGUI.EndChangeCheck())
|
||
{
|
||
materialEditor.RegisterPropertyChangeUndo(colorProp.displayName);
|
||
colorProp.colorValue = col;
|
||
}
|
||
EditorGUI.showMixedValue = false;
|
||
}
|
||
|
||
return rect;
|
||
}
|
||
|
||
// Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others
|
||
|
||
public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties)
|
||
{
|
||
return FindProperty(propertyName, properties, true);
|
||
}
|
||
|
||
// Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others
|
||
|
||
public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties, bool propertyIsMandatory)
|
||
{
|
||
for (int index = 0; index < properties.Length; ++index)
|
||
{
|
||
if (properties[index] != null && properties[index].name == propertyName)
|
||
return properties[index];
|
||
}
|
||
if (propertyIsMandatory)
|
||
throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + (object)properties.Length);
|
||
return null;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|