initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
|
@ -0,0 +1,785 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
using RenderQueue = UnityEngine.Rendering.RenderQueue;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
public abstract class BaseShaderGUI : ShaderGUI
|
||||
{
|
||||
#region EnumsAndClasses
|
||||
|
||||
[Flags]
|
||||
[URPHelpURL("shaders-in-universalrp")]
|
||||
protected enum Expandable
|
||||
{
|
||||
SurfaceOptions = 1 << 0,
|
||||
SurfaceInputs = 1 << 1,
|
||||
Advanced = 1 << 2,
|
||||
Details = 1 << 3,
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
SpecularAlpha,
|
||||
BaseAlpha,
|
||||
}
|
||||
|
||||
public enum RenderFace
|
||||
{
|
||||
Front = 2,
|
||||
Back = 1,
|
||||
Both = 0
|
||||
}
|
||||
|
||||
public enum QueueControl
|
||||
{
|
||||
Auto = 0,
|
||||
UserOverride = 1
|
||||
}
|
||||
|
||||
protected class Styles
|
||||
{
|
||||
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
|
||||
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
|
||||
public static readonly string[] renderFaceNames = Enum.GetNames(typeof(RenderFace));
|
||||
public static readonly string[] zwriteNames = Enum.GetNames(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl));
|
||||
public static readonly string[] queueControlNames = Enum.GetNames(typeof(QueueControl));
|
||||
|
||||
// need to skip the first entry for ztest (ZTestMode.Disabled is not a valid value)
|
||||
public static readonly int[] ztestValues = ((int[])Enum.GetValues(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZTestMode))).Skip(1).ToArray();
|
||||
public static readonly string[] ztestNames = Enum.GetNames(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZTestMode)).Skip(1).ToArray();
|
||||
|
||||
// Categories
|
||||
public static readonly GUIContent SurfaceOptions =
|
||||
EditorGUIUtility.TrTextContent("Surface Options", "Controls how URP Renders the material on screen.");
|
||||
|
||||
public static readonly GUIContent SurfaceInputs = EditorGUIUtility.TrTextContent("Surface Inputs",
|
||||
"These settings describe the look and feel of the surface itself.");
|
||||
|
||||
public static readonly GUIContent AdvancedLabel = EditorGUIUtility.TrTextContent("Advanced Options",
|
||||
"These settings affect behind-the-scenes rendering and underlying calculations.");
|
||||
|
||||
public static readonly GUIContent surfaceType = EditorGUIUtility.TrTextContent("Surface Type",
|
||||
"Select a surface type for your texture. Choose between Opaque or Transparent.");
|
||||
|
||||
public static readonly GUIContent blendingMode = EditorGUIUtility.TrTextContent("Blending Mode",
|
||||
"Controls how the color of the Transparent surface blends with the Material color in the background.");
|
||||
|
||||
public static readonly GUIContent cullingText = EditorGUIUtility.TrTextContent("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 zwriteText = EditorGUIUtility.TrTextContent("Depth Write",
|
||||
"Controls whether the shader writes depth. Auto will write only when the shader is opaque.");
|
||||
|
||||
public static readonly GUIContent ztestText = EditorGUIUtility.TrTextContent("Depth Test",
|
||||
"Specifies the depth test mode. The default is LEqual.");
|
||||
|
||||
public static readonly GUIContent alphaClipText = EditorGUIUtility.TrTextContent("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 = EditorGUIUtility.TrTextContent("Threshold",
|
||||
"Sets where the Alpha Clipping starts. The higher the value is, the brighter the effect is when clipping starts.");
|
||||
|
||||
public static readonly GUIContent castShadowText = EditorGUIUtility.TrTextContent("Cast Shadows",
|
||||
"When enabled, this GameObject will cast shadows onto any geometry that can receive them.");
|
||||
|
||||
public static readonly GUIContent receiveShadowText = EditorGUIUtility.TrTextContent("Receive Shadows",
|
||||
"When enabled, other GameObjects can cast shadows onto this GameObject.");
|
||||
|
||||
public static readonly GUIContent baseMap = EditorGUIUtility.TrTextContent("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 = EditorGUIUtility.TrTextContent("Emission Map",
|
||||
"Determines the color and intensity of light that the surface of the material emits.");
|
||||
|
||||
public static readonly GUIContent normalMapText =
|
||||
EditorGUIUtility.TrTextContent("Normal Map", "Designates a Normal Map to create the illusion of bumps and dents on this Material's surface.");
|
||||
|
||||
public static readonly GUIContent bumpScaleNotSupported =
|
||||
EditorGUIUtility.TrTextContent("Bump scale is not supported on mobile platforms");
|
||||
|
||||
public static readonly GUIContent fixNormalNow = EditorGUIUtility.TrTextContent("Fix now",
|
||||
"Converts the assigned texture to be a normal map format.");
|
||||
|
||||
public static readonly GUIContent queueSlider = EditorGUIUtility.TrTextContent("Sorting Priority",
|
||||
"Determines the chronological rendering order for a Material. Materials with lower value are rendered first.");
|
||||
|
||||
public static readonly GUIContent queueControl = EditorGUIUtility.TrTextContent("Queue Control",
|
||||
"Controls whether render queue is automatically set based on material surface type, or explicitly set by the user.");
|
||||
|
||||
public static readonly GUIContent documentationIcon = EditorGUIUtility.TrIconContent("_Help", $"Open Reference for URP Shaders.");
|
||||
}
|
||||
|
||||
#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 ztestProp { get; set; }
|
||||
|
||||
protected MaterialProperty zwriteProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaClipProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaCutoffProp { get; set; }
|
||||
|
||||
protected MaterialProperty castShadowsProp { 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; }
|
||||
|
||||
protected MaterialProperty queueControlProp { get; set; }
|
||||
|
||||
public bool m_FirstTimeApply = true;
|
||||
|
||||
// By default, everything is expanded, except advanced
|
||||
readonly MaterialHeaderScopeList m_MaterialScopeList = new MaterialHeaderScopeList(uint.MaxValue & ~(uint)Expandable.Advanced);
|
||||
|
||||
#endregion
|
||||
|
||||
private const int queueOffsetRange = 50;
|
||||
|
||||
////////////////////////////////////
|
||||
// General Functions //
|
||||
////////////////////////////////////
|
||||
#region GeneralFunctions
|
||||
|
||||
[Obsolete("MaterialChanged has been renamed ValidateMaterial", false)]
|
||||
public virtual void MaterialChanged(Material material)
|
||||
{
|
||||
ValidateMaterial(material);
|
||||
}
|
||||
|
||||
public virtual void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
var material = materialEditor?.target as Material;
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
surfaceTypeProp = FindProperty(Property.SurfaceType, properties, false);
|
||||
blendModeProp = FindProperty(Property.BlendMode, properties, false);
|
||||
cullingProp = FindProperty(Property.CullMode, properties, false);
|
||||
zwriteProp = FindProperty(Property.ZWriteControl, properties, false);
|
||||
ztestProp = FindProperty(Property.ZTest, properties, false);
|
||||
alphaClipProp = FindProperty(Property.AlphaClip, properties, false);
|
||||
|
||||
// ShaderGraph Lit and Unlit Subtargets only
|
||||
castShadowsProp = FindProperty(Property.CastShadows, properties, false);
|
||||
queueControlProp = FindProperty(Property.QueueControl, properties, false);
|
||||
|
||||
// ShaderGraph Lit, and Lit.shader
|
||||
receiveShadowsProp = FindProperty(Property.ReceiveShadows, properties, false);
|
||||
|
||||
// The following are not mandatory for shadergraphs (it's up to the user to add them to their graph)
|
||||
alphaCutoffProp = FindProperty("_Cutoff", properties, false);
|
||||
baseMapProp = FindProperty("_BaseMap", properties, false);
|
||||
baseColorProp = FindProperty("_BaseColor", properties, false);
|
||||
emissionMapProp = FindProperty(Property.EmissionMap, properties, false);
|
||||
emissionColorProp = FindProperty(Property.EmissionColor, properties, false);
|
||||
queueOffsetProp = FindProperty(Property.QueueOffset, properties, false);
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||||
{
|
||||
if (materialEditorIn == null)
|
||||
throw new ArgumentNullException("materialEditorIn");
|
||||
|
||||
materialEditor = materialEditorIn;
|
||||
Material material = materialEditor.target as Material;
|
||||
|
||||
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
protected virtual uint materialFilter => uint.MaxValue;
|
||||
|
||||
public virtual void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
var filter = (Expandable)materialFilter;
|
||||
|
||||
// Generate the foldouts
|
||||
if (filter.HasFlag(Expandable.SurfaceOptions))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.SurfaceOptions, (uint)Expandable.SurfaceOptions, DrawSurfaceOptions);
|
||||
|
||||
if (filter.HasFlag(Expandable.SurfaceInputs))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.SurfaceInputs, (uint)Expandable.SurfaceInputs, DrawSurfaceInputs);
|
||||
|
||||
if (filter.HasFlag(Expandable.Details))
|
||||
FillAdditionalFoldouts(m_MaterialScopeList);
|
||||
|
||||
if (filter.HasFlag(Expandable.Advanced))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.AdvancedLabel, (uint)Expandable.Advanced, DrawAdvancedOptions);
|
||||
}
|
||||
|
||||
public void ShaderPropertiesGUI(Material material)
|
||||
{
|
||||
m_MaterialScopeList.DrawHeaders(materialEditor, material);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Drawing Functions //
|
||||
////////////////////////////////////
|
||||
#region DrawingFunctions
|
||||
|
||||
internal void DrawShaderGraphProperties(Material material, IEnumerable<MaterialProperty> properties)
|
||||
{
|
||||
if (properties == null)
|
||||
return;
|
||||
|
||||
ShaderGraphPropertyDrawers.DrawShaderGraphGUI(materialEditor, properties);
|
||||
}
|
||||
|
||||
internal static void DrawFloatToggleProperty(GUIContent styles, MaterialProperty prop)
|
||||
{
|
||||
if (prop == null)
|
||||
return;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop.hasMixedValue;
|
||||
bool newValue = EditorGUILayout.Toggle(styles, prop.floatValue == 1);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop.floatValue = newValue ? 1.0f : 0.0f;
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public virtual void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
DoPopup(Styles.surfaceType, surfaceTypeProp, Styles.surfaceTypeNames);
|
||||
if ((surfaceTypeProp != null) && ((SurfaceType)surfaceTypeProp.floatValue == SurfaceType.Transparent))
|
||||
DoPopup(Styles.blendingMode, blendModeProp, Styles.blendModeNames);
|
||||
|
||||
DoPopup(Styles.cullingText, cullingProp, Styles.renderFaceNames);
|
||||
DoPopup(Styles.zwriteText, zwriteProp, Styles.zwriteNames);
|
||||
|
||||
if (ztestProp != null)
|
||||
materialEditor.IntPopupShaderProperty(ztestProp, Styles.ztestText.text, Styles.ztestNames, Styles.ztestValues);
|
||||
|
||||
DrawFloatToggleProperty(Styles.alphaClipText, alphaClipProp);
|
||||
|
||||
if ((alphaClipProp != null) && (alphaCutoffProp != null) && (alphaClipProp.floatValue == 1))
|
||||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||||
|
||||
DrawFloatToggleProperty(Styles.castShadowText, castShadowsProp);
|
||||
DrawFloatToggleProperty(Styles.receiveShadowText, receiveShadowsProp);
|
||||
}
|
||||
|
||||
public virtual void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawBaseProperties(material);
|
||||
}
|
||||
|
||||
public virtual void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Only draw the sorting priority field if queue control is set to "auto"
|
||||
bool autoQueueControl = GetAutomaticQueueControlSetting(material);
|
||||
if (autoQueueControl)
|
||||
DrawQueueOffsetField();
|
||||
materialEditor.EnableInstancingField();
|
||||
}
|
||||
|
||||
protected void DrawQueueOffsetField()
|
||||
{
|
||||
if (queueOffsetProp != null)
|
||||
materialEditor.IntSliderShaderProperty(queueOffsetProp, -queueOffsetRange, queueOffsetRange, Styles.queueSlider);
|
||||
}
|
||||
|
||||
[Obsolete("DrawAdditionalFoldouts has been deprecated. Use FillAdditionalFoldouts instead, and materialScopesList.RegisterHeaderScope", false)]
|
||||
public virtual void DrawAdditionalFoldouts(Material material) { }
|
||||
|
||||
public virtual void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList) { }
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEmissionTextureProperty()
|
||||
{
|
||||
if ((emissionMapProp == null) || (emissionColorProp == null))
|
||||
return;
|
||||
|
||||
using (new EditorGUI.IndentLevelScope(2))
|
||||
{
|
||||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawEmissionProperties(Material material, bool keyword)
|
||||
{
|
||||
var emissive = true;
|
||||
|
||||
if (!keyword)
|
||||
{
|
||||
DrawEmissionTextureProperty();
|
||||
}
|
||||
else
|
||||
{
|
||||
emissive = materialEditor.EmissionEnabledProperty();
|
||||
using (new EditorGUI.DisabledScope(!emissive))
|
||||
{
|
||||
DrawEmissionTextureProperty();
|
||||
}
|
||||
}
|
||||
|
||||
// If texture was assigned and color was black set color to white
|
||||
if ((emissionMapProp != null) && (emissionColorProp != null))
|
||||
{
|
||||
var hadEmissionTexture = emissionMapProp?.textureValue != null;
|
||||
var brightness = emissionColorProp.colorValue.maxColorComponent;
|
||||
if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f)
|
||||
emissionColorProp.colorValue = Color.white;
|
||||
}
|
||||
|
||||
if (emissive)
|
||||
{
|
||||
// Change the GI emission flag and fix it up with emissive as black if necessary.
|
||||
materialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (textureProp != null)
|
||||
materialEditor.TextureScaleOffsetProperty(textureProp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Material Data Functions //
|
||||
////////////////////////////////////
|
||||
#region MaterialDataFunctions
|
||||
|
||||
// this function is shared with ShaderGraph Lit/Unlit GUIs and also the hand-written GUIs
|
||||
internal static void UpdateMaterialSurfaceOptions(Material material, bool automaticRenderQueue)
|
||||
{
|
||||
// Setup blending - consistent across all Universal RP shaders
|
||||
SetupMaterialBlendModeInternal(material, out int renderQueue);
|
||||
|
||||
// apply automatic render queue
|
||||
if (automaticRenderQueue && (renderQueue != material.renderQueue))
|
||||
material.renderQueue = renderQueue;
|
||||
|
||||
bool isShaderGraph = material.IsShaderGraph();
|
||||
|
||||
// Cast Shadows
|
||||
bool castShadows = true;
|
||||
if (material.HasProperty(Property.CastShadows))
|
||||
{
|
||||
castShadows = (material.GetFloat(Property.CastShadows) != 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isShaderGraph)
|
||||
{
|
||||
// Lit.shadergraph or Unlit.shadergraph, but no material control defined
|
||||
// enable the pass in the material, so shader can decide...
|
||||
castShadows = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lit.shader or Unlit.shader -- set based on transparency
|
||||
castShadows = Rendering.Universal.ShaderGUI.LitGUI.IsOpaque(material);
|
||||
}
|
||||
}
|
||||
material.SetShaderPassEnabled("ShadowCaster", castShadows);
|
||||
|
||||
// Receive Shadows
|
||||
if (material.HasProperty(Property.ReceiveShadows))
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._RECEIVE_SHADOWS_OFF, material.GetFloat(Property.ReceiveShadows) == 0.0f);
|
||||
}
|
||||
|
||||
// this function is shared between ShaderGraph and hand-written GUIs
|
||||
internal static void UpdateMaterialRenderQueueControl(Material material)
|
||||
{
|
||||
//
|
||||
// Render Queue Control handling
|
||||
//
|
||||
// Check for a raw render queue (the actual serialized setting - material.renderQueue has already been converted)
|
||||
// setting of -1, indicating that the material property should be inherited from the shader.
|
||||
// If we find this, add a new property "render queue control" set to 0 so we will
|
||||
// always know to follow the surface type of the material (this matches the hand-written behavior)
|
||||
// If we find another value, add the the property set to 1 so we will know that the
|
||||
// user has explicitly selected a render queue and we should not override it.
|
||||
//
|
||||
bool isShaderGraph = material.IsShaderGraph(); // Non-shadergraph materials use automatic behavior
|
||||
int rawRenderQueue = MaterialAccess.ReadMaterialRawRenderQueue(material);
|
||||
if (!isShaderGraph || rawRenderQueue == -1)
|
||||
{
|
||||
material.SetFloat(Property.QueueControl, (float)QueueControl.Auto); // Automatic behavior - surface type override
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetFloat(Property.QueueControl, (float)QueueControl.UserOverride); // User has selected explicit render queue
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool GetAutomaticQueueControlSetting(Material material)
|
||||
{
|
||||
// If a Shader Graph material doesn't yet have the queue control property,
|
||||
// we should not engage automatic behavior until the shader gets reimported.
|
||||
bool automaticQueueControl = !material.IsShaderGraph();
|
||||
if (material.HasProperty(Property.QueueControl))
|
||||
{
|
||||
var queueControl = material.GetFloat(Property.QueueControl);
|
||||
if (queueControl < 0.0f)
|
||||
{
|
||||
// The property was added with a negative value, indicating it needs to be validated for this material
|
||||
UpdateMaterialRenderQueueControl(material);
|
||||
}
|
||||
automaticQueueControl = (material.GetFloat(Property.QueueControl) == (float)QueueControl.Auto);
|
||||
}
|
||||
return automaticQueueControl;
|
||||
}
|
||||
|
||||
// this is the function used by Lit.shader, Unlit.shader GUIs
|
||||
public static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null, Action<Material> shaderFunc = null)
|
||||
{
|
||||
UpdateMaterialSurfaceOptions(material, automaticRenderQueue: true);
|
||||
|
||||
// Setup double sided GI based on Cull state
|
||||
if (material.HasProperty(Property.CullMode))
|
||||
material.doubleSidedGI = (RenderFace)material.GetFloat(Property.CullMode) != RenderFace.Front;
|
||||
|
||||
// Temporary fix for lightmapping. TODO: to be replaced with attribute tag.
|
||||
if (material.HasProperty("_MainTex"))
|
||||
{
|
||||
material.SetTexture("_MainTex", material.GetTexture("_BaseMap"));
|
||||
material.SetTextureScale("_MainTex", material.GetTextureScale("_BaseMap"));
|
||||
material.SetTextureOffset("_MainTex", material.GetTextureOffset("_BaseMap"));
|
||||
}
|
||||
if (material.HasProperty("_Color"))
|
||||
material.SetColor("_Color", material.GetColor("_BaseColor"));
|
||||
|
||||
// Emission
|
||||
if (material.HasProperty(Property.EmissionColor))
|
||||
MaterialEditor.FixupEmissiveFlag(material);
|
||||
|
||||
bool shouldEmissionBeEnabled =
|
||||
(material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
|
||||
|
||||
// Not sure what this is used for, I don't see this property declared by any Unity shader in our repo...
|
||||
// I'm guessing it is some kind of legacy material upgrade support thing? Or maybe just dead code now...
|
||||
if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled)
|
||||
shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f;
|
||||
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._EMISSION, shouldEmissionBeEnabled);
|
||||
|
||||
// Normal Map
|
||||
if (material.HasProperty("_BumpMap"))
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._NORMALMAP, material.GetTexture("_BumpMap"));
|
||||
|
||||
// Shader specific keyword functions
|
||||
shadingModelFunc?.Invoke(material);
|
||||
shaderFunc?.Invoke(material);
|
||||
}
|
||||
|
||||
internal static void SetMaterialSrcDstBlendProperties(Material material, UnityEngine.Rendering.BlendMode srcBlend, UnityEngine.Rendering.BlendMode dstBlend)
|
||||
{
|
||||
if (material.HasProperty(Property.SrcBlend))
|
||||
material.SetFloat(Property.SrcBlend, (float)srcBlend);
|
||||
|
||||
if (material.HasProperty(Property.DstBlend))
|
||||
material.SetFloat(Property.DstBlend, (float)dstBlend);
|
||||
}
|
||||
|
||||
internal static void SetMaterialZWriteProperty(Material material, bool zwriteEnabled)
|
||||
{
|
||||
if (material.HasProperty(Property.ZWrite))
|
||||
material.SetFloat(Property.ZWrite, zwriteEnabled ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
internal static void SetupMaterialBlendModeInternal(Material material, out int automaticRenderQueue)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
bool alphaClip = false;
|
||||
if (material.HasProperty(Property.AlphaClip))
|
||||
alphaClip = material.GetFloat(Property.AlphaClip) >= 0.5;
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._ALPHATEST_ON, alphaClip);
|
||||
|
||||
// default is to use the shader render queue
|
||||
int renderQueue = material.shader.renderQueue;
|
||||
material.SetOverrideTag("RenderType", ""); // clear override tag
|
||||
if (material.HasProperty(Property.SurfaceType))
|
||||
{
|
||||
SurfaceType surfaceType = (SurfaceType)material.GetFloat(Property.SurfaceType);
|
||||
bool zwrite = false;
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT, surfaceType == SurfaceType.Transparent);
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
if (alphaClip)
|
||||
{
|
||||
renderQueue = (int)RenderQueue.AlphaTest;
|
||||
material.SetOverrideTag("RenderType", "TransparentCutout");
|
||||
}
|
||||
else
|
||||
{
|
||||
renderQueue = (int)RenderQueue.Geometry;
|
||||
material.SetOverrideTag("RenderType", "Opaque");
|
||||
}
|
||||
|
||||
SetMaterialSrcDstBlendProperties(material, UnityEngine.Rendering.BlendMode.One, UnityEngine.Rendering.BlendMode.Zero);
|
||||
zwrite = true;
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
material.DisableKeyword(ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT);
|
||||
}
|
||||
else // SurfaceType Transparent
|
||||
{
|
||||
BlendMode blendMode = (BlendMode)material.GetFloat(Property.BlendMode);
|
||||
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAMODULATE_ON);
|
||||
|
||||
// Specific Transparent Mode Settings
|
||||
switch (blendMode)
|
||||
{
|
||||
case BlendMode.Alpha:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.SrcAlpha,
|
||||
UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
break;
|
||||
case BlendMode.Premultiply:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.One,
|
||||
UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.EnableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.SrcAlpha,
|
||||
UnityEngine.Rendering.BlendMode.One);
|
||||
break;
|
||||
case BlendMode.Multiply:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.DstColor,
|
||||
UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.EnableKeyword(ShaderKeywordStrings._ALPHAMODULATE_ON);
|
||||
break;
|
||||
}
|
||||
|
||||
// General Transparent Material Settings
|
||||
material.SetOverrideTag("RenderType", "Transparent");
|
||||
zwrite = false;
|
||||
material.EnableKeyword(ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT);
|
||||
renderQueue = (int)RenderQueue.Transparent;
|
||||
}
|
||||
|
||||
// check for override enum
|
||||
if (material.HasProperty(Property.ZWriteControl))
|
||||
{
|
||||
var zwriteControl = (UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl)material.GetFloat(Property.ZWriteControl);
|
||||
if (zwriteControl == UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl.ForceEnabled)
|
||||
zwrite = true;
|
||||
else if (zwriteControl == UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl.ForceDisabled)
|
||||
zwrite = false;
|
||||
}
|
||||
SetMaterialZWriteProperty(material, zwrite);
|
||||
material.SetShaderPassEnabled("DepthOnly", zwrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no surface type property -- must be hard-coded by the shadergraph,
|
||||
// so ensure the pass is enabled at the material level
|
||||
material.SetShaderPassEnabled("DepthOnly", true);
|
||||
}
|
||||
|
||||
// must always apply queue offset, even if not set to material control
|
||||
if (material.HasProperty(Property.QueueOffset))
|
||||
renderQueue += (int)material.GetFloat(Property.QueueOffset);
|
||||
|
||||
automaticRenderQueue = renderQueue;
|
||||
}
|
||||
|
||||
public static void SetupMaterialBlendMode(Material material)
|
||||
{
|
||||
SetupMaterialBlendModeInternal(material, out int renderQueue);
|
||||
|
||||
// apply automatic render queue
|
||||
if (renderQueue != material.renderQueue)
|
||||
material.renderQueue = renderQueue;
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
// Clear all keywords for fresh start
|
||||
// Note: this will nuke user-selected custom keywords when they change shaders
|
||||
material.shaderKeywords = null;
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
// Setup keywords based on the new shader
|
||||
UpdateMaterial(material, MaterialUpdateType.ChangedAssignedShader);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Helper Functions //
|
||||
////////////////////////////////////
|
||||
#region HelperFunctions
|
||||
|
||||
public static void TwoFloatSingleLine(GUIContent title, MaterialProperty prop1, GUIContent prop1Label,
|
||||
MaterialProperty prop2, GUIContent prop2Label, MaterialEditor materialEditor, float labelWidth = 30f)
|
||||
{
|
||||
const int kInterFieldPadding = 2;
|
||||
|
||||
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 - 1, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop1.hasMixedValue;
|
||||
var prop1val = EditorGUI.FloatField(propRect1, prop1Label, prop1.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop1.floatValue = prop1val;
|
||||
|
||||
Rect propRect2 = new Rect(propRect1.x + propRect1.width + kInterFieldPadding, rect.y,
|
||||
propRect1.width, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop2.hasMixedValue;
|
||||
var prop2val = EditorGUI.FloatField(propRect2, prop2Label, prop2.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop2.floatValue = prop2val;
|
||||
|
||||
EditorGUI.indentLevel = indent;
|
||||
EditorGUIUtility.labelWidth = preLabelWidth;
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public void DoPopup(GUIContent label, MaterialProperty property, string[] options)
|
||||
{
|
||||
if (property != null)
|
||||
materialEditor.PopupShaderProperty(property, label, options);
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,782 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
using RenderQueue = UnityEngine.Rendering.RenderQueue;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
public abstract class BaseShaderGUI : ShaderGUI
|
||||
{
|
||||
#region EnumsAndClasses
|
||||
|
||||
[Flags]
|
||||
[URPHelpURL("shaders-in-universalrp")]
|
||||
protected enum Expandable
|
||||
{
|
||||
SurfaceOptions = 1 << 0,
|
||||
SurfaceInputs = 1 << 1,
|
||||
Advanced = 1 << 2,
|
||||
Details = 1 << 3,
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
SpecularAlpha,
|
||||
BaseAlpha,
|
||||
}
|
||||
|
||||
public enum RenderFace
|
||||
{
|
||||
Front = 2,
|
||||
Back = 1,
|
||||
Both = 0
|
||||
}
|
||||
|
||||
public enum QueueControl
|
||||
{
|
||||
Auto = 0,
|
||||
UserOverride = 1
|
||||
}
|
||||
|
||||
protected class Styles
|
||||
{
|
||||
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
|
||||
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
|
||||
public static readonly string[] renderFaceNames = Enum.GetNames(typeof(RenderFace));
|
||||
public static readonly string[] zwriteNames = Enum.GetNames(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl));
|
||||
public static readonly string[] queueControlNames = Enum.GetNames(typeof(QueueControl));
|
||||
|
||||
// need to skip the first entry for ztest (ZTestMode.Disabled is not a valid value)
|
||||
public static readonly int[] ztestValues = ((int[])Enum.GetValues(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZTestMode))).Skip(1).ToArray();
|
||||
public static readonly string[] ztestNames = Enum.GetNames(typeof(UnityEditor.Rendering.Universal.ShaderGraph.ZTestMode)).Skip(1).ToArray();
|
||||
|
||||
// Categories
|
||||
public static readonly GUIContent SurfaceOptions =
|
||||
EditorGUIUtility.TrTextContent("Surface Options", "Controls how URP Renders the material on screen.");
|
||||
|
||||
public static readonly GUIContent SurfaceInputs = EditorGUIUtility.TrTextContent("Surface Inputs",
|
||||
"These settings describe the look and feel of the surface itself.");
|
||||
|
||||
public static readonly GUIContent AdvancedLabel = EditorGUIUtility.TrTextContent("Advanced Options",
|
||||
"These settings affect behind-the-scenes rendering and underlying calculations.");
|
||||
|
||||
public static readonly GUIContent surfaceType = EditorGUIUtility.TrTextContent("Surface Type",
|
||||
"Select a surface type for your texture. Choose between Opaque or Transparent.");
|
||||
|
||||
public static readonly GUIContent blendingMode = EditorGUIUtility.TrTextContent("Blending Mode",
|
||||
"Controls how the color of the Transparent surface blends with the Material color in the background.");
|
||||
|
||||
public static readonly GUIContent cullingText = EditorGUIUtility.TrTextContent("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 zwriteText = EditorGUIUtility.TrTextContent("Depth Write",
|
||||
"Controls whether the shader writes depth. Auto will write only when the shader is opaque.");
|
||||
|
||||
public static readonly GUIContent ztestText = EditorGUIUtility.TrTextContent("Depth Test",
|
||||
"Specifies the depth test mode. The default is LEqual.");
|
||||
|
||||
public static readonly GUIContent alphaClipText = EditorGUIUtility.TrTextContent("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 = EditorGUIUtility.TrTextContent("Threshold",
|
||||
"Sets where the Alpha Clipping starts. The higher the value is, the brighter the effect is when clipping starts.");
|
||||
|
||||
public static readonly GUIContent castShadowText = EditorGUIUtility.TrTextContent("Cast Shadows",
|
||||
"When enabled, this GameObject will cast shadows onto any geometry that can receive them.");
|
||||
|
||||
public static readonly GUIContent receiveShadowText = EditorGUIUtility.TrTextContent("Receive Shadows",
|
||||
"When enabled, other GameObjects can cast shadows onto this GameObject.");
|
||||
|
||||
public static readonly GUIContent baseMap = EditorGUIUtility.TrTextContent("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 = EditorGUIUtility.TrTextContent("Emission Map",
|
||||
"Determines the color and intensity of light that the surface of the material emits.");
|
||||
|
||||
public static readonly GUIContent normalMapText =
|
||||
EditorGUIUtility.TrTextContent("Normal Map", "Designates a Normal Map to create the illusion of bumps and dents on this Material's surface.");
|
||||
|
||||
public static readonly GUIContent bumpScaleNotSupported =
|
||||
EditorGUIUtility.TrTextContent("Bump scale is not supported on mobile platforms");
|
||||
|
||||
public static readonly GUIContent fixNormalNow = EditorGUIUtility.TrTextContent("Fix now",
|
||||
"Converts the assigned texture to be a normal map format.");
|
||||
|
||||
public static readonly GUIContent queueSlider = EditorGUIUtility.TrTextContent("Sorting Priority",
|
||||
"Determines the chronological rendering order for a Material. Materials with lower value are rendered first.");
|
||||
|
||||
public static readonly GUIContent queueControl = EditorGUIUtility.TrTextContent("Queue Control",
|
||||
"Controls whether render queue is automatically set based on material surface type, or explicitly set by the user.");
|
||||
|
||||
public static readonly GUIContent documentationIcon = EditorGUIUtility.TrIconContent("_Help", $"Open Reference for URP Shaders.");
|
||||
}
|
||||
|
||||
#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 ztestProp { get; set; }
|
||||
|
||||
protected MaterialProperty zwriteProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaClipProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaCutoffProp { get; set; }
|
||||
|
||||
protected MaterialProperty castShadowsProp { 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; }
|
||||
|
||||
protected MaterialProperty queueControlProp { get; set; }
|
||||
|
||||
public bool m_FirstTimeApply = true;
|
||||
|
||||
// By default, everything is expanded, except advanced
|
||||
readonly MaterialHeaderScopeList m_MaterialScopeList = new MaterialHeaderScopeList(uint.MaxValue & ~(uint)Expandable.Advanced);
|
||||
|
||||
#endregion
|
||||
|
||||
private const int queueOffsetRange = 50;
|
||||
|
||||
////////////////////////////////////
|
||||
// General Functions //
|
||||
////////////////////////////////////
|
||||
#region GeneralFunctions
|
||||
|
||||
[Obsolete("MaterialChanged has been renamed ValidateMaterial", false)]
|
||||
public virtual void MaterialChanged(Material material)
|
||||
{
|
||||
ValidateMaterial(material);
|
||||
}
|
||||
|
||||
public virtual void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
var material = materialEditor?.target as Material;
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
surfaceTypeProp = FindProperty(Property.SurfaceType, properties, false);
|
||||
blendModeProp = FindProperty(Property.BlendMode, properties, false);
|
||||
cullingProp = FindProperty(Property.CullMode, properties, false);
|
||||
zwriteProp = FindProperty(Property.ZWriteControl, properties, false);
|
||||
ztestProp = FindProperty(Property.ZTest, properties, false);
|
||||
alphaClipProp = FindProperty(Property.AlphaClip, properties, false);
|
||||
|
||||
// ShaderGraph Lit and Unlit Subtargets only
|
||||
castShadowsProp = FindProperty(Property.CastShadows, properties, false);
|
||||
queueControlProp = FindProperty(Property.QueueControl, properties, false);
|
||||
|
||||
// ShaderGraph Lit, and Lit.shader
|
||||
receiveShadowsProp = FindProperty(Property.ReceiveShadows, properties, false);
|
||||
|
||||
// The following are not mandatory for shadergraphs (it's up to the user to add them to their graph)
|
||||
alphaCutoffProp = FindProperty("_Cutoff", properties, false);
|
||||
baseMapProp = FindProperty("_BaseMap", properties, false);
|
||||
baseColorProp = FindProperty("_BaseColor", properties, false);
|
||||
emissionMapProp = FindProperty(Property.EmissionMap, properties, false);
|
||||
emissionColorProp = FindProperty(Property.EmissionColor, properties, false);
|
||||
queueOffsetProp = FindProperty(Property.QueueOffset, properties, false);
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||||
{
|
||||
if (materialEditorIn == null)
|
||||
throw new ArgumentNullException("materialEditorIn");
|
||||
|
||||
materialEditor = materialEditorIn;
|
||||
Material material = materialEditor.target as Material;
|
||||
|
||||
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
protected virtual uint materialFilter => uint.MaxValue;
|
||||
|
||||
public virtual void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
var filter = (Expandable)materialFilter;
|
||||
|
||||
// Generate the foldouts
|
||||
if (filter.HasFlag(Expandable.SurfaceOptions))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.SurfaceOptions, (uint)Expandable.SurfaceOptions, DrawSurfaceOptions);
|
||||
|
||||
if (filter.HasFlag(Expandable.SurfaceInputs))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.SurfaceInputs, (uint)Expandable.SurfaceInputs, DrawSurfaceInputs);
|
||||
|
||||
if (filter.HasFlag(Expandable.Details))
|
||||
FillAdditionalFoldouts(m_MaterialScopeList);
|
||||
|
||||
if (filter.HasFlag(Expandable.Advanced))
|
||||
m_MaterialScopeList.RegisterHeaderScope(Styles.AdvancedLabel, (uint)Expandable.Advanced, DrawAdvancedOptions);
|
||||
}
|
||||
|
||||
public void ShaderPropertiesGUI(Material material)
|
||||
{
|
||||
m_MaterialScopeList.DrawHeaders(materialEditor, material);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Drawing Functions //
|
||||
////////////////////////////////////
|
||||
#region DrawingFunctions
|
||||
|
||||
internal void DrawShaderGraphProperties(Material material, IEnumerable<MaterialProperty> properties)
|
||||
{
|
||||
if (properties == null)
|
||||
return;
|
||||
|
||||
ShaderGraphPropertyDrawers.DrawShaderGraphGUI(materialEditor, properties);
|
||||
}
|
||||
|
||||
internal static void DrawFloatToggleProperty(GUIContent styles, MaterialProperty prop)
|
||||
{
|
||||
if (prop == null)
|
||||
return;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop.hasMixedValue;
|
||||
bool newValue = EditorGUILayout.Toggle(styles, prop.floatValue == 1);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop.floatValue = newValue ? 1.0f : 0.0f;
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public virtual void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
DoPopup(Styles.surfaceType, surfaceTypeProp, Styles.surfaceTypeNames);
|
||||
if ((surfaceTypeProp != null) && ((SurfaceType)surfaceTypeProp.floatValue == SurfaceType.Transparent))
|
||||
DoPopup(Styles.blendingMode, blendModeProp, Styles.blendModeNames);
|
||||
|
||||
DoPopup(Styles.cullingText, cullingProp, Styles.renderFaceNames);
|
||||
DoPopup(Styles.zwriteText, zwriteProp, Styles.zwriteNames);
|
||||
|
||||
if (ztestProp != null)
|
||||
materialEditor.IntPopupShaderProperty(ztestProp, Styles.ztestText.text, Styles.ztestNames, Styles.ztestValues);
|
||||
|
||||
DrawFloatToggleProperty(Styles.alphaClipText, alphaClipProp);
|
||||
|
||||
if ((alphaClipProp != null) && (alphaCutoffProp != null) && (alphaClipProp.floatValue == 1))
|
||||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||||
|
||||
DrawFloatToggleProperty(Styles.castShadowText, castShadowsProp);
|
||||
DrawFloatToggleProperty(Styles.receiveShadowText, receiveShadowsProp);
|
||||
}
|
||||
|
||||
public virtual void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawBaseProperties(material);
|
||||
}
|
||||
|
||||
public virtual void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Only draw the sorting priority field if queue control is set to "auto"
|
||||
bool autoQueueControl = GetAutomaticQueueControlSetting(material);
|
||||
if (autoQueueControl)
|
||||
DrawQueueOffsetField();
|
||||
materialEditor.EnableInstancingField();
|
||||
}
|
||||
|
||||
protected void DrawQueueOffsetField()
|
||||
{
|
||||
if (queueOffsetProp != null)
|
||||
materialEditor.IntSliderShaderProperty(queueOffsetProp, -queueOffsetRange, queueOffsetRange, Styles.queueSlider);
|
||||
}
|
||||
|
||||
public virtual void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList) { }
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEmissionTextureProperty()
|
||||
{
|
||||
if ((emissionMapProp == null) || (emissionColorProp == null))
|
||||
return;
|
||||
|
||||
using (new EditorGUI.IndentLevelScope(2))
|
||||
{
|
||||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawEmissionProperties(Material material, bool keyword)
|
||||
{
|
||||
var emissive = true;
|
||||
|
||||
if (!keyword)
|
||||
{
|
||||
DrawEmissionTextureProperty();
|
||||
}
|
||||
else
|
||||
{
|
||||
emissive = materialEditor.EmissionEnabledProperty();
|
||||
using (new EditorGUI.DisabledScope(!emissive))
|
||||
{
|
||||
DrawEmissionTextureProperty();
|
||||
}
|
||||
}
|
||||
|
||||
// If texture was assigned and color was black set color to white
|
||||
if ((emissionMapProp != null) && (emissionColorProp != null))
|
||||
{
|
||||
var hadEmissionTexture = emissionMapProp?.textureValue != null;
|
||||
var brightness = emissionColorProp.colorValue.maxColorComponent;
|
||||
if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f)
|
||||
emissionColorProp.colorValue = Color.white;
|
||||
}
|
||||
|
||||
if (emissive)
|
||||
{
|
||||
// Change the GI emission flag and fix it up with emissive as black if necessary.
|
||||
materialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (textureProp != null)
|
||||
materialEditor.TextureScaleOffsetProperty(textureProp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Material Data Functions //
|
||||
////////////////////////////////////
|
||||
#region MaterialDataFunctions
|
||||
|
||||
// this function is shared with ShaderGraph Lit/Unlit GUIs and also the hand-written GUIs
|
||||
internal static void UpdateMaterialSurfaceOptions(Material material, bool automaticRenderQueue)
|
||||
{
|
||||
// Setup blending - consistent across all Universal RP shaders
|
||||
SetupMaterialBlendModeInternal(material, out int renderQueue);
|
||||
|
||||
// apply automatic render queue
|
||||
if (automaticRenderQueue && (renderQueue != material.renderQueue))
|
||||
material.renderQueue = renderQueue;
|
||||
|
||||
bool isShaderGraph = material.IsShaderGraph();
|
||||
|
||||
// Cast Shadows
|
||||
bool castShadows = true;
|
||||
if (material.HasProperty(Property.CastShadows))
|
||||
{
|
||||
castShadows = (material.GetFloat(Property.CastShadows) != 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isShaderGraph)
|
||||
{
|
||||
// Lit.shadergraph or Unlit.shadergraph, but no material control defined
|
||||
// enable the pass in the material, so shader can decide...
|
||||
castShadows = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lit.shader or Unlit.shader -- set based on transparency
|
||||
castShadows = Rendering.Universal.ShaderGUI.LitGUI.IsOpaque(material);
|
||||
}
|
||||
}
|
||||
material.SetShaderPassEnabled("ShadowCaster", castShadows);
|
||||
|
||||
// Receive Shadows
|
||||
if (material.HasProperty(Property.ReceiveShadows))
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._RECEIVE_SHADOWS_OFF, material.GetFloat(Property.ReceiveShadows) == 0.0f);
|
||||
}
|
||||
|
||||
// this function is shared between ShaderGraph and hand-written GUIs
|
||||
internal static void UpdateMaterialRenderQueueControl(Material material)
|
||||
{
|
||||
//
|
||||
// Render Queue Control handling
|
||||
//
|
||||
// Check for a raw render queue (the actual serialized setting - material.renderQueue has already been converted)
|
||||
// setting of -1, indicating that the material property should be inherited from the shader.
|
||||
// If we find this, add a new property "render queue control" set to 0 so we will
|
||||
// always know to follow the surface type of the material (this matches the hand-written behavior)
|
||||
// If we find another value, add the the property set to 1 so we will know that the
|
||||
// user has explicitly selected a render queue and we should not override it.
|
||||
//
|
||||
bool isShaderGraph = material.IsShaderGraph(); // Non-shadergraph materials use automatic behavior
|
||||
int rawRenderQueue = MaterialAccess.ReadMaterialRawRenderQueue(material);
|
||||
if (!isShaderGraph || rawRenderQueue == -1)
|
||||
{
|
||||
material.SetFloat(Property.QueueControl, (float)QueueControl.Auto); // Automatic behavior - surface type override
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetFloat(Property.QueueControl, (float)QueueControl.UserOverride); // User has selected explicit render queue
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool GetAutomaticQueueControlSetting(Material material)
|
||||
{
|
||||
// If a Shader Graph material doesn't yet have the queue control property,
|
||||
// we should not engage automatic behavior until the shader gets reimported.
|
||||
bool automaticQueueControl = !material.IsShaderGraph();
|
||||
if (material.HasProperty(Property.QueueControl))
|
||||
{
|
||||
var queueControl = material.GetFloat(Property.QueueControl);
|
||||
if (queueControl < 0.0f)
|
||||
{
|
||||
// The property was added with a negative value, indicating it needs to be validated for this material
|
||||
UpdateMaterialRenderQueueControl(material);
|
||||
}
|
||||
automaticQueueControl = (material.GetFloat(Property.QueueControl) == (float)QueueControl.Auto);
|
||||
}
|
||||
return automaticQueueControl;
|
||||
}
|
||||
|
||||
// this is the function used by Lit.shader, Unlit.shader GUIs
|
||||
public static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null, Action<Material> shaderFunc = null)
|
||||
{
|
||||
UpdateMaterialSurfaceOptions(material, automaticRenderQueue: true);
|
||||
|
||||
// Setup double sided GI based on Cull state
|
||||
if (material.HasProperty(Property.CullMode))
|
||||
material.doubleSidedGI = (RenderFace)material.GetFloat(Property.CullMode) != RenderFace.Front;
|
||||
|
||||
// Temporary fix for lightmapping. TODO: to be replaced with attribute tag.
|
||||
if (material.HasProperty("_MainTex"))
|
||||
{
|
||||
material.SetTexture("_MainTex", material.GetTexture("_BaseMap"));
|
||||
material.SetTextureScale("_MainTex", material.GetTextureScale("_BaseMap"));
|
||||
material.SetTextureOffset("_MainTex", material.GetTextureOffset("_BaseMap"));
|
||||
}
|
||||
if (material.HasProperty("_Color"))
|
||||
material.SetColor("_Color", material.GetColor("_BaseColor"));
|
||||
|
||||
// Emission
|
||||
if (material.HasProperty(Property.EmissionColor))
|
||||
MaterialEditor.FixupEmissiveFlag(material);
|
||||
|
||||
bool shouldEmissionBeEnabled =
|
||||
(material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
|
||||
|
||||
// Not sure what this is used for, I don't see this property declared by any Unity shader in our repo...
|
||||
// I'm guessing it is some kind of legacy material upgrade support thing? Or maybe just dead code now...
|
||||
if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled)
|
||||
shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f;
|
||||
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._EMISSION, shouldEmissionBeEnabled);
|
||||
|
||||
// Normal Map
|
||||
if (material.HasProperty("_BumpMap"))
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._NORMALMAP, material.GetTexture("_BumpMap"));
|
||||
|
||||
// Shader specific keyword functions
|
||||
shadingModelFunc?.Invoke(material);
|
||||
shaderFunc?.Invoke(material);
|
||||
}
|
||||
|
||||
internal static void SetMaterialSrcDstBlendProperties(Material material, UnityEngine.Rendering.BlendMode srcBlend, UnityEngine.Rendering.BlendMode dstBlend)
|
||||
{
|
||||
if (material.HasProperty(Property.SrcBlend))
|
||||
material.SetFloat(Property.SrcBlend, (float)srcBlend);
|
||||
|
||||
if (material.HasProperty(Property.DstBlend))
|
||||
material.SetFloat(Property.DstBlend, (float)dstBlend);
|
||||
}
|
||||
|
||||
internal static void SetMaterialZWriteProperty(Material material, bool zwriteEnabled)
|
||||
{
|
||||
if (material.HasProperty(Property.ZWrite))
|
||||
material.SetFloat(Property.ZWrite, zwriteEnabled ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
internal static void SetupMaterialBlendModeInternal(Material material, out int automaticRenderQueue)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
bool alphaClip = false;
|
||||
if (material.HasProperty(Property.AlphaClip))
|
||||
alphaClip = material.GetFloat(Property.AlphaClip) >= 0.5;
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._ALPHATEST_ON, alphaClip);
|
||||
|
||||
// default is to use the shader render queue
|
||||
int renderQueue = material.shader.renderQueue;
|
||||
material.SetOverrideTag("RenderType", ""); // clear override tag
|
||||
if (material.HasProperty(Property.SurfaceType))
|
||||
{
|
||||
SurfaceType surfaceType = (SurfaceType)material.GetFloat(Property.SurfaceType);
|
||||
bool zwrite = false;
|
||||
CoreUtils.SetKeyword(material, ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT, surfaceType == SurfaceType.Transparent);
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
if (alphaClip)
|
||||
{
|
||||
renderQueue = (int)RenderQueue.AlphaTest;
|
||||
material.SetOverrideTag("RenderType", "TransparentCutout");
|
||||
}
|
||||
else
|
||||
{
|
||||
renderQueue = (int)RenderQueue.Geometry;
|
||||
material.SetOverrideTag("RenderType", "Opaque");
|
||||
}
|
||||
|
||||
SetMaterialSrcDstBlendProperties(material, UnityEngine.Rendering.BlendMode.One, UnityEngine.Rendering.BlendMode.Zero);
|
||||
zwrite = true;
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
material.DisableKeyword(ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT);
|
||||
}
|
||||
else // SurfaceType Transparent
|
||||
{
|
||||
BlendMode blendMode = (BlendMode)material.GetFloat(Property.BlendMode);
|
||||
|
||||
// Specific Transparent Mode Settings
|
||||
switch (blendMode)
|
||||
{
|
||||
case BlendMode.Alpha:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.SrcAlpha,
|
||||
UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
break;
|
||||
case BlendMode.Premultiply:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.One,
|
||||
UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.EnableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.SrcAlpha,
|
||||
UnityEngine.Rendering.BlendMode.One);
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
break;
|
||||
case BlendMode.Multiply:
|
||||
SetMaterialSrcDstBlendProperties(material,
|
||||
UnityEngine.Rendering.BlendMode.DstColor,
|
||||
UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.DisableKeyword(ShaderKeywordStrings._ALPHAPREMULTIPLY_ON);
|
||||
material.EnableKeyword(ShaderKeywordStrings._ALPHAMODULATE_ON);
|
||||
break;
|
||||
}
|
||||
|
||||
// General Transparent Material Settings
|
||||
material.SetOverrideTag("RenderType", "Transparent");
|
||||
zwrite = false;
|
||||
material.EnableKeyword(ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT);
|
||||
renderQueue = (int)RenderQueue.Transparent;
|
||||
}
|
||||
|
||||
// check for override enum
|
||||
if (material.HasProperty(Property.ZWriteControl))
|
||||
{
|
||||
var zwriteControl = (UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl)material.GetFloat(Property.ZWriteControl);
|
||||
if (zwriteControl == UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl.ForceEnabled)
|
||||
zwrite = true;
|
||||
else if (zwriteControl == UnityEditor.Rendering.Universal.ShaderGraph.ZWriteControl.ForceDisabled)
|
||||
zwrite = false;
|
||||
}
|
||||
SetMaterialZWriteProperty(material, zwrite);
|
||||
material.SetShaderPassEnabled("DepthOnly", zwrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no surface type property -- must be hard-coded by the shadergraph,
|
||||
// so ensure the pass is enabled at the material level
|
||||
material.SetShaderPassEnabled("DepthOnly", true);
|
||||
}
|
||||
|
||||
// must always apply queue offset, even if not set to material control
|
||||
if (material.HasProperty(Property.QueueOffset))
|
||||
renderQueue += (int)material.GetFloat(Property.QueueOffset);
|
||||
|
||||
automaticRenderQueue = renderQueue;
|
||||
}
|
||||
|
||||
public static void SetupMaterialBlendMode(Material material)
|
||||
{
|
||||
SetupMaterialBlendModeInternal(material, out int renderQueue);
|
||||
|
||||
// apply automatic render queue
|
||||
if (renderQueue != material.renderQueue)
|
||||
material.renderQueue = renderQueue;
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
// Clear all keywords for fresh start
|
||||
// Note: this will nuke user-selected custom keywords when they change shaders
|
||||
material.shaderKeywords = null;
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
// Setup keywords based on the new shader
|
||||
UpdateMaterial(material, MaterialUpdateType.ChangedAssignedShader);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Helper Functions //
|
||||
////////////////////////////////////
|
||||
#region HelperFunctions
|
||||
|
||||
public static void TwoFloatSingleLine(GUIContent title, MaterialProperty prop1, GUIContent prop1Label,
|
||||
MaterialProperty prop2, GUIContent prop2Label, MaterialEditor materialEditor, float labelWidth = 30f)
|
||||
{
|
||||
const int kInterFieldPadding = 2;
|
||||
|
||||
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 - 1, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop1.hasMixedValue;
|
||||
var prop1val = EditorGUI.FloatField(propRect1, prop1Label, prop1.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop1.floatValue = prop1val;
|
||||
|
||||
Rect propRect2 = new Rect(propRect1.x + propRect1.width + kInterFieldPadding, rect.y,
|
||||
propRect1.width, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop2.hasMixedValue;
|
||||
var prop2val = EditorGUI.FloatField(propRect2, prop2Label, prop2.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
prop2.floatValue = prop2val;
|
||||
|
||||
EditorGUI.indentLevel = indent;
|
||||
EditorGUIUtility.labelWidth = preLabelWidth;
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public void DoPopup(GUIContent label, MaterialProperty property, string[] options)
|
||||
{
|
||||
if (property != null)
|
||||
materialEditor.PopupShaderProperty(property, label, options);
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: faa1af574d7a1e94a89f04dbe126d52f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5faac1f019b9d88418c3721b7845b4d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
public class EnumFieldUtils : MonoBehaviour
|
||||
{
|
||||
public class EnumData
|
||||
{
|
||||
public Enum[] values;
|
||||
public int[] flagValues;
|
||||
public string[] displayNames;
|
||||
public string[] names;
|
||||
public string[] tooltip;
|
||||
public bool flags;
|
||||
public Type underlyingType;
|
||||
public bool unsigned;
|
||||
public bool serializable;
|
||||
}
|
||||
|
||||
static FieldInfo s_EnumDataField;
|
||||
|
||||
public static FieldInfo enumDataField
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_EnumDataField == null)
|
||||
{
|
||||
s_EnumDataField = typeof(EnumField).GetField("m_EnumData", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
return s_EnumDataField;
|
||||
}
|
||||
}
|
||||
|
||||
static FieldInfo s_values;
|
||||
static FieldInfo s_flagValues;
|
||||
static FieldInfo s_displayNames;
|
||||
static FieldInfo s_names;
|
||||
static FieldInfo s_tooltip;
|
||||
|
||||
static void InitializeFields()
|
||||
{
|
||||
Type enumType = enumDataField.FieldType;
|
||||
s_values = enumType.GetField("values", BindingFlags.Instance | BindingFlags.Public);
|
||||
s_flagValues = enumType.GetField("flagValues", BindingFlags.Instance | BindingFlags.Public);
|
||||
s_displayNames = enumType.GetField("displayNames", BindingFlags.Instance | BindingFlags.Public);
|
||||
s_names = enumType.GetField("names", BindingFlags.Instance | BindingFlags.Public);
|
||||
s_tooltip = enumType.GetField("tooltip", BindingFlags.Instance | BindingFlags.Public);
|
||||
}
|
||||
|
||||
public static object GetBoxedEnumData(EnumData enumData)
|
||||
{
|
||||
if (s_values == null)
|
||||
{
|
||||
InitializeFields();
|
||||
}
|
||||
Type enumType = enumDataField.FieldType;
|
||||
object s_BoxedEnumData = Activator.CreateInstance(enumType);
|
||||
s_values.SetValue(s_BoxedEnumData, enumData.values);
|
||||
s_flagValues.SetValue(s_BoxedEnumData, enumData.flagValues);
|
||||
s_displayNames.SetValue(s_BoxedEnumData, enumData.displayNames);
|
||||
s_names.SetValue(s_BoxedEnumData, enumData.names);
|
||||
s_tooltip.SetValue(s_BoxedEnumData, enumData.tooltip);
|
||||
return s_BoxedEnumData;
|
||||
}
|
||||
|
||||
static Action<EnumField, Enum> s_UpdateValueLabelAction;
|
||||
public static Action<EnumField, Enum> UpdateValueLabelAction
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_UpdateValueLabelAction == null)
|
||||
{
|
||||
MethodInfo updateValueInfo = typeof(EnumField).GetMethod("UpdateValueLabel", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
s_UpdateValueLabelAction = (Action<EnumField, Enum>)updateValueInfo.CreateDelegate(typeof(Action<EnumField, Enum>));
|
||||
}
|
||||
return s_UpdateValueLabelAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d01dcc398770dc44f863c389ddfa01d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using SLZ.SLZEditorTools;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class ForceReloadDrawer : MaterialPropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
|
||||
{
|
||||
ShaderGUIUtils.ForceRebuild(editor);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34c606745ae9ccb4bb0c7a630eb88ecf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 03e55040d94ce7448bb143a63b1e201a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,726 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine.Rendering;
|
||||
using Object = UnityEngine.Object;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using System.Reflection;
|
||||
using SLZ.SLZEditorTools;
|
||||
using UnityEditor.SLZMaterialUI;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static UnityEngine.Rendering.DebugUI.MessageBox;
|
||||
using UnityEditor.ShaderGraph;
|
||||
|
||||
namespace UnityEditor // This MUST be in the base editor namespace!!!!!
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
public class LitMASGUI : UIElementsMaterialEditor
|
||||
{
|
||||
const string keyword_DETAILS_ON = "_DETAILS_ON";
|
||||
const string keyword_BRDF = "_BRDFMAP";
|
||||
const string keyword_EXPENSIVE_TP = "_EXPENSIVE_TP";
|
||||
|
||||
const string defaultMASGUID = "75f1fbacfa73385419ec8d7700a107ea";
|
||||
static string s_defaultMASPath;
|
||||
static string defaultMASPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_defaultMASPath == null)
|
||||
{
|
||||
s_defaultMASPath = AssetDatabase.GUIDToAssetPath(defaultMASGUID);
|
||||
}
|
||||
return s_defaultMASPath;
|
||||
}
|
||||
}
|
||||
|
||||
enum PName
|
||||
{
|
||||
_BaseMap = 0,
|
||||
_BaseColor,
|
||||
_MetallicGlossMap,
|
||||
_Normals,
|
||||
_BumpMap,
|
||||
_Emission,
|
||||
_EmissionMap,
|
||||
_EmissionColor,
|
||||
_EmissionFalloff,
|
||||
_BakedMutiplier,
|
||||
_Details,
|
||||
_DetailMap,
|
||||
g_tBRDFMap,
|
||||
BRDFMAP,
|
||||
_HitRamp,
|
||||
_HitColor,
|
||||
|
||||
// Rendering properties
|
||||
_Surface,
|
||||
_BlendSrc,
|
||||
_BlendDst,
|
||||
_ZWrite,
|
||||
_Cull,
|
||||
|
||||
// Triplanar properties
|
||||
_Expensive,
|
||||
_RotateUVs,
|
||||
_DetailsuseLocalUVs,
|
||||
_UVScaler,
|
||||
}
|
||||
static ReadOnlySpan<string> propertyNames => new string[] {
|
||||
"_BaseMap",
|
||||
"_BaseColor",
|
||||
"_MetallicGlossMap",
|
||||
"_Normals",
|
||||
"_BumpMap",
|
||||
"_Emission",
|
||||
"_EmissionMap",
|
||||
"_EmissionColor",
|
||||
"_EmissionFalloff",
|
||||
"_BakedMutiplier",
|
||||
"_Details",
|
||||
"_DetailMap",
|
||||
"g_tBRDFMap",
|
||||
"BRDFMAP",
|
||||
"_HitRamp",
|
||||
"_HitColor",
|
||||
|
||||
// Rendering properties
|
||||
"_Surface",
|
||||
"_BlendSrc",
|
||||
"_BlendDst",
|
||||
"_ZWrite",
|
||||
"_Cull",
|
||||
|
||||
// Triplanar properties
|
||||
"_Expensive",
|
||||
"_RotateUVs",
|
||||
"_DetailsuseLocalUVs",
|
||||
"_UVScaler",
|
||||
};
|
||||
class ShaderPropertyTable
|
||||
{
|
||||
public int[] nameToPropIdx;
|
||||
//public int _BaseMap = -1;
|
||||
//public int _BaseColor = -1;
|
||||
//public int _Normals = -1;
|
||||
//public int _MetallicGlossMap = -1;
|
||||
//public int _Emission = -1;
|
||||
//public int _EmissionMap = -1;
|
||||
//public int _EmissionColor = -1;
|
||||
//public int _EmissionFalloff = -1;
|
||||
//public int _BakedMutiplier = -1;
|
||||
//public int _Details = -1;
|
||||
//public int _DetailMap = -1;
|
||||
//public int _SSROff = -1;
|
||||
//public int _SSRTemporalMul = -1;
|
||||
public List<int> unknownProperties;
|
||||
public int texturePropertyCount;
|
||||
}
|
||||
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
Debug.Log("Added Visual Element?");
|
||||
VisualElement root = new VisualElement();
|
||||
VisualElement MainWindow = new VisualElement();
|
||||
root.Add(MainWindow);
|
||||
bool success = base.Initialize(root,MainWindow);
|
||||
if (!success)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
MainWindow.styleSheets.Add(ShaderGUIUtils.shaderGUISheet);
|
||||
|
||||
MaterialProperty[] props = materialProperties;
|
||||
|
||||
int[] propIdx = ShaderGUIUtils.GetMaterialPropertyShaderIdx(props, base.shader);
|
||||
|
||||
ShaderImporter shaderImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(base.shader)) as ShaderImporter;
|
||||
|
||||
//ShaderGUIUtils.SanitizeMaterials(this.targets, props, propIdx, shader);
|
||||
|
||||
ShaderPropertyTable propTable = GetPropertyTable(props);
|
||||
materialFields = new List<BaseMaterialField>(props.Length + propTable.texturePropertyCount + 5); // Scale/offsets are separate fields, double the number of texture properties
|
||||
//int currentFieldIdx = 0;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Rendering Properties ------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
|
||||
Foldout drawProps = new Foldout();
|
||||
|
||||
|
||||
{
|
||||
//drawProps.value = false;
|
||||
|
||||
RenderQueueDropdown renderQueue = new RenderQueueDropdown(serializedObject, shader);
|
||||
|
||||
int surfaceIdx = PropertyIdx(ref propTable, PName._Surface);
|
||||
int blendSrcIdx = PropertyIdx(ref propTable, PName._BlendSrc);
|
||||
int blendDstIdx = PropertyIdx(ref propTable, PName._BlendDst);
|
||||
int zWriteIdx = PropertyIdx(ref propTable, PName._ZWrite);
|
||||
if (surfaceIdx != -1 && blendSrcIdx != -1 && blendDstIdx != -1 && zWriteIdx != -1)
|
||||
{
|
||||
MaterialDummyField blendSrcField = new MaterialDummyField(props[blendSrcIdx], propIdx[blendSrcIdx]);
|
||||
MaterialDummyField blendDstField = new MaterialDummyField(props[blendDstIdx], propIdx[blendDstIdx]);
|
||||
MaterialDummyField zWriteField = new MaterialDummyField(props[zWriteIdx], propIdx[zWriteIdx]);
|
||||
materialFields.Add(blendSrcField);
|
||||
materialFields.Add(blendDstField);
|
||||
materialFields.Add(zWriteField);
|
||||
|
||||
SurfaceTypeField surfaceTypeField = new SurfaceTypeField();
|
||||
surfaceTypeField.Initialize(
|
||||
props[surfaceIdx],
|
||||
propIdx[surfaceIdx],
|
||||
blendSrcField,
|
||||
blendDstField,
|
||||
zWriteField,
|
||||
renderQueue
|
||||
);
|
||||
surfaceTypeField.tooltip = LitMASGui_Tooltips.Surface.ToString();
|
||||
materialFields.Add(surfaceTypeField);
|
||||
drawProps.contentContainer.Add(surfaceTypeField);
|
||||
}
|
||||
|
||||
int cullIdx = PropertyIdx(ref propTable, PName._Cull);
|
||||
if (cullIdx != -1)
|
||||
{
|
||||
List<int> cullChoices = new List<int>() { (int)CullMode.Back, (int)CullMode.Front, (int)CullMode.Off};
|
||||
Dictionary<int, string> cullLabels = new Dictionary<int, string>() { { (int)CullMode.Back, "Front" }, { (int)CullMode.Front, "Back" }, { (int)CullMode.Off, "Both (EXPENSIVE)" } };
|
||||
|
||||
MaterialIntPopup cullPopup = new MaterialIntPopup();
|
||||
cullPopup.label = "Rendered Side";
|
||||
cullPopup.Initialize(props[cullIdx], propIdx[cullIdx], cullChoices, cullLabels);
|
||||
|
||||
materialFields.Add(cullPopup);
|
||||
drawProps.contentContainer.Add(cullPopup);
|
||||
}
|
||||
|
||||
drawProps.contentContainer.Add(renderQueue);
|
||||
}
|
||||
MainWindow.Add(drawProps);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Core Properties -----------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
|
||||
Foldout baseProps = new Foldout();
|
||||
Texture2D MaterialIcon = ShaderGUIUtils.GetClosestUnityIconMip("Material Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(baseProps, "Core Shading", MaterialIcon);
|
||||
bool hasCoreProperty = false;
|
||||
|
||||
// Base Map ------------------------------------------------------
|
||||
|
||||
|
||||
TextureField baseMapField = null;
|
||||
int baseMapIdx = PropertyIdx(ref propTable, PName._BaseMap);
|
||||
if (baseMapIdx != -1)
|
||||
{
|
||||
baseMapField = new TextureField(props[baseMapIdx], propIdx[baseMapIdx], false);
|
||||
baseMapField.tooltip2 = LitMASGui_Tooltips.BaseMap.ToString();
|
||||
baseProps.Add(baseMapField);
|
||||
materialFields.Add(baseMapField);
|
||||
hasCoreProperty = true;
|
||||
}
|
||||
|
||||
// Base Color ----------------------------------------------------
|
||||
int baseColorIdx = PropertyIdx(ref propTable, PName._BaseColor);
|
||||
if (baseColorIdx != -1)
|
||||
{
|
||||
MaterialColorField baseColorField = new MaterialColorField();
|
||||
if (baseMapField != null)
|
||||
{
|
||||
baseColorField.Initialize(props[baseColorIdx], propIdx[baseColorIdx], true);
|
||||
baseMapField.rightAlignBox.Add(baseColorField);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseColorField.Initialize(props[baseColorIdx], propIdx[baseColorIdx], false);
|
||||
baseProps.Add(baseColorField);
|
||||
}
|
||||
baseColorField.tooltip = LitMASGui_Tooltips.BaseColor.ToString();
|
||||
materialFields.Add(baseColorField);
|
||||
hasCoreProperty = true;
|
||||
}
|
||||
|
||||
// MAS Map -------------------------------------------------------
|
||||
int MASMapIdx = PropertyIdx(ref propTable, PName._MetallicGlossMap);
|
||||
if (MASMapIdx != -1)
|
||||
{
|
||||
Texture2D defaultMAS = AssetDatabase.LoadAssetAtPath<Texture2D>(defaultMASPath);
|
||||
TextureField MASMap = new TextureField(props[MASMapIdx], propIdx[MASMapIdx], false, shaderImporter?.GetDefaultTexture(props[MASMapIdx].name));
|
||||
MASMap.tooltip2 = LitMASGui_Tooltips.MASMap.ToString();
|
||||
baseProps.Add(MASMap);
|
||||
materialFields.Add(MASMap);
|
||||
hasCoreProperty = true;
|
||||
|
||||
MAS_defaultSlider defaultSlider = new MAS_defaultSlider(MASMap);
|
||||
MASMap.rightAlignBox.Add(defaultSlider);
|
||||
}
|
||||
|
||||
// Normal Map ----------------------------------------------------
|
||||
int NormalMapIdx = PropertyIdx(ref propTable, PName._BumpMap);
|
||||
if (NormalMapIdx != -1)
|
||||
{
|
||||
TextureField NormalMap = new TextureField(props[NormalMapIdx], propIdx[NormalMapIdx], true);
|
||||
NormalMap.tooltip2 = LitMASGui_Tooltips.NormalMap.ToString();
|
||||
baseProps.Add(NormalMap);
|
||||
materialFields.Add(NormalMap);
|
||||
|
||||
int NormalsIdx = PropertyIdx(ref propTable, PName._Normals);
|
||||
if (NormalsIdx != -1)
|
||||
{
|
||||
NormalMap.leftAlignBox.SetEnabled(props[NormalsIdx].floatValue > 0.0);
|
||||
MaterialToggleField normalToggle = new MaterialToggleField();
|
||||
normalToggle.Initialize(props[NormalsIdx], propIdx[NormalsIdx], null, false, true);
|
||||
normalToggle.RegisterValueChangedCallback(evt => NormalMap.leftAlignBox.SetEnabled(evt.newValue));
|
||||
NormalMap.rightAlignBox.Add(normalToggle);
|
||||
materialFields.Add(normalToggle);
|
||||
}
|
||||
hasCoreProperty = true;
|
||||
}
|
||||
|
||||
int BRDFRampIdx = PropertyIdx(ref propTable, PName.g_tBRDFMap);
|
||||
if(BRDFRampIdx != -1)
|
||||
{
|
||||
TextureField BRDFRamp = new TextureField(props[BRDFRampIdx], propIdx[BRDFRampIdx], false);
|
||||
//NormalMap.tooltip2 = LitMASGui_Tooltips.NormalMap.ToString();
|
||||
baseProps.Add(BRDFRamp);
|
||||
materialFields.Add(BRDFRamp);
|
||||
|
||||
int BRDFRampToggleIdx = PropertyIdx(ref propTable, PName.BRDFMAP);
|
||||
if (BRDFRampToggleIdx != -1)
|
||||
{
|
||||
BRDFRamp.leftAlignBox.SetEnabled(props[BRDFRampToggleIdx].floatValue > 0.0);
|
||||
MaterialToggleField BRDFRampToggle = new MaterialToggleField();
|
||||
BRDFRampToggle.Initialize(props[BRDFRampToggleIdx], propIdx[BRDFRampToggleIdx], keyword_BRDF, false, true);
|
||||
BRDFRampToggle.RegisterValueChangedCallback(evt => BRDFRamp.leftAlignBox.SetEnabled(evt.newValue));
|
||||
BRDFRamp.rightAlignBox.Add(BRDFRampToggle);
|
||||
materialFields.Add(BRDFRampToggle);
|
||||
}
|
||||
hasCoreProperty = true;
|
||||
}
|
||||
|
||||
// Triplanar options ---------------------------------------------
|
||||
|
||||
int fixSeamsIdx = PropertyIdx(ref propTable, PName._Expensive);
|
||||
if (fixSeamsIdx != -1)
|
||||
{
|
||||
MaterialToggleField seamToggle = new MaterialToggleField();
|
||||
seamToggle.Initialize(props[fixSeamsIdx], propIdx[fixSeamsIdx], keyword_EXPENSIVE_TP, false);
|
||||
materialFields.Add(seamToggle);
|
||||
baseProps.Add(seamToggle);
|
||||
}
|
||||
|
||||
int rotateUVsIdx = PropertyIdx(ref propTable, PName._RotateUVs);
|
||||
if (rotateUVsIdx != -1)
|
||||
{
|
||||
MaterialToggleField rotateUVsToggle = new MaterialToggleField();
|
||||
rotateUVsToggle.Initialize(props[rotateUVsIdx], propIdx[rotateUVsIdx], null, false);
|
||||
materialFields.Add(rotateUVsToggle);
|
||||
baseProps.Add(rotateUVsToggle);
|
||||
}
|
||||
int triplanarScaleIdx = PropertyIdx(ref propTable, PName._UVScaler);
|
||||
if (triplanarScaleIdx != -1)
|
||||
{
|
||||
MaterialFloatField triplanarScaleField = new MaterialFloatField();
|
||||
triplanarScaleField.Initialize(props[triplanarScaleIdx], propIdx[triplanarScaleIdx]);
|
||||
materialFields.Add(triplanarScaleField);
|
||||
baseProps.Add(triplanarScaleField);
|
||||
}
|
||||
|
||||
// Base map tiling offset ----------------------------------------
|
||||
|
||||
if (baseMapIdx != -1 && (props[baseMapIdx].flags & MaterialProperty.PropFlags.NoScaleOffset) == 0)
|
||||
{
|
||||
MaterialScaleOffsetField baseScaleOffsetField = new MaterialScaleOffsetField(props[baseMapIdx], propIdx[baseMapIdx]);
|
||||
baseProps.Add(baseScaleOffsetField);
|
||||
materialFields.Add(baseScaleOffsetField);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (hasCoreProperty)
|
||||
{
|
||||
Texture2D RTIcon = ShaderGUIUtils.GetClosestUnityIconMip("RenderTexture Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(drawProps, "Rendering Properties", RTIcon);
|
||||
MainWindow.Add(baseProps);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Emission Properties -------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
|
||||
Toggle emissionToggle = null;
|
||||
Foldout emissionProps = new Foldout();
|
||||
|
||||
|
||||
bool hasEmissionProperty = false;
|
||||
// Emission Map --------------------------------------------------
|
||||
|
||||
TextureField emissionMapField = null;
|
||||
int emissionMapIdx = PropertyIdx(ref propTable, PName._EmissionMap);
|
||||
if (emissionMapIdx != -1)
|
||||
{
|
||||
emissionMapField = new TextureField(props[emissionMapIdx], propIdx[emissionMapIdx], false);
|
||||
emissionMapField.tooltip2 = LitMASGui_Tooltips.EmissionMap.ToString();
|
||||
emissionProps.Add(emissionMapField);
|
||||
materialFields.Add(emissionMapField);
|
||||
hasEmissionProperty = true;
|
||||
}
|
||||
|
||||
int emissionColorIdx = PropertyIdx(ref propTable, PName._EmissionColor);
|
||||
if (emissionColorIdx != -1)
|
||||
{
|
||||
MaterialColorField emissionColorField = new MaterialColorField();
|
||||
emissionColorField.hdr = true;
|
||||
if (emissionMapIdx != -1)
|
||||
{
|
||||
emissionColorField.Initialize(props[emissionColorIdx], propIdx[emissionColorIdx], true);
|
||||
emissionMapField.rightAlignBox.Add(emissionColorField);
|
||||
}
|
||||
else
|
||||
{
|
||||
emissionColorField.Initialize(props[emissionColorIdx], propIdx[emissionColorIdx], false);
|
||||
emissionProps.Add(emissionColorField);
|
||||
}
|
||||
emissionColorField.tooltip = LitMASGui_Tooltips.EmissionColor.ToString();
|
||||
materialFields.Add(emissionColorField);
|
||||
hasEmissionProperty = true;
|
||||
}
|
||||
|
||||
int emissionFalloffIdx = PropertyIdx(ref propTable, PName._EmissionFalloff);
|
||||
if (emissionFalloffIdx != -1)
|
||||
{
|
||||
MaterialFloatField emissionFalloffField = new MaterialFloatField();
|
||||
|
||||
emissionFalloffField.Initialize(props[emissionFalloffIdx], propIdx[emissionFalloffIdx]);
|
||||
emissionProps.Add(emissionFalloffField);
|
||||
|
||||
emissionFalloffField.tooltip = LitMASGui_Tooltips.EmissionFalloff.ToString();
|
||||
materialFields.Add(emissionFalloffField);
|
||||
hasEmissionProperty = true;
|
||||
}
|
||||
|
||||
int emissionMultiplierIdx = PropertyIdx(ref propTable, PName._BakedMutiplier);
|
||||
if (emissionMultiplierIdx != -1)
|
||||
{
|
||||
MaterialFloatField emissionMultiplierField = new MaterialFloatField();
|
||||
|
||||
emissionMultiplierField.Initialize(props[emissionMultiplierIdx], propIdx[emissionMultiplierIdx]);
|
||||
emissionProps.Add(emissionMultiplierField);
|
||||
|
||||
emissionMultiplierField.tooltip = LitMASGui_Tooltips.EmissionFalloff.ToString();
|
||||
materialFields.Add(emissionMultiplierField);
|
||||
hasEmissionProperty = true;
|
||||
}
|
||||
|
||||
int emissionToggleIdx = PropertyIdx(ref propTable, PName._Emission);
|
||||
EmissionToggleField emissionMatToggle = null;
|
||||
if (emissionToggleIdx != -1)
|
||||
{
|
||||
emissionMatToggle = new EmissionToggleField();
|
||||
emissionMatToggle.Initialize(props[emissionToggleIdx], propIdx[emissionToggleIdx], null, false, true);
|
||||
|
||||
emissionMatToggle.RegisterCallback<ChangeEvent<bool>>(evt => { emissionProps.contentContainer.SetEnabled(evt.newValue); });
|
||||
emissionToggle = emissionMatToggle;
|
||||
materialFields.Add(emissionMatToggle);
|
||||
hasEmissionProperty = true;
|
||||
|
||||
bool emissionEnabled = props[emissionToggleIdx].floatValue > 0.0f;
|
||||
emissionProps.contentContainer.SetEnabled(emissionEnabled);
|
||||
}
|
||||
|
||||
|
||||
if (hasEmissionProperty)
|
||||
{
|
||||
GIFlagsPopup emissionFlags = new GIFlagsPopup(serializedObject);
|
||||
emissionProps.Add(emissionFlags);
|
||||
|
||||
Toggle doubleSidedGIToggle = new Toggle("Double Sided GI");
|
||||
SetAlignStyle(doubleSidedGIToggle);
|
||||
doubleSidedGIToggle.bindingPath = "m_DoubleSidedGI";
|
||||
emissionProps.Add(doubleSidedGIToggle);
|
||||
|
||||
Texture2D LightIcon = ShaderGUIUtils.GetClosestUnityIconMip("Light Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(emissionProps, "Emission", LightIcon, emissionToggle);
|
||||
MainWindow.Add(emissionProps);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Detail Properties ---------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
|
||||
Toggle detailToggle = null;
|
||||
Foldout detailProps = new Foldout();
|
||||
|
||||
bool hasDetails = false;
|
||||
|
||||
int detailMapIdx = PropertyIdx(ref propTable, PName._DetailMap);
|
||||
if (detailMapIdx != -1)
|
||||
{
|
||||
TextureField detailsMapField = new TextureField(props[detailMapIdx], propIdx[detailMapIdx], false, shaderImporter?.GetDefaultTexture(props[detailMapIdx].name));
|
||||
detailsMapField.tooltip2 = LitMASGui_Tooltips.DetailMap.ToString();
|
||||
detailProps.Add(detailsMapField);
|
||||
materialFields.Add(detailsMapField);
|
||||
hasDetails = true;
|
||||
|
||||
MaterialScaleOffsetField detailScaleOffset = new MaterialScaleOffsetField(props[detailMapIdx], propIdx[detailMapIdx]);
|
||||
detailProps.Add(detailScaleOffset);
|
||||
materialFields.Add(detailScaleOffset);
|
||||
}
|
||||
|
||||
int detailToggleIdx = PropertyIdx(ref propTable, PName._Details);
|
||||
if (detailToggleIdx != -1 && hasDetails)
|
||||
{
|
||||
MaterialToggleField detailMatToggle = new MaterialToggleField();
|
||||
detailMatToggle.Initialize(props[detailToggleIdx], propIdx[detailToggleIdx], keyword_DETAILS_ON, false, true);
|
||||
detailMatToggle.RegisterCallback<ChangeEvent<bool>>(evt => { detailProps.contentContainer.SetEnabled(evt.newValue); });
|
||||
bool detailEnabled = props[detailToggleIdx].floatValue > 0.0f;
|
||||
detailProps.contentContainer.SetEnabled(detailEnabled);
|
||||
materialFields.Add(detailMatToggle);
|
||||
detailToggle = detailMatToggle;
|
||||
}
|
||||
|
||||
|
||||
if (hasDetails)
|
||||
{
|
||||
Texture2D detailIcon = ShaderGUIUtils.GetClosestUnityIconMip("Grid Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(detailProps, "Details", detailIcon, detailToggle);
|
||||
MainWindow.Add(detailProps);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Impact Properties --------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
Foldout ImpactProps = new Foldout();
|
||||
bool hasImpacts = false;
|
||||
|
||||
int hitRampIdx = PropertyIdx(ref propTable, PName._HitRamp);
|
||||
TextureField hitRamp = null;
|
||||
if (hitRampIdx != -1)
|
||||
{
|
||||
hitRamp = new TextureField(props[hitRampIdx], propIdx[hitRampIdx], false);
|
||||
ImpactProps.Add(hitRamp);
|
||||
materialFields.Add(hitRamp);
|
||||
hasImpacts = true;
|
||||
}
|
||||
|
||||
int hitColorIdx = PropertyIdx(ref propTable, PName._HitColor);
|
||||
if (hitRampIdx != -1)
|
||||
{
|
||||
MaterialColorField hitColorField = new MaterialColorField();
|
||||
hitColorField.hdr = true;
|
||||
if (hitColorIdx != -1)
|
||||
{
|
||||
hitColorField.Initialize(props[hitColorIdx], propIdx[hitColorIdx], true);
|
||||
hitRamp.rightAlignBox.Add(hitColorField);
|
||||
}
|
||||
else
|
||||
{
|
||||
hitColorField.Initialize(props[emissionColorIdx], propIdx[emissionColorIdx], false);
|
||||
ImpactProps.Add(hitColorField);
|
||||
}
|
||||
hitColorField.tooltip = LitMASGui_Tooltips.EmissionColor.ToString();
|
||||
materialFields.Add(hitColorField);
|
||||
hasImpacts = true;
|
||||
}
|
||||
|
||||
if (hasImpacts)
|
||||
{
|
||||
Texture2D impactIcon = ShaderGUIUtils.GetClosestUnityIconMip("RaycastCollider Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(ImpactProps, "Impacts", impactIcon);
|
||||
MainWindow.Add(ImpactProps);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Unknown Properties --------------------------------------------
|
||||
//----------------------------------------------------------------
|
||||
Foldout unknownProps = new Foldout();
|
||||
Texture2D otherIcon = ShaderGUIUtils.GetClosestUnityIconMip("Settings Icon", 16);
|
||||
ShaderGUIUtils.SetHeaderStyle(unknownProps, "Other", otherIcon);
|
||||
|
||||
int numUnknown = propTable.unknownProperties.Count;
|
||||
List<int> unknownPropIdx = propTable.unknownProperties;
|
||||
for (int i = 0; i < numUnknown; i++)
|
||||
{
|
||||
MaterialProperty prop = props[unknownPropIdx[i]];
|
||||
int shaderIdx = propIdx[unknownPropIdx[i]];
|
||||
if ((prop.flags & MaterialProperty.PropFlags.HideInInspector) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (prop.type)
|
||||
{
|
||||
case (MaterialProperty.PropType.Texture):
|
||||
if ((prop.flags & MaterialProperty.PropFlags.NonModifiableTextureData) != 0) continue;
|
||||
TextureField tf = new TextureField(prop, shaderIdx, (prop.flags & MaterialProperty.PropFlags.Normal) != 0, shaderImporter?.GetDefaultTexture(prop.name));
|
||||
unknownProps.Add(tf);
|
||||
materialFields.Add(tf);
|
||||
|
||||
if ((prop.flags & MaterialProperty.PropFlags.NoScaleOffset) == 0)
|
||||
{
|
||||
MaterialScaleOffsetField msof = new MaterialScaleOffsetField(prop, shaderIdx);
|
||||
unknownProps.Add(msof);
|
||||
materialFields.Add(msof);
|
||||
}
|
||||
|
||||
break;
|
||||
case (MaterialProperty.PropType.Color):
|
||||
MaterialColorField cf = new MaterialColorField();
|
||||
if ((prop.flags & MaterialProperty.PropFlags.HDR) != 0)
|
||||
{
|
||||
cf.hdr = true;
|
||||
}
|
||||
cf.Initialize(prop, shaderIdx, false);
|
||||
unknownProps.Add(cf);
|
||||
materialFields.Add(cf);
|
||||
break;
|
||||
case (MaterialProperty.PropType.Vector):
|
||||
MaterialVectorField vf = new MaterialVectorField();
|
||||
vf.Initialize(prop, shaderIdx);
|
||||
unknownProps.Add(vf);
|
||||
materialFields.Add(vf);
|
||||
break;
|
||||
case (MaterialProperty.PropType.Range):
|
||||
if (shader.GetPropertyAttributes(shaderIdx).Contains("IntRange"))
|
||||
{
|
||||
MaterialIntRangeField irf = new MaterialIntRangeField();
|
||||
irf.Initialize(prop, shaderIdx);
|
||||
unknownProps.Add(irf);
|
||||
materialFields.Add(irf);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaterialRangeField rf = new MaterialRangeField();
|
||||
rf.Initialize(prop, shaderIdx);
|
||||
unknownProps.Add(rf);
|
||||
materialFields.Add(rf);
|
||||
}
|
||||
break;
|
||||
case (MaterialProperty.PropType.Float):
|
||||
string[] attributes = shader.GetPropertyAttributes(shaderIdx);
|
||||
string keyword;
|
||||
if (HasToggleAttribute(attributes, out keyword))
|
||||
{
|
||||
MaterialToggleField tgf = new MaterialToggleField();
|
||||
tgf.Initialize(prop, shaderIdx, keyword, false);
|
||||
unknownProps.Add(tgf);
|
||||
materialFields.Add(tgf);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaterialFloatField ff = new MaterialFloatField();
|
||||
ff.Initialize(prop, shaderIdx);
|
||||
unknownProps.Add(ff);
|
||||
materialFields.Add(ff);
|
||||
}
|
||||
break;
|
||||
case (MaterialProperty.PropType.Int):
|
||||
MaterialIntField inf = new MaterialIntField();
|
||||
inf.Initialize(prop, shaderIdx);
|
||||
unknownProps.Add(inf);
|
||||
materialFields.Add(inf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numUnknown > 0)
|
||||
{
|
||||
MainWindow.Add(unknownProps);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
static char[] attributeSeparators = new char[2] { '(', ')' };
|
||||
bool HasToggleAttribute(string[] attributes, out string keyword)
|
||||
{
|
||||
int numAttr = attributes.Length;
|
||||
for (int i = 0; i < numAttr; i++)
|
||||
{
|
||||
if (attributes[i].StartsWith("Toggle"))
|
||||
{
|
||||
if (attributes[i].Equals("ToggleUI"))
|
||||
{
|
||||
keyword = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Debug.Log(attributes[i]);
|
||||
string[] split = attributes[i].Split(attributeSeparators);
|
||||
keyword = split[1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
keyword = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ShaderPropertyTable GetPropertyTable(MaterialProperty[] props)
|
||||
{
|
||||
int numProps = props.Length;
|
||||
int numNames = propertyNames.Length;
|
||||
ShaderPropertyTable output = new ShaderPropertyTable();
|
||||
|
||||
int[] nameToPropIdx = new int[numNames];
|
||||
output.nameToPropIdx = nameToPropIdx;
|
||||
for (int i = 0; i < numNames; i++) nameToPropIdx[i] = -1;
|
||||
|
||||
output.unknownProperties = new List<int>(numProps);
|
||||
for (int propIdx = 0; propIdx < numProps; propIdx++)
|
||||
{
|
||||
if (props[propIdx].type == MaterialProperty.PropType.Texture) output.texturePropertyCount++;
|
||||
bool unknown = true;
|
||||
string propName = props[propIdx].name;
|
||||
for (int nameIdx = 0; nameIdx < numNames; nameIdx++)
|
||||
{
|
||||
if (nameToPropIdx[nameIdx] == -1 && string.Equals(propertyNames[nameIdx], propName))
|
||||
{
|
||||
nameToPropIdx[nameIdx] = propIdx;
|
||||
unknown = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unknown)
|
||||
{
|
||||
output.unknownProperties.Add(propIdx);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static int PropertyIdx(ref ShaderPropertyTable table, PName name)
|
||||
{
|
||||
return table.nameToPropIdx[(int)name];
|
||||
}
|
||||
|
||||
static void SetAlignStyle(VisualElement vi)
|
||||
{
|
||||
VisualElement left = vi.ElementAt(0);
|
||||
left.AddToClassList("materialGUILeftBox");
|
||||
left.style.overflow = Overflow.Hidden;
|
||||
left.style.minWidth = 0;
|
||||
VisualElement right = vi.ElementAt(1);
|
||||
right.AddToClassList("materialGUIRightBox");
|
||||
vi.style.justifyContent = Justify.FlexStart;
|
||||
vi.style.marginRight = 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 30e0cd503f4520e40808615cd58eaafc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLZ.SLZEditorTools
|
||||
{
|
||||
internal static class LitMASGui_Tooltips
|
||||
{
|
||||
public static ReadOnlySpan<char> BaseMap =>
|
||||
"Base Color (RGB).\nThe color of the material. When the material is metallic, this also tints the reflections";
|
||||
|
||||
public static ReadOnlySpan<char> BaseColor =>
|
||||
"Base color, tints the albedo map";
|
||||
|
||||
public static ReadOnlySpan<char> MASMap =>
|
||||
"Metallic (R), Ambient Occlusion (G), Smoothness (B).\nThe metallic controls how reflective the surface is and how much the albedo tints reflections. " +
|
||||
"Ambient occlusion is fake pre-baked shadows that darkens areas like crevices or creases which are likely to be shadowed by surface itself. " +
|
||||
"Smoothness controls the sharpness of reflections, and for non-metallic surfaces the strength of reflections.";
|
||||
|
||||
public static ReadOnlySpan<char> NormalMap =>
|
||||
"Unused (R), Normal Oct Y (G), Geometric Roughness (B), Normal Oct X (A).\nVector map that offsets the normal (direction the surface is facing) when calculating lighting. Used to add high-resolution detail to otherwise simple mesh geometry. " +
|
||||
"Also contains roughness calculated from the normal variance for the mips in the blue channel. Assumes normals are encoded into hemi-octahedral format and stored in the G and A channels. " +
|
||||
"The texture importer will by default automatically convert textures marked as normal maps to hemi-octahedral format and calculate geometric roughness";
|
||||
|
||||
public static ReadOnlySpan<char> EmissionMap =>
|
||||
"Emission Color (RGB).\nControls the intensity and color of light being emitted by the material";
|
||||
|
||||
public static ReadOnlySpan<char> EmissionColor =>
|
||||
"Tints the emission from the emission map. Additionally, the alpha channel controls " +
|
||||
"how much the albedo map tints the emission. As the alpha goes to 0, the emission is increasingly tinted by the albedo";
|
||||
|
||||
public static ReadOnlySpan<char> EmissionFalloff =>
|
||||
"Controls the strength of the emission fresenel. This is an effect where the strength of the emission decreases as the surface points farther away from the camera.";
|
||||
|
||||
public static ReadOnlySpan<char> EmissionBakedMultiplier =>
|
||||
"Artificially increases the strength of the emission when baking lights. WARNING: this will make specular lighting too " +
|
||||
"dark for other shaders that don't guestimate the specular from diffuse light probes. Shaders that do not use Bonelab's " +
|
||||
"custom lighting model will most likely only get specular lighting from reflection probes, and this " +
|
||||
"multiplier does not effect the brightness of this material as seen by reflection probes.";
|
||||
|
||||
public static ReadOnlySpan<char> DetailMap =>
|
||||
"Overlay Brighten/Darken (R), Normal X (G), Geometric Roughness (B), Normal Y (A).\nRed channel brightens or darkens the material, with 0.5 being neutral. " +
|
||||
"The rest of the channels are exactly like the normal map, and are blended with the normal map to allow having two different scales of normal details";
|
||||
|
||||
public static ReadOnlySpan<char> Surface =>
|
||||
"How the material is blended with the background. Opaque does what you'd expect and does not blend with what's behind it. Transparent is physically transparent, ie " +
|
||||
"only the diffuse lighting component is alpha blended with the background. Specular reflections off the surface are unaffected by alpha and are added " +
|
||||
"to the background. Thus you can still see reflections off a 0 alpha transparent object. Addtionally, as the metallic goes to 1, the material becomes opaque. Fade is " +
|
||||
"simple alpha blending; as the alpha goes to 0 the material fully disappears";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 681d21469bfc6a849b96b89958d9e0fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SLZMaterialUI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class MAS_defaultSlider : VisualElement
|
||||
{
|
||||
public TextureField MASField;
|
||||
|
||||
struct MASProperties
|
||||
{
|
||||
public int metallic;
|
||||
public int smoothness;
|
||||
}
|
||||
static Dictionary<Texture, MASProperties> MASProps;
|
||||
static Texture[] MASTextures;
|
||||
const int numSmoothness = 10;
|
||||
const int numMetallic = 1;
|
||||
const int smoothIncr = 100 / numSmoothness;
|
||||
const int metalIncr = 100 / numMetallic;
|
||||
|
||||
const string defaultTexPath = "Packages/com.unity.render-pipelines.universal/Textures/Default/MAS/";
|
||||
SliderInt SmoothnessSlider;
|
||||
Toggle MetallicCheck;
|
||||
|
||||
static void Init()
|
||||
{
|
||||
int numTex = (numSmoothness + 1) * (numMetallic+1);
|
||||
MASTextures = new Texture[numTex];
|
||||
MASProps = new Dictionary<Texture, MASProperties>(numTex);
|
||||
|
||||
int index = 0;
|
||||
for (int m = 0; m <= 100; m += metalIncr)
|
||||
{
|
||||
string mDigits = Mathf.Min(m, 99).ToString().PadLeft(2,'0');
|
||||
for (int s = 0; s <= 100; s += smoothIncr)
|
||||
{
|
||||
string sDigits = Mathf.Min(s, 99).ToString().PadLeft(2,'0');
|
||||
string path = string.Format("{0}/MAS_M{1}_S{2}.png", defaultTexPath, mDigits, sDigits);
|
||||
//Debug.Log(path);
|
||||
Texture2D mas = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
MASTextures[index] = mas;
|
||||
index++;
|
||||
MASProps.Add(mas, new MASProperties { metallic = m, smoothness = s });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MAS_defaultSlider(TextureField MASField)
|
||||
{
|
||||
this.MASField = MASField;
|
||||
SmoothnessSlider = new SliderInt(0, smoothIncr);
|
||||
MetallicCheck = new Toggle();
|
||||
MetallicCheck.style.marginRight = 8;
|
||||
MetallicCheck.style.marginBottom = 0;
|
||||
|
||||
this.style.flexDirection = FlexDirection.Row;
|
||||
this.style.alignItems = Align.Center;
|
||||
this.style.justifyContent = Justify.SpaceBetween;
|
||||
this.style.flexGrow = 1;
|
||||
this.style.paddingTop = 0;
|
||||
this.style.marginTop = 0;
|
||||
SmoothnessSlider.style.flexGrow = 1;
|
||||
SmoothnessSlider.style.flexShrink = 1;
|
||||
SmoothnessSlider.style.marginTop = 0;
|
||||
SmoothnessSlider.style.marginRight = 4;
|
||||
//SmoothnessSlider.style.alignSelf = Align.Center;
|
||||
//SmoothnessSlider.label = "Smoothness";
|
||||
Label metalLabel = new Label("Metal");
|
||||
|
||||
Label SmoothLabel = new Label("Smoothness");
|
||||
Add(metalLabel);
|
||||
Add(MetallicCheck);
|
||||
Add(SmoothLabel);
|
||||
Add(SmoothnessSlider);
|
||||
CheckIfDefault();
|
||||
MASField.texObjField.RegisterValueChangedCallback(evt => CheckIfDefault());
|
||||
SmoothnessSlider.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
int index = evt.newValue + (MetallicCheck.value ? numSmoothness + 1 : 0);
|
||||
MASField.texObjField.value = MASTextures[index];
|
||||
});
|
||||
|
||||
MetallicCheck.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
int index = SmoothnessSlider.value + (evt.newValue ? numSmoothness + 1 : 0);
|
||||
MASField.texObjField.value = MASTextures[index];
|
||||
});
|
||||
}
|
||||
|
||||
void CheckIfDefault()
|
||||
{
|
||||
if (MASProps == null || MASTextures == null)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
MASProperties props;
|
||||
Texture2D mas = MASField.texObjField.value as Texture2D;
|
||||
if (mas != null && MASProps.TryGetValue(mas, out props))
|
||||
{
|
||||
this.style.display = DisplayStyle.Flex;
|
||||
SmoothnessSlider.SetValueWithoutNotify(props.smoothness / numSmoothness);
|
||||
MetallicCheck.SetValueWithoutNotify(props.metallic > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b19b1d15cfa66184596abb2867615e59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
using System;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using UnityEditor.Rendering.Universal.ShaderGUI;
|
||||
using UnityEngine;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using BlendMode = UnityEngine.Rendering.BlendMode;
|
||||
using RenderQueue = UnityEngine.Rendering.RenderQueue;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
// Used for ShaderGraph Lit shaders
|
||||
class LitMASIMGUI : BaseShaderGUI
|
||||
{
|
||||
public MaterialProperty workflowMode;
|
||||
public MaterialProperty blendSrc;
|
||||
public MaterialProperty blendDst;
|
||||
public MaterialProperty temporalAcm;
|
||||
|
||||
|
||||
MaterialProperty[] properties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// save off the list of all properties for shadergraph
|
||||
this.properties = properties;
|
||||
|
||||
var material = materialEditor?.target as Material;
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
base.FindProperties(properties);
|
||||
workflowMode = BaseShaderGUI.FindProperty(Property.SpecularWorkflowMode, properties, false);
|
||||
blendSrc = BaseShaderGUI.FindProperty("_BlendSrc", properties, false);
|
||||
blendDst = BaseShaderGUI.FindProperty("_BlendDst", properties, false);
|
||||
zwriteProp = BaseShaderGUI.FindProperty("_ZWrite", properties, false);
|
||||
temporalAcm = BaseShaderGUI.FindProperty("_SSRTemporalMul", properties, false);
|
||||
}
|
||||
|
||||
static string[] surfaceNames = new string[]
|
||||
{
|
||||
"Opaque",
|
||||
"Transparent",
|
||||
"Fade",
|
||||
};
|
||||
|
||||
bool hasInitialized = false;
|
||||
bool hasSSR = false;
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
float surface = material.GetFloat("_Surface");
|
||||
Debug.Log(oldShader.name);
|
||||
if (oldShader.name.StartsWith("Universal Render Pipeline"))
|
||||
{
|
||||
bool hasBlendmode = oldShader.FindPropertyIndex("_Blend") >= 0;
|
||||
|
||||
|
||||
if (hasBlendmode)
|
||||
{
|
||||
float blend = material.GetFloat("_Blend");
|
||||
|
||||
if (surface > 0.0f && blend == (float)BaseShaderGUI.BlendMode.Alpha)
|
||||
{
|
||||
surface = 2.0f;
|
||||
material.SetFloat("_Surface", surface);
|
||||
}
|
||||
}
|
||||
bool hasEmission = material.IsKeywordEnabled("_EMISSION");
|
||||
if (hasEmission)
|
||||
{
|
||||
material.SetFloat("_Emission", 1);
|
||||
}
|
||||
}
|
||||
bool hasTemporalAcm = newShader.FindPropertyIndex("_SSRTemporalMul") >= 0;
|
||||
switch (surface)
|
||||
{
|
||||
case 0:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.SetFloat("_ZWrite", 1);
|
||||
material.renderQueue = -1;
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 1.0f);
|
||||
break;
|
||||
case 1:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.SetFloat("_ZWrite", 0);
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 0.0f);
|
||||
material.renderQueue = 3000;
|
||||
break;
|
||||
case 2:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.SetFloat("_ZWrite", 0);
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 0.0f);
|
||||
material.renderQueue = 3000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
int val = (int)surfaceTypeProp.floatValue;
|
||||
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = surfaceTypeProp.hasMixedValue;
|
||||
int newValue = EditorGUILayout.Popup(Styles.surfaceType, val, surfaceNames);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (EditorGUI.EndChangeCheck() && (newValue != val || surfaceTypeProp.hasMixedValue))
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo(Styles.surfaceType.text);
|
||||
surfaceTypeProp.floatValue = val = newValue;
|
||||
switch (newValue)
|
||||
{
|
||||
case 0:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.Zero;
|
||||
zwriteProp.floatValue = 1;
|
||||
SetQueue(-1);
|
||||
if (temporalAcm != null) temporalAcm.floatValue = 1;
|
||||
break;
|
||||
case 1:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha;
|
||||
zwriteProp.floatValue = 0;
|
||||
if (temporalAcm != null) temporalAcm.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
case 2:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.SrcAlpha;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha;
|
||||
zwriteProp.floatValue = 0;
|
||||
if (temporalAcm != null) temporalAcm.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (val != 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Non-opaque surfaces are EXPENSIVE on Quest and other mobile devices. Avoid when possible!", MessageType.Warning);
|
||||
}
|
||||
|
||||
DoPopup(Styles.cullingText, cullingProp, Styles.renderFaceNames);
|
||||
//DoPopup(Styles.zwriteText, zwriteProp, Styles.zwriteNames);
|
||||
materialEditor.RenderQueueField();
|
||||
if (ztestProp != null)
|
||||
materialEditor.IntPopupShaderProperty(ztestProp, Styles.ztestText.text, Styles.ztestNames, Styles.ztestValues);
|
||||
|
||||
DrawFloatToggleProperty(Styles.alphaClipText, alphaClipProp);
|
||||
|
||||
if ((alphaClipProp != null) && (alphaCutoffProp != null) && (alphaClipProp.floatValue == 1))
|
||||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||||
|
||||
DrawFloatToggleProperty(Styles.castShadowText, castShadowsProp);
|
||||
DrawFloatToggleProperty(Styles.receiveShadowText, receiveShadowsProp);
|
||||
hasInitialized = true;
|
||||
}
|
||||
|
||||
void SetQueue(int value)
|
||||
{
|
||||
UnityEngine.Object[] array3 = materialEditor.targets;
|
||||
foreach (UnityEngine.Object @object in array3)
|
||||
{
|
||||
((Material)@object).renderQueue = value;
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateQueue(Material mat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void UpdateMaterial(Material material, MaterialUpdateType updateType)
|
||||
{
|
||||
// newly created materials should initialize the globalIlluminationFlags (default is off)
|
||||
if (updateType == MaterialUpdateType.CreatedNewMaterial)
|
||||
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
|
||||
|
||||
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
|
||||
//BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
|
||||
LitGUI.SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkflow);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
UpdateMaterial(material, MaterialUpdateType.ModifiedMaterial);
|
||||
}
|
||||
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawShaderGraphProperties(material, properties);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Always show the queue control field. Only show the render queue field if queue control is set to user override
|
||||
DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
|
||||
//if (material.HasProperty(Property.QueueControl) && material.GetFloat(Property.QueueControl) == (float)QueueControl.UserOverride)
|
||||
|
||||
base.DrawAdvancedOptions(material);
|
||||
|
||||
// ignore emission color for shadergraphs, because shadergraphs don't have a hard-coded emission property, it's up to the user
|
||||
materialEditor.DoubleSidedGIField();
|
||||
materialEditor.LightmapEmissionFlagsProperty(0, enabled: true, ignoreEmissionColor: true);
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 01b3876e9bed3ad49a32f59cbcf453d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c811f0193eef849ec831aecd46767d34
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"reference": "GUID:2bafac87e7f4b9b418d9448d219b01ab"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4fb7e7ed7072b3742ae4d27c3ee5649d
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
[assembly: InternalsVisibleTo("Unity.RenderPipelines.Universal.Editor")]
|
||||
|
||||
namespace UnityEditor.Rendering.Universal
|
||||
{
|
||||
internal static class MaterialAccess
|
||||
{
|
||||
internal static int ReadMaterialRawRenderQueue(Material mat)
|
||||
{
|
||||
return mat.rawRenderQueue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fc8990925d7874f13aba12a9ea9c2e1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
using UnityEngine;
|
||||
using UnityEditorInternal;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
public static class ParticleGUI
|
||||
{
|
||||
public enum ColorMode
|
||||
{
|
||||
Multiply,
|
||||
Additive,
|
||||
Subtractive,
|
||||
Overlay,
|
||||
Color,
|
||||
Difference
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent colorMode = EditorGUIUtility.TrTextContent("Color Mode",
|
||||
"Controls how the Particle color and the Material color blend together.");
|
||||
|
||||
public static GUIContent flipbookMode = EditorGUIUtility.TrTextContent("Flip-Book Blending",
|
||||
"Blends the frames in a flip-book together in a smooth animation.");
|
||||
|
||||
public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent("Soft Particles",
|
||||
"Makes particles fade out when they get close to intersecting with the surface of other geometry in the depth buffer.");
|
||||
|
||||
public static GUIContent softParticlesFadeText = EditorGUIUtility.TrTextContent("Surface Fade");
|
||||
|
||||
public static GUIContent softParticlesNearFadeDistanceText =
|
||||
EditorGUIUtility.TrTextContent("Near",
|
||||
"The distance from the other surface where the particle is completely transparent.");
|
||||
|
||||
public static GUIContent softParticlesFarFadeDistanceText =
|
||||
EditorGUIUtility.TrTextContent("Far",
|
||||
"The distance from the other surface where the particle is completely opaque.");
|
||||
|
||||
public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Camera Fading",
|
||||
"Makes particles fade out when they get close to the camera.");
|
||||
|
||||
public static GUIContent cameraFadingDistanceText = EditorGUIUtility.TrTextContent("Distance");
|
||||
|
||||
public static GUIContent cameraNearFadeDistanceText =
|
||||
EditorGUIUtility.TrTextContent("Near",
|
||||
"The distance from the camera where the particle is completely transparent.");
|
||||
|
||||
public static GUIContent cameraFarFadeDistanceText =
|
||||
EditorGUIUtility.TrTextContent("Far", "The distance from the camera where the particle is completely opaque.");
|
||||
|
||||
public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Distortion",
|
||||
"Creates a distortion effect by making particles perform refraction with the objects drawn before them.");
|
||||
|
||||
public static GUIContent distortionStrength = EditorGUIUtility.TrTextContent("Strength",
|
||||
"Controls how much the Particle distorts the background. ");
|
||||
|
||||
public static GUIContent distortionBlend = EditorGUIUtility.TrTextContent("Blend",
|
||||
"Controls how visible the distortion effect is. At 0, there’s no visible distortion. At 1, only the distortion effect is visible, not the background.");
|
||||
|
||||
public static GUIContent VertexStreams = EditorGUIUtility.TrTextContent("Vertex Streams",
|
||||
"List detailing the expected layout of data sent to the shader from the particle system.");
|
||||
|
||||
public static string streamPositionText = "Position (POSITION.xyz)";
|
||||
public static string streamNormalText = "Normal (NORMAL.xyz)";
|
||||
public static string streamColorText = "Color (COLOR.xyzw)";
|
||||
public static string streamColorInstancedText = "Color (INSTANCED0.xyzw)";
|
||||
public static string streamUVText = "UV (TEXCOORD0.xy)";
|
||||
public static string streamUV2Text = "UV2 (TEXCOORD0.zw)";
|
||||
public static string streamAnimBlendText = "AnimBlend (TEXCOORD1.x)";
|
||||
public static string streamAnimFrameText = "AnimFrame (INSTANCED1.x)";
|
||||
public static string streamTangentText = "Tangent (TANGENT.xyzw)";
|
||||
|
||||
public static GUIContent streamApplyToAllSystemsText = EditorGUIUtility.TrTextContent("Fix Now",
|
||||
"Apply the vertex stream layout to all Particle Systems using this material");
|
||||
|
||||
public static string undoApplyCustomVertexStreams = L10n.Tr("Apply custom vertex streams from material");
|
||||
|
||||
public static GUIStyle vertexStreamIcon = new GUIStyle();
|
||||
}
|
||||
|
||||
private static ReorderableList vertexStreamList;
|
||||
|
||||
public struct ParticleProperties
|
||||
{
|
||||
// Surface Option Props
|
||||
public MaterialProperty colorMode;
|
||||
|
||||
// Advanced Props
|
||||
public MaterialProperty flipbookMode;
|
||||
public MaterialProperty softParticlesEnabled;
|
||||
public MaterialProperty cameraFadingEnabled;
|
||||
public MaterialProperty distortionEnabled;
|
||||
public MaterialProperty softParticlesNearFadeDistance;
|
||||
public MaterialProperty softParticlesFarFadeDistance;
|
||||
public MaterialProperty cameraNearFadeDistance;
|
||||
public MaterialProperty cameraFarFadeDistance;
|
||||
public MaterialProperty distortionBlend;
|
||||
public MaterialProperty distortionStrength;
|
||||
|
||||
public ParticleProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Option Props
|
||||
colorMode = BaseShaderGUI.FindProperty("_ColorMode", properties, false);
|
||||
// Advanced Props
|
||||
flipbookMode = BaseShaderGUI.FindProperty("_FlipbookBlending", properties);
|
||||
softParticlesEnabled = BaseShaderGUI.FindProperty("_SoftParticlesEnabled", properties);
|
||||
cameraFadingEnabled = BaseShaderGUI.FindProperty("_CameraFadingEnabled", properties);
|
||||
distortionEnabled = BaseShaderGUI.FindProperty("_DistortionEnabled", properties, false);
|
||||
softParticlesNearFadeDistance = BaseShaderGUI.FindProperty("_SoftParticlesNearFadeDistance", properties);
|
||||
softParticlesFarFadeDistance = BaseShaderGUI.FindProperty("_SoftParticlesFarFadeDistance", properties);
|
||||
cameraNearFadeDistance = BaseShaderGUI.FindProperty("_CameraNearFadeDistance", properties);
|
||||
cameraFarFadeDistance = BaseShaderGUI.FindProperty("_CameraFarFadeDistance", properties);
|
||||
distortionBlend = BaseShaderGUI.FindProperty("_DistortionBlend", properties, false);
|
||||
distortionStrength = BaseShaderGUI.FindProperty("_DistortionStrength", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetupMaterialWithColorMode(Material material)
|
||||
{
|
||||
var colorMode = (ColorMode)material.GetFloat("_ColorMode");
|
||||
|
||||
switch (colorMode)
|
||||
{
|
||||
case ColorMode.Multiply:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
break;
|
||||
case ColorMode.Overlay:
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.EnableKeyword("_COLOROVERLAY_ON");
|
||||
break;
|
||||
case ColorMode.Color:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.EnableKeyword("_COLORCOLOR_ON");
|
||||
break;
|
||||
case ColorMode.Difference:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(-1.0f, 1.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
case ColorMode.Additive:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(1.0f, 0.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
case ColorMode.Subtractive:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(-1.0f, 0.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void FadingOptions(Material material, MaterialEditor materialEditor, ParticleProperties properties)
|
||||
{
|
||||
// Z write doesn't work with fading
|
||||
bool hasZWrite = (material.GetFloat("_ZWrite") > 0.0f);
|
||||
if (!hasZWrite)
|
||||
{
|
||||
// Soft Particles
|
||||
{
|
||||
materialEditor.ShaderProperty(properties.softParticlesEnabled, Styles.softParticlesEnabled);
|
||||
if (properties.softParticlesEnabled.floatValue >= 0.5f)
|
||||
{
|
||||
UniversalRenderPipelineAsset urpAsset = UniversalRenderPipeline.asset;
|
||||
if (urpAsset != null && !urpAsset.supportsCameraDepthTexture)
|
||||
{
|
||||
GUIStyle warnStyle = new GUIStyle(GUI.skin.label);
|
||||
warnStyle.fontStyle = FontStyle.BoldAndItalic;
|
||||
warnStyle.wordWrap = true;
|
||||
EditorGUILayout.HelpBox("Soft Particles require depth texture. Please enable \"Depth Texture\" in the Universal Render Pipeline settings.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
BaseShaderGUI.TwoFloatSingleLine(Styles.softParticlesFadeText,
|
||||
properties.softParticlesNearFadeDistance,
|
||||
Styles.softParticlesNearFadeDistanceText,
|
||||
properties.softParticlesFarFadeDistance,
|
||||
Styles.softParticlesFarFadeDistanceText,
|
||||
materialEditor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
// Camera Fading
|
||||
{
|
||||
materialEditor.ShaderProperty(properties.cameraFadingEnabled, Styles.cameraFadingEnabled);
|
||||
if (properties.cameraFadingEnabled.floatValue >= 0.5f)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
BaseShaderGUI.TwoFloatSingleLine(Styles.cameraFadingDistanceText,
|
||||
properties.cameraNearFadeDistance,
|
||||
Styles.cameraNearFadeDistanceText,
|
||||
properties.cameraFarFadeDistance,
|
||||
Styles.cameraFarFadeDistanceText,
|
||||
materialEditor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
// Distortion
|
||||
if (properties.distortionEnabled != null)
|
||||
{
|
||||
materialEditor.ShaderProperty(properties.distortionEnabled, Styles.distortionEnabled);
|
||||
if (properties.distortionEnabled.floatValue >= 0.5f)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditor.ShaderProperty(properties.distortionStrength, Styles.distortionStrength);
|
||||
materialEditor.ShaderProperty(properties.distortionBlend, Styles.distortionBlend);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoVertexStreamsArea(Material material, List<ParticleSystemRenderer> renderers, bool useLighting = false)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
// Display list of streams required to make this shader work
|
||||
bool useNormalMap = false;
|
||||
bool useFlipbookBlending = (material.GetFloat("_FlipbookBlending") > 0.0f);
|
||||
if (material.HasProperty("_BumpMap"))
|
||||
useNormalMap = material.GetTexture("_BumpMap");
|
||||
|
||||
bool useGPUInstancing = ShaderUtil.HasProceduralInstancing(material.shader);
|
||||
if (useGPUInstancing && renderers.Count > 0)
|
||||
{
|
||||
if (!renderers[0].enableGPUInstancing || renderers[0].renderMode != ParticleSystemRenderMode.Mesh)
|
||||
useGPUInstancing = false;
|
||||
}
|
||||
|
||||
// Build the list of expected vertex streams
|
||||
List<ParticleSystemVertexStream> streams = new List<ParticleSystemVertexStream>();
|
||||
List<string> streamList = new List<string>();
|
||||
|
||||
streams.Add(ParticleSystemVertexStream.Position);
|
||||
streamList.Add(Styles.streamPositionText);
|
||||
|
||||
if (useLighting || useNormalMap)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.Normal);
|
||||
streamList.Add(Styles.streamNormalText);
|
||||
if (useNormalMap)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.Tangent);
|
||||
streamList.Add(Styles.streamTangentText);
|
||||
}
|
||||
}
|
||||
|
||||
streams.Add(ParticleSystemVertexStream.Color);
|
||||
streamList.Add(useGPUInstancing ? Styles.streamColorInstancedText : Styles.streamColorText);
|
||||
streams.Add(ParticleSystemVertexStream.UV);
|
||||
streamList.Add(Styles.streamUVText);
|
||||
|
||||
List<ParticleSystemVertexStream> instancedStreams = new List<ParticleSystemVertexStream>(streams);
|
||||
|
||||
if (useGPUInstancing)
|
||||
{
|
||||
instancedStreams.Add(ParticleSystemVertexStream.AnimFrame);
|
||||
streamList.Add(Styles.streamAnimFrameText);
|
||||
}
|
||||
else if (useFlipbookBlending && !useGPUInstancing)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.UV2);
|
||||
streamList.Add(Styles.streamUV2Text);
|
||||
streams.Add(ParticleSystemVertexStream.AnimBlend);
|
||||
streamList.Add(Styles.streamAnimBlendText);
|
||||
}
|
||||
|
||||
vertexStreamList = new ReorderableList(streamList, typeof(string), false, true, false, false);
|
||||
|
||||
vertexStreamList.drawHeaderCallback = (Rect rect) =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, Styles.VertexStreams);
|
||||
};
|
||||
|
||||
vertexStreamList.DoLayoutList();
|
||||
|
||||
// Display a warning if any renderers have incorrect vertex streams
|
||||
string Warnings = "";
|
||||
List<ParticleSystemVertexStream> rendererStreams = new List<ParticleSystemVertexStream>();
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
renderer.GetActiveVertexStreams(rendererStreams);
|
||||
|
||||
bool streamsValid;
|
||||
if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)
|
||||
streamsValid = CompareVertexStreams(rendererStreams, instancedStreams);
|
||||
else
|
||||
streamsValid = CompareVertexStreams(rendererStreams, instancedStreams);
|
||||
|
||||
if (!streamsValid)
|
||||
Warnings += "-" + renderer.name + "\n";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Warnings))
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
"The following Particle System Renderers are using this material with incorrect Vertex Streams:\n" +
|
||||
Warnings, MessageType.Error, true);
|
||||
// Set the streams on all systems using this material
|
||||
if (GUILayout.Button(Styles.streamApplyToAllSystemsText, EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
|
||||
{
|
||||
Undo.RecordObjects(renderers.Where(r => r != null).ToArray(), Styles.undoApplyCustomVertexStreams);
|
||||
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)
|
||||
renderer.SetActiveVertexStreams(instancedStreams);
|
||||
else
|
||||
renderer.SetActiveVertexStreams(streams);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CompareVertexStreams(IEnumerable<ParticleSystemVertexStream> a, IEnumerable<ParticleSystemVertexStream> b)
|
||||
{
|
||||
var differenceA = a.Except(b);
|
||||
var differenceB = b.Except(a);
|
||||
var difference = differenceA.Union(differenceB).Distinct();
|
||||
if (!difference.Any())
|
||||
return true;
|
||||
// If normals are the only difference, ignore them, because the default particle streams include normals, to make it easy for users to switch between lit and unlit
|
||||
if (difference.Count() == 1)
|
||||
{
|
||||
if (difference.First() == ParticleSystemVertexStream.Normal)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
// Setup particle + material color blending
|
||||
SetupMaterialWithColorMode(material);
|
||||
// Is the material transparent, this is set in BaseShaderGUI
|
||||
bool isTransparent = material.GetTag("RenderType", false) == "Transparent";
|
||||
// Z write doesn't work with distortion/fading
|
||||
bool hasZWrite = (material.GetFloat("_ZWrite") > 0.0f);
|
||||
|
||||
// Flipbook blending
|
||||
if (material.HasProperty("_FlipbookBlending"))
|
||||
{
|
||||
var useFlipbookBlending = (material.GetFloat("_FlipbookBlending") > 0.0f);
|
||||
CoreUtils.SetKeyword(material, "_FLIPBOOKBLENDING_ON", useFlipbookBlending);
|
||||
}
|
||||
// Soft particles
|
||||
var useSoftParticles = false;
|
||||
if (material.HasProperty("_SoftParticlesEnabled"))
|
||||
{
|
||||
useSoftParticles = (material.GetFloat("_SoftParticlesEnabled") > 0.0f && isTransparent);
|
||||
if (useSoftParticles)
|
||||
{
|
||||
var softParticlesNearFadeDistance = material.GetFloat("_SoftParticlesNearFadeDistance");
|
||||
var softParticlesFarFadeDistance = material.GetFloat("_SoftParticlesFarFadeDistance");
|
||||
// clamp values
|
||||
if (softParticlesNearFadeDistance < 0.0f)
|
||||
{
|
||||
softParticlesNearFadeDistance = 0.0f;
|
||||
material.SetFloat("_SoftParticlesNearFadeDistance", 0.0f);
|
||||
}
|
||||
|
||||
if (softParticlesFarFadeDistance < 0.0f)
|
||||
{
|
||||
softParticlesFarFadeDistance = 0.0f;
|
||||
material.SetFloat("_SoftParticlesFarFadeDistance", 0.0f);
|
||||
}
|
||||
// set keywords
|
||||
material.SetVector("_SoftParticleFadeParams",
|
||||
new Vector4(softParticlesNearFadeDistance,
|
||||
1.0f / (softParticlesFarFadeDistance - softParticlesNearFadeDistance), 0.0f, 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetVector("_SoftParticleFadeParams", new Vector4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
CoreUtils.SetKeyword(material, "_SOFTPARTICLES_ON", useSoftParticles);
|
||||
}
|
||||
// Camera fading
|
||||
var useCameraFading = false;
|
||||
if (material.HasProperty("_CameraFadingEnabled") && isTransparent)
|
||||
{
|
||||
useCameraFading = (material.GetFloat("_CameraFadingEnabled") > 0.0f);
|
||||
if (useCameraFading)
|
||||
{
|
||||
var cameraNearFadeDistance = material.GetFloat("_CameraNearFadeDistance");
|
||||
var cameraFarFadeDistance = material.GetFloat("_CameraFarFadeDistance");
|
||||
// clamp values
|
||||
if (cameraNearFadeDistance < 0.0f)
|
||||
{
|
||||
cameraNearFadeDistance = 0.0f;
|
||||
material.SetFloat("_CameraNearFadeDistance", 0.0f);
|
||||
}
|
||||
|
||||
if (cameraFarFadeDistance < 0.0f)
|
||||
{
|
||||
cameraFarFadeDistance = 0.0f;
|
||||
material.SetFloat("_CameraFarFadeDistance", 0.0f);
|
||||
}
|
||||
// set keywords
|
||||
material.SetVector("_CameraFadeParams",
|
||||
new Vector4(cameraNearFadeDistance, 1.0f / (cameraFarFadeDistance - cameraNearFadeDistance),
|
||||
0.0f, 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetVector("_CameraFadeParams", new Vector4(0.0f, Mathf.Infinity, 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
// Distortion
|
||||
if (material.HasProperty("_DistortionEnabled"))
|
||||
{
|
||||
var useDistortion = (material.GetFloat("_DistortionEnabled") > 0.0f) && isTransparent;
|
||||
CoreUtils.SetKeyword(material, "_DISTORTION_ON", useDistortion);
|
||||
if (useDistortion)
|
||||
material.SetFloat("_DistortionStrengthScaled", material.GetFloat("_DistortionStrength") * 0.1f);
|
||||
}
|
||||
|
||||
var useFading = (useSoftParticles || useCameraFading) && !hasZWrite;
|
||||
CoreUtils.SetKeyword(material, "_FADING_ON", useFading);
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2b54c0ca113574ce495f3b706648b6d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using UnityEditor.Rendering.Universal.ShaderGUI;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
class SLZUnlit_IMGUI : BaseShaderGUI
|
||||
{
|
||||
public MaterialProperty blendSrc;
|
||||
public MaterialProperty blendDst;
|
||||
|
||||
MaterialProperty[] properties;
|
||||
|
||||
public enum UnlitBlendModes
|
||||
{
|
||||
Opaque = 0,
|
||||
AlphaPremultiplied,
|
||||
AlphaBlended,
|
||||
Additive,
|
||||
Multiplicative,
|
||||
}
|
||||
|
||||
static string[] unlitBlendModeNames = Enum.GetNames(typeof(UnlitBlendModes));
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// save off the list of all properties for shadergraph
|
||||
this.properties = properties;
|
||||
|
||||
var material = materialEditor?.target as Material;
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
base.FindProperties(properties);
|
||||
blendModeProp = BaseShaderGUI.FindProperty("_BlendMode", properties, false);
|
||||
blendSrc = BaseShaderGUI.FindProperty("_BlendSrc", properties, false);
|
||||
blendDst = BaseShaderGUI.FindProperty("_BlendDst", properties, false);
|
||||
zwriteProp = BaseShaderGUI.FindProperty("_ZWrite", properties, false);
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
float surface = material.GetFloat("_Surface");
|
||||
Debug.Log(oldShader.name);
|
||||
if (oldShader.name.StartsWith("Universal Render Pipeline"))
|
||||
{
|
||||
bool hasBlendmode = oldShader.FindPropertyIndex("_Blend") >= 0;
|
||||
|
||||
|
||||
if (hasBlendmode)
|
||||
{
|
||||
float blend = material.GetFloat("_Blend");
|
||||
|
||||
if (surface > 0.0f && blend == (float)BaseShaderGUI.BlendMode.Alpha)
|
||||
{
|
||||
surface = 2.0f;
|
||||
material.SetFloat("_Surface", surface);
|
||||
}
|
||||
}
|
||||
bool hasEmission = material.IsKeywordEnabled("_EMISSION");
|
||||
if (hasEmission)
|
||||
{
|
||||
material.SetFloat("_Emission", 1);
|
||||
}
|
||||
}
|
||||
bool hasTemporalAcm = newShader.FindPropertyIndex("_SSRTemporalMul") >= 0;
|
||||
switch (surface)
|
||||
{
|
||||
case 0:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.SetFloat("_ZWrite", 1);
|
||||
material.renderQueue = -1;
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 1.0f);
|
||||
break;
|
||||
case 1:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.SetFloat("_ZWrite", 0);
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 0.0f);
|
||||
material.renderQueue = 3000;
|
||||
break;
|
||||
case 2:
|
||||
material.SetFloat("_BlendSrc", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
material.SetFloat("_BlendDst", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.SetFloat("_ZWrite", 0);
|
||||
if (hasTemporalAcm) material.SetFloat("_SSRTemporalMul", 0.0f);
|
||||
material.renderQueue = 3000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
int val = (int)blendModeProp.floatValue;
|
||||
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = blendModeProp.hasMixedValue;
|
||||
int newValue = EditorGUILayout.Popup(Styles.blendingMode, val, unlitBlendModeNames);
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (EditorGUI.EndChangeCheck() && (newValue != val || blendModeProp.hasMixedValue))
|
||||
{
|
||||
UnlitBlendModes enumVal = (UnlitBlendModes)newValue;
|
||||
materialEditor.RegisterPropertyChangeUndo(Styles.blendingMode.text);
|
||||
blendModeProp.floatValue = val = newValue;
|
||||
switch (enumVal)
|
||||
{
|
||||
case UnlitBlendModes.Opaque:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.Zero;
|
||||
zwriteProp.floatValue = 1;
|
||||
SetQueue(-1);
|
||||
break;
|
||||
case UnlitBlendModes.AlphaPremultiplied:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha;
|
||||
zwriteProp.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
case UnlitBlendModes.AlphaBlended:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.SrcAlpha;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha;
|
||||
zwriteProp.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
case UnlitBlendModes.Additive:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.One;
|
||||
zwriteProp.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
case UnlitBlendModes.Multiplicative:
|
||||
blendSrc.floatValue = (float)UnityEngine.Rendering.BlendMode.DstColor;
|
||||
blendDst.floatValue = (float)UnityEngine.Rendering.BlendMode.Zero;
|
||||
zwriteProp.floatValue = 0;
|
||||
SetQueue(3000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (val != 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Non-opaque surfaces are EXPENSIVE on Quest and other mobile devices. Avoid when possible!", MessageType.Warning);
|
||||
}
|
||||
|
||||
DoPopup(Styles.cullingText, cullingProp, Styles.renderFaceNames);
|
||||
//DoPopup(Styles.zwriteText, zwriteProp, Styles.zwriteNames);
|
||||
materialEditor.RenderQueueField();
|
||||
if (ztestProp != null)
|
||||
materialEditor.IntPopupShaderProperty(ztestProp, Styles.ztestText.text, Styles.ztestNames, Styles.ztestValues);
|
||||
|
||||
DrawFloatToggleProperty(Styles.alphaClipText, alphaClipProp);
|
||||
|
||||
if ((alphaClipProp != null) && (alphaCutoffProp != null) && (alphaClipProp.floatValue == 1))
|
||||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||||
|
||||
DrawFloatToggleProperty(Styles.castShadowText, castShadowsProp);
|
||||
DrawFloatToggleProperty(Styles.receiveShadowText, receiveShadowsProp);
|
||||
}
|
||||
|
||||
void SetQueue(int value)
|
||||
{
|
||||
UnityEngine.Object[] array3 = materialEditor.targets;
|
||||
foreach (UnityEngine.Object @object in array3)
|
||||
{
|
||||
((Material)@object).renderQueue = value;
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateQueue(Material mat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void UpdateMaterial(Material material, MaterialUpdateType updateType)
|
||||
{
|
||||
// newly created materials should initialize the globalIlluminationFlags (default is off)
|
||||
if (updateType == MaterialUpdateType.CreatedNewMaterial)
|
||||
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
|
||||
|
||||
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
|
||||
//BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
|
||||
LitGUI.SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkflow);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
UpdateMaterial(material, MaterialUpdateType.ModifiedMaterial);
|
||||
}
|
||||
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawShaderGraphProperties(material, properties);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Always show the queue control field. Only show the render queue field if queue control is set to user override
|
||||
DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
|
||||
//if (material.HasProperty(Property.QueueControl) && material.GetFloat(Property.QueueControl) == (float)QueueControl.UserOverride)
|
||||
|
||||
base.DrawAdvancedOptions(material);
|
||||
|
||||
// ignore emission color for shadergraphs, because shadergraphs don't have a hard-coded emission property, it's up to the user
|
||||
materialEditor.DoubleSidedGIField();
|
||||
materialEditor.LightmapEmissionFlagsProperty(0, enabled: true, ignoreEmissionColor: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f4531d6ebd8d69549954e73e74c5172d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
using Unity.Collections;
|
||||
using Unity.Mathematics;
|
||||
using System.IO;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace SLZ.SLZEditorTools
|
||||
{
|
||||
public static class ShaderGUIUtils
|
||||
{
|
||||
|
||||
const string shaderGUIStylePath = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGUI/Styles/ShaderGUIStyles.uss";
|
||||
static StyleSheet s_ShaderGUISheet;
|
||||
public static StyleSheet shaderGUISheet
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_ShaderGUISheet == null)
|
||||
{
|
||||
s_ShaderGUISheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(shaderGUIStylePath);
|
||||
if (s_ShaderGUISheet == null)
|
||||
{
|
||||
Debug.LogError("Failed to find Shader GUI Style Sheet at " + shaderGUIStylePath);
|
||||
}
|
||||
}
|
||||
|
||||
return s_ShaderGUISheet;
|
||||
}
|
||||
}
|
||||
|
||||
static FieldInfo s_InaccessibleToggle;
|
||||
/// <summary>
|
||||
/// Makes a foldout look like a unity inspector header.
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="iconTex"></param>
|
||||
public static void SetHeaderStyle(Foldout f, string title, Texture iconTex = null, Toggle headerToggle = null)
|
||||
{
|
||||
|
||||
f.AddToClassList("headerRoot");
|
||||
if (s_InaccessibleToggle == null)
|
||||
{
|
||||
s_InaccessibleToggle = typeof(Foldout).GetField("m_Toggle", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
}
|
||||
Toggle actualFuckingToggle = (Toggle)s_InaccessibleToggle.GetValue(f);
|
||||
actualFuckingToggle.AddToClassList("headerTogglebar");
|
||||
actualFuckingToggle.style.paddingBottom = 3;
|
||||
actualFuckingToggle.style.paddingTop = 2;
|
||||
actualFuckingToggle.style.marginBottom = 1;
|
||||
VisualElement container = actualFuckingToggle.ElementAt(0);
|
||||
container.style.marginRight = 0;
|
||||
container.style.alignItems = Align.Center;
|
||||
VisualElement dropdown = container.ElementAt(0);
|
||||
dropdown.style.marginLeft = 5;
|
||||
|
||||
Label titleLabel = new Label(title);
|
||||
titleLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
titleLabel.style.marginLeft = 6;
|
||||
titleLabel.style.unityTextAlign = TextAnchor.UpperLeft;
|
||||
titleLabel.style.paddingTop = 0;
|
||||
if (iconTex != null)
|
||||
{
|
||||
Image icon = new Image();
|
||||
icon.image = iconTex;
|
||||
icon.style.height = 16;
|
||||
icon.style.width = 16;
|
||||
icon.style.minWidth = 16;
|
||||
icon.style.minHeight = 16;
|
||||
icon.style.maxWidth = 16;
|
||||
icon.style.maxHeight = 16;
|
||||
icon.style.marginRight = 0;
|
||||
icon.style.marginLeft = 0;
|
||||
icon.style.marginTop = 0;
|
||||
icon.style.marginBottom = 0;
|
||||
// icon.style.ba
|
||||
//icon.style.scale = new Vector2(1.1f, 1.1f);
|
||||
container.Add(icon);
|
||||
}
|
||||
if (headerToggle == null)
|
||||
{
|
||||
headerToggle = new Toggle();
|
||||
headerToggle.style.visibility = Visibility.Hidden;
|
||||
}
|
||||
headerToggle.style.marginLeft = 6;
|
||||
headerToggle.style.marginRight = 0;
|
||||
headerToggle.style.marginBottom = 1;
|
||||
container.Add(headerToggle);
|
||||
container.Add(titleLabel);
|
||||
f.contentContainer.AddToClassList("headerContent");
|
||||
}
|
||||
|
||||
// Gets the shader property index corresponding to each element of a material property array
|
||||
public static int[] GetMaterialPropertyShaderIdx(MaterialProperty[] materialProperties, Shader shader)
|
||||
{
|
||||
int numMatProps = materialProperties.Length;
|
||||
int[] propertyIdx = new int[numMatProps];
|
||||
for (int i = 0; i < numMatProps; i++)
|
||||
{
|
||||
propertyIdx[i] = shader.FindPropertyIndex(materialProperties[i].name);
|
||||
}
|
||||
return propertyIdx;
|
||||
}
|
||||
|
||||
public static int[] GetShaderIdxToMaterialProp(MaterialProperty[] materialProperties, Shader shader)
|
||||
{
|
||||
int numMatProps = materialProperties.Length;
|
||||
int[] propertyIdx = new int[shader.GetPropertyCount()];
|
||||
for (int i = 0; i < numMatProps; i++)
|
||||
{
|
||||
//propertyIdx[shader.FindPropertyIndex(materialProperties[i].name)] = i;
|
||||
propertyIdx[i] = i;
|
||||
}
|
||||
return propertyIdx;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Strip out unused texture references in materials to avoid unity bundling/loading them
|
||||
/// </summary>
|
||||
/// <param name="targets">target objects, assumed to all be materials</param>
|
||||
/// <param name="materialProperties">Array of material properties retrieved from MaterialEditor.GetMaterialProperties</param>
|
||||
/// <param name="propertyIdx">map from each element of materialProperties to the index of its shader property</param>
|
||||
/// <param name="shader">Shader used by all the target materials</param>
|
||||
public static void SanitizeMaterials(Object[] targets, MaterialProperty[] materialProperties, int[] propertyIdx, Shader shader)
|
||||
{
|
||||
int numMatProps = materialProperties.Length;
|
||||
|
||||
HashSet<string> validTextureNames = new HashSet<string>();
|
||||
|
||||
for (int i = 0; i < numMatProps; i++)
|
||||
{
|
||||
ShaderPropertyType type = shader.GetPropertyType(propertyIdx[i]);
|
||||
switch (type)
|
||||
{
|
||||
case ShaderPropertyType.Texture:
|
||||
validTextureNames.Add(materialProperties[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int numMats = targets.Length;
|
||||
for (int mat = 0; mat < numMats; mat++)
|
||||
{
|
||||
SerializedObject smat = new SerializedObject(targets[mat]);
|
||||
SerializedProperty texEnv = smat.FindProperty("m_SavedProperties.m_TexEnvs");
|
||||
bool removedProp = false;
|
||||
string removedPropNames = "\n ";
|
||||
if (texEnv != null)
|
||||
{
|
||||
int numTex = texEnv.arraySize;
|
||||
for (int tIdx = numTex - 1; tIdx >= 0; tIdx--)
|
||||
{
|
||||
SerializedProperty nameProp = smat.FindProperty("m_SavedProperties.m_TexEnvs.Array.data[" + tIdx.ToString() + "].first");
|
||||
string name = nameProp.stringValue;
|
||||
if (!validTextureNames.Contains(name))
|
||||
{
|
||||
texEnv.DeleteArrayElementAtIndex(tIdx);
|
||||
removedPropNames += name + "\n ";
|
||||
removedProp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removedProp)
|
||||
{
|
||||
Debug.LogWarning("LitMAS GUI: Removed the following unused texture properties from " + targets[mat].name + removedPropNames);
|
||||
smat.ApplyModifiedProperties();
|
||||
}
|
||||
smat.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, Texture2D> icon16px = new Dictionary<string, Texture2D>();
|
||||
public static Texture2D GetClosestUnityIconMip(string textureName, int iconHeightInPts)
|
||||
{
|
||||
int closestPow2Res = (int)math.round(math.log2(iconHeightInPts * EditorGUIUtility.pixelsPerPoint));
|
||||
int iconRes = 1 << closestPow2Res;
|
||||
string key = textureName + "X" + iconRes.ToString();
|
||||
|
||||
if (icon16px.ContainsKey(key))
|
||||
{
|
||||
Texture2D storedIcon = icon16px[key];
|
||||
if (storedIcon != null)
|
||||
{
|
||||
return icon16px[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
icon16px.Remove(key);
|
||||
}
|
||||
}
|
||||
GUIContent imguiIcon = EditorGUIUtility.IconContent(textureName);
|
||||
if (imguiIcon == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Texture2D icon = imguiIcon.image as Texture2D;
|
||||
|
||||
if (icon == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (icon.width < (iconRes + (iconRes / 2)))
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
int numMips = icon.mipmapCount;
|
||||
int desiredMip = numMips - (closestPow2Res + 1);
|
||||
if (desiredMip < 1)
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
Texture2D tex = new Texture2D(
|
||||
Mathf.Max(icon.width >> desiredMip, 1),
|
||||
Mathf.Max(icon.height >> desiredMip, 1),
|
||||
icon.graphicsFormat,
|
||||
TextureCreationFlags.MipChain);
|
||||
tex.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
|
||||
tex.name = textureName;
|
||||
int currentMip = 0;
|
||||
NativeArray<byte> iconData = new NativeArray<byte>((int)GraphicsFormatUtility.ComputeMipmapSize(tex.width, tex.height, tex.graphicsFormat), Allocator.Persistent);
|
||||
while (desiredMip < numMips && currentMip < tex.mipmapCount)
|
||||
{
|
||||
NativeArray<byte> texData = tex.GetPixelData<byte>(currentMip);
|
||||
AsyncGPUReadbackRequest request = AsyncGPUReadback.RequestIntoNativeArray<byte>(ref iconData, icon, desiredMip);
|
||||
request.WaitForCompletion();
|
||||
NativeArray<byte>.Copy(iconData, texData, texData.Length);
|
||||
currentMip++;
|
||||
desiredMip++;
|
||||
texData.Dispose();
|
||||
}
|
||||
iconData.Dispose();
|
||||
tex.Apply(false, true);
|
||||
icon16px.Add(key, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
||||
static Action<VisualElement, int> s_IncrementVersion;
|
||||
public static void UpdateVisualElement(VisualElement v)
|
||||
{
|
||||
if (s_IncrementVersion == null)
|
||||
{
|
||||
MethodInfo mi = typeof(VisualElement).GetMethod("IncrementVersion", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
s_IncrementVersion = (Action<VisualElement, int>) mi.CreateDelegate(typeof(Action<VisualElement, int>));
|
||||
}
|
||||
s_IncrementVersion.Invoke(v, 8 | 2048);
|
||||
}
|
||||
|
||||
static MethodInfo getTracker;
|
||||
static PropertyInfo s_PropertyViewer;
|
||||
|
||||
static void ReflectEditorTracker()
|
||||
{
|
||||
s_PropertyViewer = typeof(Editor).GetProperty("propertyViewer", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (s_PropertyViewer == null) Debug.Log("NULL Property Viewer field");
|
||||
Type viewerInterface = s_PropertyViewer.PropertyType;
|
||||
if (viewerInterface == null) Debug.Log("NULL Property Viewer type");
|
||||
getTracker = viewerInterface.GetProperty("tracker", BindingFlags.Public | BindingFlags.Instance).GetGetMethod();
|
||||
}
|
||||
|
||||
public static void ForceRebuild(Editor e)
|
||||
{
|
||||
if (s_PropertyViewer == null)
|
||||
{
|
||||
ReflectEditorTracker();
|
||||
}
|
||||
object propertyViewer = s_PropertyViewer.GetValue(e);
|
||||
|
||||
if (propertyViewer != null)
|
||||
{
|
||||
var map = propertyViewer.GetType().GetInterfaceMap(getTracker.DeclaringType);
|
||||
int index = Array.IndexOf(map.InterfaceMethods, getTracker);
|
||||
if (index < 0) return;
|
||||
object tracker = map.InterfaceMethods[index].Invoke(propertyViewer, null);
|
||||
ActiveEditorTracker activeEditorTracker = (ActiveEditorTracker) tracker;
|
||||
//activeEditorTracker.ForceRebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47d498d37cb59c84a8f57a8004475463
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using UnityEditor.Rendering.Universal.ShaderGUI;
|
||||
using UnityEngine;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
// Used for ShaderGraph Lit shaders
|
||||
class ShaderGraphLitGUI : BaseShaderGUI
|
||||
{
|
||||
public MaterialProperty workflowMode;
|
||||
|
||||
MaterialProperty[] properties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// save off the list of all properties for shadergraph
|
||||
this.properties = properties;
|
||||
|
||||
var material = materialEditor?.target as Material;
|
||||
if (material == null)
|
||||
return;
|
||||
|
||||
base.FindProperties(properties);
|
||||
workflowMode = BaseShaderGUI.FindProperty(Property.SpecularWorkflowMode, properties, false);
|
||||
}
|
||||
|
||||
public static void UpdateMaterial(Material material, MaterialUpdateType updateType)
|
||||
{
|
||||
// newly created materials should initialize the globalIlluminationFlags (default is off)
|
||||
if (updateType == MaterialUpdateType.CreatedNewMaterial)
|
||||
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
|
||||
|
||||
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
|
||||
BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
|
||||
LitGUI.SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkflow);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
UpdateMaterial(material, MaterialUpdateType.ModifiedMaterial);
|
||||
}
|
||||
|
||||
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
|
||||
if (workflowMode != null)
|
||||
DoPopup(LitGUI.Styles.workflowModeText, workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawShaderGraphProperties(material, properties);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Always show the queue control field. Only show the render queue field if queue control is set to user override
|
||||
DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
|
||||
if (material.HasProperty(Property.QueueControl) && material.GetFloat(Property.QueueControl) == (float)QueueControl.UserOverride)
|
||||
materialEditor.RenderQueueField();
|
||||
base.DrawAdvancedOptions(material);
|
||||
|
||||
// ignore emission color for shadergraphs, because shadergraphs don't have a hard-coded emission property, it's up to the user
|
||||
materialEditor.DoubleSidedGIField();
|
||||
materialEditor.LightmapEmissionFlagsProperty(0, enabled: true, ignoreEmissionColor: true);
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1efcaa82db5b5604b861d10e36958714
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
// Used for ShaderGraph Unlit shaders
|
||||
class ShaderGraphUnlitGUI : BaseShaderGUI
|
||||
{
|
||||
MaterialProperty[] properties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// save off the list of all properties for shadergraph
|
||||
this.properties = properties;
|
||||
|
||||
base.FindProperties(properties);
|
||||
}
|
||||
|
||||
public static void UpdateMaterial(Material material, MaterialUpdateType updateType)
|
||||
{
|
||||
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
|
||||
BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
UpdateMaterial(material, MaterialUpdateType.ModifiedMaterial);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawShaderGraphProperties(material, properties);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
// Always show the queue control field. Only show the render queue field if queue control is set to user override
|
||||
DoPopup(Styles.queueControl, queueControlProp, Styles.queueControlNames);
|
||||
if (material.HasProperty(Property.QueueControl) && material.GetFloat(Property.QueueControl) == (float)QueueControl.UserOverride)
|
||||
materialEditor.RenderQueueField();
|
||||
base.DrawAdvancedOptions(material);
|
||||
materialEditor.DoubleSidedGIField();
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5b95b9b576115ac4bbf3b1ea150ab3c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 44979452441cd45d5a88ff530647528f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class BakedLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private BakedLitGUI.BakedLitProperties shadingModelProperties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new BakedLitGUI.BakedLitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
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;
|
||||
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
BakedLitGUI.Inputs(shadingModelProperties, materialEditor);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
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("_Blend", (float)blendMode);
|
||||
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
else
|
||||
{
|
||||
material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8176ef27c50d1485084b4ab6f1554353
|
||||
timeCreated: 1504689095
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class LitShader : BaseShaderGUI
|
||||
{
|
||||
static readonly string[] workflowModeNames = Enum.GetNames(typeof(LitGUI.WorkflowMode));
|
||||
|
||||
private LitGUI.LitProperties litProperties;
|
||||
private LitDetailGUI.LitProperties litDetailProperties;
|
||||
|
||||
public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
|
||||
{
|
||||
materialScopesList.RegisterHeaderScope(LitDetailGUI.Styles.detailInputs, Expandable.Details, _ => LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor));
|
||||
}
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
litProperties = new LitGUI.LitProperties(properties);
|
||||
litDetailProperties = new LitDetailGUI.LitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, LitDetailGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
if (litProperties.workflowMode != null)
|
||||
DoPopup(LitGUI.Styles.workflowModeText, litProperties.workflowMode, workflowModeNames);
|
||||
|
||||
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)
|
||||
{
|
||||
materialEditor.ShaderProperty(litProperties.highlights, LitGUI.Styles.highlightsText);
|
||||
materialEditor.ShaderProperty(litProperties.reflections, LitGUI.Styles.reflectionsText);
|
||||
}
|
||||
|
||||
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("_Blend", (float)blendMode);
|
||||
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
else
|
||||
{
|
||||
material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a72ab9c46e7987c40bcd48bcf9e7c0dd
|
||||
timeCreated: 1504689095
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private LitGUI.LitProperties litProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
litProperties = new LitGUI.LitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
LitGUI.Inputs(litProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial, true);
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9818dc043dbe84466a71ed6178bbffda
|
||||
timeCreated: 1509367878
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesSimpleLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private SimpleLitGUI.SimpleLitProperties shadingModelProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new SimpleLitGUI.SimpleLitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
SimpleLitGUI.Inputs(shadingModelProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
SimpleLitGUI.Advanced(shadingModelProperties);
|
||||
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial, true);
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d80ff2d19402463c8a2a52558deaf43
|
||||
timeCreated: 1509367878
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesUnlitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private BakedLitGUI.BakedLitProperties shadingModelProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new BakedLitGUI.BakedLitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
SetMaterialKeywords(material, null, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
BakedLitGUI.Inputs(shadingModelProperties, materialEditor);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial);
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 84e6c97ce450449128b4f193da9c0263
|
||||
timeCreated: 1509367878
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class SimpleLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private SimpleLitGUI.SimpleLitProperties shadingModelProperties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new SimpleLitGUI.SimpleLitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
SimpleLitGUI.Inputs(shadingModelProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
SimpleLitGUI.Advanced(shadingModelProperties);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b31b6386794884dfbb8513e510144b19
|
||||
timeCreated: 1504689095
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class UnlitShader : BaseShaderGUI
|
||||
{
|
||||
// material changed check
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
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;
|
||||
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
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("_Blend", (float)blendMode);
|
||||
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
else
|
||||
{
|
||||
material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8ed8ed178d5584da0874d4c69e3624a9
|
||||
timeCreated: 1504689095
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a22c22fb536604167866c59ce9a780d2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
public static class BakedLitGUI
|
||||
{
|
||||
public struct BakedLitProperties
|
||||
{
|
||||
// Surface Input Props
|
||||
public MaterialProperty bumpMapProp;
|
||||
|
||||
public BakedLitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Input Props
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(BakedLitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 795fde47942374005bbe56e3879983db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class LitDetailGUI
|
||||
{
|
||||
public static class Styles
|
||||
{
|
||||
public static readonly GUIContent detailInputs = EditorGUIUtility.TrTextContent("Detail Inputs",
|
||||
"These settings define the surface details by tiling and overlaying additional maps on the surface.");
|
||||
|
||||
public static readonly GUIContent detailMaskText = EditorGUIUtility.TrTextContent("Mask",
|
||||
"Select a mask for the Detail map. The mask uses the alpha channel of the selected texture. The Tiling and Offset settings have no effect on the mask.");
|
||||
|
||||
public static readonly GUIContent detailAlbedoMapText = EditorGUIUtility.TrTextContent("Detail Map",
|
||||
"(R) Desaturated albedo, (G) Normal Y, (B) Smoothness, (A) Normal X.");
|
||||
// "Select the surface detail texture.The alpha of your texture determines surface hue and intensity.");
|
||||
|
||||
public static readonly GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent("Normal Map",
|
||||
"Designates a Normal Map to create the illusion of bumps and dents in the details of this Material's surface.");
|
||||
|
||||
//public static readonly GUIContent detailAlbedoMapScaleInfo = EditorGUIUtility.TrTextContent("Setting the scaling factor to a value other than 1 results in a less performant shader variant.");
|
||||
}
|
||||
|
||||
public struct LitProperties
|
||||
{
|
||||
// public MaterialProperty detailMask;
|
||||
public MaterialProperty detailMap;
|
||||
//public MaterialProperty detailAlbedoMapScale;
|
||||
//public MaterialProperty detailAlbedoMap;
|
||||
public MaterialProperty detailNormalMapScale;
|
||||
public MaterialProperty detailSmoothnessMapScale;
|
||||
//public MaterialProperty detailNormalMap;
|
||||
|
||||
public LitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// detailMask = BaseShaderGUI.FindProperty("_DetailMask", properties, false);
|
||||
detailMap = BaseShaderGUI.FindProperty("_DetailMap", properties, false);
|
||||
//detailAlbedoMapScale = BaseShaderGUI.FindProperty("_DetailAlbedoMapScale", properties, false);
|
||||
// detailAlbedoMap = BaseShaderGUI.FindProperty("_DetailAlbedoMap", properties, false);
|
||||
detailNormalMapScale = BaseShaderGUI.FindProperty("_DetailNormalMapScale", properties, false);
|
||||
detailSmoothnessMapScale = BaseShaderGUI.FindProperty("_DetailSmoothnessMapScale", properties, false);
|
||||
// detailNormalMap = BaseShaderGUI.FindProperty("_DetailNormalMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
// materialEditor.TexturePropertySingleLine(Styles.detailMaskText, properties.detailMask);
|
||||
materialEditor.TexturePropertySingleLine(Styles.detailAlbedoMapText, properties.detailMap);
|
||||
//,properties.detailMap.textureValue != null ? properties.detailAlbedoMapScale : null);
|
||||
// if (properties.detailAlbedoMapScale.floatValue != 1.0f)
|
||||
// {
|
||||
// EditorGUILayout.HelpBox(Styles.detailAlbedoMapScaleInfo.text, MessageType.Info, true);
|
||||
// }
|
||||
if (properties.detailMap.textureValue != null)
|
||||
{
|
||||
// materialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, properties.detailNormalMap,
|
||||
// properties.detailNormalMap.textureValue != null ? properties.detailNormalMapScale : null);
|
||||
materialEditor.RangeProperty(properties.detailNormalMapScale, "Bump Scale");
|
||||
materialEditor.RangeProperty(properties.detailSmoothnessMapScale, "Smoothness Scale");
|
||||
materialEditor.TextureScaleOffsetProperty(properties.detailMap);
|
||||
// materialEditor.TextureScaleOffsetProperty(properties.detailAlbedoMap);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
if (material.HasProperty("_DetailMap") )//&& material.HasProperty("_DetailAlbedoMapScale"))
|
||||
{
|
||||
bool isScaled = false;//material.GetFloat("_DetailAlbedoMapScale") != 1.0f;
|
||||
bool hasDetailMap = material.GetTexture("_DetailMap");
|
||||
CoreUtils.SetKeyword(material, "_DETAIL_MULX2", !isScaled && hasDetailMap);
|
||||
if (hasDetailMap) CoreUtils.SetKeyword(material, "_NORMALMAP", true); //Forcing on normalmap to avoid a darkening bug with mixed directional lights :/
|
||||
// CoreUtils.SetKeyword(material, "_DETAIL_SCALED", isScaled && hasDetailMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7645809b8de779942be231eecf635c5b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
public static class LitGUI
|
||||
{
|
||||
public enum WorkflowMode
|
||||
{
|
||||
Specular = 0,
|
||||
Metallic
|
||||
}
|
||||
|
||||
public enum SmoothnessMapChannel
|
||||
{
|
||||
SpecularMetallicAlpha,
|
||||
AlbedoAlpha,
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent workflowModeText = EditorGUIUtility.TrTextContent("Workflow Mode",
|
||||
"Select a workflow that fits your textures. Choose between Metallic or Specular.");
|
||||
|
||||
public static GUIContent specularMapText =
|
||||
EditorGUIUtility.TrTextContent("Specular Map", "Designates a Specular Map and specular color determining the apperance of reflections on this Material's surface.");
|
||||
|
||||
public static GUIContent metallicMapText =
|
||||
EditorGUIUtility.TrTextContent("Mask Map", "Metallic (R), AO (G), Detail Mask (B), Smoothness (A)"); //Using HDRP's packing to free up some texture channels
|
||||
|
||||
public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent("Smoothness",
|
||||
"Controls the spread of highlights and reflections on the surface.");
|
||||
|
||||
public static GUIContent smoothnessMapChannelText =
|
||||
EditorGUIUtility.TrTextContent("Source",
|
||||
"Specifies where to sample a smoothness map from. By default, uses the alpha channel for your map.");
|
||||
|
||||
public static GUIContent highlightsText = EditorGUIUtility.TrTextContent("Specular Highlights",
|
||||
"When enabled, the Material reflects the shine from direct lighting.");
|
||||
|
||||
public static GUIContent reflectionsText =
|
||||
EditorGUIUtility.TrTextContent("Environment Reflections",
|
||||
"When enabled, the Material samples reflections from the nearest Reflection Probes or Lighting Probe.");
|
||||
|
||||
public static GUIContent heightMapText = EditorGUIUtility.TrTextContent("Height Map",
|
||||
"Defines a Height Map that will drive a parallax effect in the shader making the surface seem displaced.");
|
||||
|
||||
public static GUIContent occlusionText = EditorGUIUtility.TrTextContent("Occlusion Map",
|
||||
"Sets an occlusion map to simulate shadowing from ambient lighting (G).");
|
||||
|
||||
public static readonly string[] metallicSmoothnessChannelNames = { "Metallic Alpha", "Albedo Alpha" };
|
||||
public static readonly string[] specularSmoothnessChannelNames = { "Specular Alpha", "Albedo Alpha" };
|
||||
|
||||
public static GUIContent clearCoatText = EditorGUIUtility.TrTextContent("Clear Coat",
|
||||
"A multi-layer material feature which simulates a thin layer of coating on top of the surface material." +
|
||||
"\nPerformance cost is considerable as the specular component is evaluated twice, once per layer.");
|
||||
|
||||
public static GUIContent clearCoatMaskText = EditorGUIUtility.TrTextContent("Mask",
|
||||
"Specifies the amount of the coat blending." +
|
||||
"\nActs as a multiplier of the clear coat map mask value or as a direct mask value if no map is specified." +
|
||||
"\nThe map specifies clear coat mask in the red channel and clear coat smoothness in the green channel.");
|
||||
|
||||
public static GUIContent clearCoatSmoothnessText = EditorGUIUtility.TrTextContent("Smoothness",
|
||||
"Specifies the smoothness of the coating." +
|
||||
"\nActs as a multiplier of the clear coat map smoothness value or as a direct smoothness value if no map is specified.");
|
||||
}
|
||||
|
||||
public struct LitProperties
|
||||
{
|
||||
// Surface Option Props
|
||||
public MaterialProperty workflowMode;
|
||||
|
||||
// Surface Input Props
|
||||
public MaterialProperty metallic;
|
||||
public MaterialProperty specColor;
|
||||
public MaterialProperty metallicGlossMap;
|
||||
public MaterialProperty specGlossMap;
|
||||
public MaterialProperty smoothness;
|
||||
public MaterialProperty smoothnessMapChannel;
|
||||
public MaterialProperty bumpMapProp;
|
||||
public MaterialProperty bumpScaleProp;
|
||||
public MaterialProperty parallaxMapProp;
|
||||
public MaterialProperty parallaxScaleProp;
|
||||
public MaterialProperty occlusionStrength;
|
||||
public MaterialProperty occlusionMap;
|
||||
|
||||
// Advanced Props
|
||||
public MaterialProperty highlights;
|
||||
public MaterialProperty reflections;
|
||||
|
||||
public MaterialProperty clearCoat; // Enable/Disable dummy property
|
||||
public MaterialProperty clearCoatMap;
|
||||
public MaterialProperty clearCoatMask;
|
||||
public MaterialProperty clearCoatSmoothness;
|
||||
|
||||
public LitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Option Props
|
||||
workflowMode = BaseShaderGUI.FindProperty("_WorkflowMode", properties, false);
|
||||
// Surface Input Props
|
||||
metallic = BaseShaderGUI.FindProperty("_Metallic", properties);
|
||||
specColor = BaseShaderGUI.FindProperty("_SpecColor", properties, false);
|
||||
metallicGlossMap = BaseShaderGUI.FindProperty("_MetallicGlossMap", properties);
|
||||
specGlossMap = BaseShaderGUI.FindProperty("_SpecGlossMap", properties, false);
|
||||
smoothness = BaseShaderGUI.FindProperty("_Smoothness", properties, false);
|
||||
smoothnessMapChannel = BaseShaderGUI.FindProperty("_SmoothnessTextureChannel", properties, false);
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
bumpScaleProp = BaseShaderGUI.FindProperty("_BumpScale", properties, false);
|
||||
parallaxMapProp = BaseShaderGUI.FindProperty("_ParallaxMap", properties, false);
|
||||
parallaxScaleProp = BaseShaderGUI.FindProperty("_Parallax", properties, false);
|
||||
occlusionStrength = BaseShaderGUI.FindProperty("_OcclusionStrength", properties, false);
|
||||
occlusionMap = BaseShaderGUI.FindProperty("_OcclusionMap", properties, false);
|
||||
// Advanced Props
|
||||
highlights = BaseShaderGUI.FindProperty("_SpecularHighlights", properties, false);
|
||||
reflections = BaseShaderGUI.FindProperty("_EnvironmentReflections", properties, false);
|
||||
|
||||
clearCoat = BaseShaderGUI.FindProperty("_ClearCoat", properties, false);
|
||||
clearCoatMap = BaseShaderGUI.FindProperty("_ClearCoatMap", properties, false);
|
||||
clearCoatMask = BaseShaderGUI.FindProperty("_ClearCoatMask", properties, false);
|
||||
clearCoatSmoothness = BaseShaderGUI.FindProperty("_ClearCoatSmoothness", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
DoMetallicSpecularArea(properties, materialEditor, material);
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp, properties.bumpScaleProp);
|
||||
|
||||
if (HeightmapAvailable(material))
|
||||
DoHeightmapArea(properties, materialEditor);
|
||||
|
||||
if (properties.occlusionMap != null)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.occlusionText, properties.occlusionMap,
|
||||
properties.occlusionMap.textureValue != null ? properties.occlusionStrength : null);
|
||||
}
|
||||
|
||||
// Check that we have all the required properties for clear coat,
|
||||
// otherwise we will get null ref exception from MaterialEditor GUI helpers.
|
||||
if (ClearCoatAvailable(material))
|
||||
DoClearCoat(properties, materialEditor, material);
|
||||
}
|
||||
|
||||
private static bool ClearCoatAvailable(Material material)
|
||||
{
|
||||
return material.HasProperty("_ClearCoat")
|
||||
&& material.HasProperty("_ClearCoatMap")
|
||||
&& material.HasProperty("_ClearCoatMask")
|
||||
&& material.HasProperty("_ClearCoatSmoothness");
|
||||
}
|
||||
|
||||
private static bool HeightmapAvailable(Material material)
|
||||
{
|
||||
return material.HasProperty("_Parallax")
|
||||
&& material.HasProperty("_ParallaxMap");
|
||||
}
|
||||
|
||||
private static void DoHeightmapArea(LitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.heightMapText, properties.parallaxMapProp,
|
||||
properties.parallaxMapProp.textureValue != null ? properties.parallaxScaleProp : null);
|
||||
}
|
||||
|
||||
private static bool ClearCoatEnabled(Material material)
|
||||
{
|
||||
return material.HasProperty("_ClearCoat") && material.GetFloat("_ClearCoat") > 0.0;
|
||||
}
|
||||
|
||||
public static void DoClearCoat(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
materialEditor.ShaderProperty(properties.clearCoat, Styles.clearCoatText);
|
||||
var coatEnabled = material.GetFloat("_ClearCoat") > 0.0;
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!coatEnabled);
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.clearCoatMaskText, properties.clearCoatMap, properties.clearCoatMask);
|
||||
|
||||
EditorGUI.indentLevel += 2;
|
||||
|
||||
// Texture and HDR color controls
|
||||
materialEditor.ShaderProperty(properties.clearCoatSmoothness, Styles.clearCoatSmoothnessText);
|
||||
|
||||
EditorGUI.indentLevel -= 2;
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
public static void DoMetallicSpecularArea(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
string[] smoothnessChannelNames;
|
||||
bool hasGlossMap = false;
|
||||
if (properties.workflowMode == null ||
|
||||
(WorkflowMode)properties.workflowMode.floatValue == WorkflowMode.Metallic)
|
||||
{
|
||||
hasGlossMap = properties.metallicGlossMap.textureValue != null;
|
||||
smoothnessChannelNames = Styles.metallicSmoothnessChannelNames;
|
||||
materialEditor.TexturePropertySingleLine(Styles.metallicMapText, properties.metallicGlossMap,
|
||||
hasGlossMap ? null : properties.metallic);
|
||||
}
|
||||
else
|
||||
{
|
||||
hasGlossMap = properties.specGlossMap.textureValue != null;
|
||||
smoothnessChannelNames = Styles.specularSmoothnessChannelNames;
|
||||
BaseShaderGUI.TextureColorProps(materialEditor, Styles.specularMapText, properties.specGlossMap,
|
||||
hasGlossMap ? null : properties.specColor);
|
||||
}
|
||||
DoSmoothness(materialEditor, material, properties.smoothness, properties.smoothnessMapChannel, smoothnessChannelNames);
|
||||
}
|
||||
|
||||
internal static bool IsOpaque(Material material)
|
||||
{
|
||||
bool opaque = true;
|
||||
if (material.HasProperty(Property.SurfaceType))
|
||||
opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat(Property.SurfaceType) == BaseShaderGUI.SurfaceType.Opaque);
|
||||
return opaque;
|
||||
}
|
||||
|
||||
public static void DoSmoothness(MaterialEditor materialEditor, Material material, MaterialProperty smoothness, MaterialProperty smoothnessMapChannel, string[] smoothnessChannelNames)
|
||||
{
|
||||
EditorGUI.indentLevel += 2;
|
||||
|
||||
materialEditor.ShaderProperty(smoothness, Styles.smoothnessText);
|
||||
|
||||
if (smoothnessMapChannel != null) // smoothness channel
|
||||
{
|
||||
var opaque = IsOpaque(material);
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.showMixedValue = smoothnessMapChannel.hasMixedValue;
|
||||
if (opaque)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var smoothnessSource = (int)smoothnessMapChannel.floatValue;
|
||||
smoothnessSource = EditorGUILayout.Popup(Styles.smoothnessMapChannelText, smoothnessSource, smoothnessChannelNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
smoothnessMapChannel.floatValue = smoothnessSource;
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.Popup(Styles.smoothnessMapChannelText, 0, smoothnessChannelNames);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUI.indentLevel -= 2;
|
||||
}
|
||||
|
||||
public static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
|
||||
{
|
||||
int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
|
||||
if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
|
||||
return SmoothnessMapChannel.AlbedoAlpha;
|
||||
|
||||
return SmoothnessMapChannel.SpecularMetallicAlpha;
|
||||
}
|
||||
|
||||
// (shared by all lit shaders, including shadergraph Lit Target and Lit.shader)
|
||||
internal static void SetupSpecularWorkflowKeyword(Material material, out bool isSpecularWorkflow)
|
||||
{
|
||||
isSpecularWorkflow = false; // default is metallic workflow
|
||||
if (material.HasProperty(Property.SpecularWorkflowMode))
|
||||
isSpecularWorkflow = ((WorkflowMode)material.GetFloat(Property.SpecularWorkflowMode)) == WorkflowMode.Specular;
|
||||
CoreUtils.SetKeyword(material, "_SPECULAR_SETUP", isSpecularWorkflow);
|
||||
}
|
||||
|
||||
// setup keywords for Lit.shader
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkFlow);
|
||||
|
||||
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
|
||||
// (MaterialProperty value might come from renderer material property block)
|
||||
var specularGlossMap = isSpecularWorkFlow ? "_SpecGlossMap" : "_MetallicGlossMap";
|
||||
var hasGlossMap = material.GetTexture(specularGlossMap) != null;
|
||||
|
||||
CoreUtils.SetKeyword(material, "_METALLICSPECGLOSSMAP", hasGlossMap);
|
||||
|
||||
//if (material.HasProperty("_SpecularHighlights"))
|
||||
// CoreUtils.SetKeyword(material, "_SPECULARHIGHLIGHTS_OFF",
|
||||
// material.GetFloat("_SpecularHighlights") == 0.0f);
|
||||
//if (material.HasProperty("_EnvironmentReflections"))
|
||||
// CoreUtils.SetKeyword(material, "_ENVIRONMENTREFLECTIONS_OFF",
|
||||
// material.GetFloat("_EnvironmentReflections") == 0.0f);
|
||||
//if (material.HasProperty("_OcclusionMap"))
|
||||
// CoreUtils.SetKeyword(material, "_OCCLUSIONMAP", material.GetTexture("_OcclusionMap"));
|
||||
|
||||
if (material.HasProperty("_ParallaxMap"))
|
||||
CoreUtils.SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
|
||||
|
||||
if (material.HasProperty("_SmoothnessTextureChannel"))
|
||||
{
|
||||
var opaque = IsOpaque(material);
|
||||
CoreUtils.SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A",
|
||||
GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha && opaque);
|
||||
}
|
||||
|
||||
// Clear coat keywords are independent to remove possiblity of invalid combinations.
|
||||
if (ClearCoatEnabled(material))
|
||||
{
|
||||
var hasMap = material.HasProperty("_ClearCoatMap") && material.GetTexture("_ClearCoatMap") != null;
|
||||
if (hasMap)
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", true);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b33851187d4324530b9f7abfe14d0137
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Scripting.APIUpdating;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
public static class SimpleLitGUI
|
||||
{
|
||||
public enum SpecularSource
|
||||
{
|
||||
SpecularTextureAndColor,
|
||||
NoSpecular
|
||||
}
|
||||
|
||||
public enum SmoothnessMapChannel
|
||||
{
|
||||
SpecularAlpha,
|
||||
AlbedoAlpha,
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent specularMapText =
|
||||
EditorGUIUtility.TrTextContent("Specular Map", "Designates a Specular Map and specular color determining the apperance of reflections on this Material's surface.");
|
||||
}
|
||||
|
||||
public struct SimpleLitProperties
|
||||
{
|
||||
// Surface Input Props
|
||||
public MaterialProperty specColor;
|
||||
public MaterialProperty specGlossMap;
|
||||
public MaterialProperty specHighlights;
|
||||
public MaterialProperty smoothnessMapChannel;
|
||||
public MaterialProperty smoothness;
|
||||
public MaterialProperty bumpMapProp;
|
||||
|
||||
public SimpleLitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Input Props
|
||||
specColor = BaseShaderGUI.FindProperty("_SpecColor", properties);
|
||||
specGlossMap = BaseShaderGUI.FindProperty("_SpecGlossMap", properties, false);
|
||||
specHighlights = BaseShaderGUI.FindProperty("_SpecularHighlights", properties, false);
|
||||
smoothnessMapChannel = BaseShaderGUI.FindProperty("_SmoothnessSource", properties, false);
|
||||
smoothness = BaseShaderGUI.FindProperty("_Smoothness", properties, false);
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(SimpleLitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
DoSpecularArea(properties, materialEditor, material);
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp);
|
||||
}
|
||||
|
||||
public static void Advanced(SimpleLitProperties properties)
|
||||
{
|
||||
//SpecularSource specularSource = (SpecularSource)properties.specHighlights.floatValue;
|
||||
//EditorGUI.BeginChangeCheck();
|
||||
//EditorGUI.showMixedValue = properties.specHighlights.hasMixedValue;
|
||||
//bool enabled = EditorGUILayout.Toggle(LitGUI.Styles.highlightsText, specularSource == SpecularSource.SpecularTextureAndColor);
|
||||
//if (EditorGUI.EndChangeCheck())
|
||||
// properties.specHighlights.floatValue = enabled ? (float)SpecularSource.SpecularTextureAndColor : (float)SpecularSource.NoSpecular;
|
||||
//EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public static void DoSpecularArea(SimpleLitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
//SpecularSource specSource = (SpecularSource)properties.specHighlights.floatValue;
|
||||
//EditorGUI.BeginDisabledGroup(specSource == SpecularSource.NoSpecular);
|
||||
BaseShaderGUI.TextureColorProps(materialEditor, Styles.specularMapText, properties.specGlossMap, properties.specColor, true);
|
||||
LitGUI.DoSmoothness(materialEditor, material, properties.smoothness, properties.smoothnessMapChannel, LitGUI.Styles.specularSmoothnessChannelNames);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
UpdateMaterialSpecularSource(material);
|
||||
}
|
||||
|
||||
private static void UpdateMaterialSpecularSource(Material material)
|
||||
{
|
||||
var opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat("_Surface") ==
|
||||
BaseShaderGUI.SurfaceType.Opaque);
|
||||
//SpecularSource specSource = (SpecularSource)material.GetFloat("_SpecularHighlights");
|
||||
//if (specSource == SpecularSource.NoSpecular)
|
||||
//{
|
||||
// CoreUtils.SetKeyword(material, "_SPECGLOSSMAP", false);
|
||||
// CoreUtils.SetKeyword(material, "_SPECULAR_COLOR", false);
|
||||
// CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", false);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
//var smoothnessSource = (SmoothnessMapChannel)material.GetFloat("_SmoothnessSource");
|
||||
bool hasMap = material.GetTexture("_SpecGlossMap");
|
||||
CoreUtils.SetKeyword(material, "_SPECGLOSSMAP", hasMap);
|
||||
CoreUtils.SetKeyword(material, "_SPECULAR_COLOR", !hasMap);
|
||||
// if (opaque)
|
||||
// CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", smoothnessSource == SmoothnessMapChannel.AlbedoAlpha);
|
||||
// else
|
||||
// CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", false);
|
||||
|
||||
string color;
|
||||
// if (smoothnessSource != SmoothnessMapChannel.AlbedoAlpha || !opaque)
|
||||
color = "_SpecColor";
|
||||
//else
|
||||
// color = "_BaseColor";
|
||||
|
||||
var col = material.GetColor(color);
|
||||
float smoothness = material.GetFloat("_Smoothness");
|
||||
if (smoothness != col.a)
|
||||
{
|
||||
col.a = smoothness;
|
||||
material.SetColor(color, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5f2b965a0132c42a4b52332918ed154a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 05b7540662f400d4aadac0c9efc5161b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
.headerTogglebar {
|
||||
height: var(--unity-metrics-single_line_large-height);
|
||||
background-color: var(--unity-colors-inspector_titlebar-background);
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.headerContent {
|
||||
border-top-color: var(--unity-colors-inspector_titlebar-border_accent);
|
||||
border-top-width: 1px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.headerRoot {
|
||||
border-bottom-color: var(--unity-colors-inspector_titlebar-border);
|
||||
border-bottom-width: 1px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.textureFieldThumb {
|
||||
border-bottom-color: var(--unity-colors-button-border_accent);
|
||||
border-bottom-width: 1px;
|
||||
border-top-color: var(--unity-colors-button-border_accent);
|
||||
border-top-width: 1px;
|
||||
border-left-color: var(--unity-colors-button-border_accent);
|
||||
border-left-width: 1px;
|
||||
border-right-color: var(--unity-colors-button-border_accent);
|
||||
border-right-width: 1px;
|
||||
min-width: 26px;
|
||||
min-height: 26px;
|
||||
max-width: 26px;
|
||||
max-height: 26px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.textureFieldThumbOld {
|
||||
border-bottom-width: 0px;
|
||||
border-top-width: 0px;
|
||||
border-left-width: 0px;
|
||||
border-right-width: 0px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.materialGUILeftBox
|
||||
{
|
||||
flex-basis: 40%;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0.4;
|
||||
flex-grow: 0.4;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.materialGUIRightBox
|
||||
{
|
||||
flex-basis: 60%;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0.6;
|
||||
flex-grow: 0.6;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23abfcaed80d7fa4e899c53d2b3a1a39
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal
|
||||
{
|
||||
internal class TerrainLitShaderGUI : UnityEditor.ShaderGUI, ITerrainLayerCustomUI
|
||||
{
|
||||
private class StylesLayer
|
||||
{
|
||||
public readonly GUIContent warningHeightBasedBlending = new GUIContent("Height-based blending is disabled if you have more than four TerrainLayer materials!");
|
||||
|
||||
public readonly GUIContent enableHeightBlend = new GUIContent("Enable Height-based Blend", "Blend terrain layers based on height values.");
|
||||
public readonly GUIContent heightTransition = new GUIContent("Height Transition", "Size in world units of the smooth transition between layers.");
|
||||
public readonly GUIContent enableInstancedPerPixelNormal = new GUIContent("Enable Per-pixel Normal", "Enable per-pixel normal when the terrain uses instanced rendering.");
|
||||
|
||||
public readonly GUIContent diffuseTexture = new GUIContent("Diffuse");
|
||||
public readonly GUIContent colorTint = new GUIContent("Color Tint");
|
||||
public readonly GUIContent opacityAsDensity = new GUIContent("Opacity as Density", "Enable Density Blend (if unchecked, opacity is used as Smoothness)");
|
||||
public readonly GUIContent normalMapTexture = new GUIContent("Normal Map");
|
||||
public readonly GUIContent normalScale = new GUIContent("Normal Scale");
|
||||
public readonly GUIContent maskMapTexture = new GUIContent("Mask", "R: Metallic\nG: AO\nB: Height\nA: Smoothness");
|
||||
public readonly GUIContent maskMapTextureWithoutHeight = new GUIContent("Mask Map", "R: Metallic\nG: AO\nA: Smoothness");
|
||||
public readonly GUIContent channelRemapping = new GUIContent("Channel Remapping");
|
||||
public readonly GUIContent defaultValues = new GUIContent("Channel Default Values");
|
||||
public readonly GUIContent metallic = new GUIContent("R: Metallic");
|
||||
public readonly GUIContent ao = new GUIContent("G: AO");
|
||||
public readonly GUIContent height = new GUIContent("B: Height");
|
||||
public readonly GUIContent heightParametrization = new GUIContent("Parametrization");
|
||||
public readonly GUIContent heightAmplitude = new GUIContent("Amplitude (cm)");
|
||||
public readonly GUIContent heightBase = new GUIContent("Base (cm)");
|
||||
public readonly GUIContent heightMin = new GUIContent("Min (cm)");
|
||||
public readonly GUIContent heightMax = new GUIContent("Max (cm)");
|
||||
public readonly GUIContent heightCm = new GUIContent("B: Height (cm)");
|
||||
public readonly GUIContent smoothness = new GUIContent("A: Smoothness");
|
||||
}
|
||||
|
||||
static StylesLayer s_Styles = null;
|
||||
private static StylesLayer styles { get { if (s_Styles == null) s_Styles = new StylesLayer(); return s_Styles; } }
|
||||
|
||||
public TerrainLitShaderGUI()
|
||||
{
|
||||
}
|
||||
|
||||
// Height blend params
|
||||
MaterialProperty enableHeightBlend = null;
|
||||
const string kEnableHeightBlend = "_EnableHeightBlend";
|
||||
|
||||
MaterialProperty heightTransition = null;
|
||||
const string kHeightTransition = "_HeightTransition";
|
||||
|
||||
// Per-pixel Normal (while instancing)
|
||||
MaterialProperty enableInstancedPerPixelNormal = null;
|
||||
const string kEnableInstancedPerPixelNormal = "_EnableInstancedPerPixelNormal";
|
||||
|
||||
private bool m_ShowChannelRemapping = false;
|
||||
enum HeightParametrization
|
||||
{
|
||||
Amplitude,
|
||||
MinMax
|
||||
};
|
||||
private HeightParametrization m_HeightParametrization = HeightParametrization.Amplitude;
|
||||
|
||||
private static bool DoesTerrainUseMaskMaps(TerrainLayer[] terrainLayers)
|
||||
{
|
||||
for (int i = 0; i < terrainLayers.Length; ++i)
|
||||
{
|
||||
if (terrainLayers[i].maskMapTexture != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void FindMaterialProperties(MaterialProperty[] props)
|
||||
{
|
||||
enableHeightBlend = FindProperty(kEnableHeightBlend, props, false);
|
||||
heightTransition = FindProperty(kHeightTransition, props, false);
|
||||
enableInstancedPerPixelNormal = FindProperty(kEnableInstancedPerPixelNormal, props, false);
|
||||
}
|
||||
|
||||
static public void SetupMaterialKeywords(Material material)
|
||||
{
|
||||
bool enableHeightBlend = (material.HasProperty(kEnableHeightBlend) && material.GetFloat(kEnableHeightBlend) > 0);
|
||||
CoreUtils.SetKeyword(material, "_TERRAIN_BLEND_HEIGHT", enableHeightBlend);
|
||||
|
||||
bool enableInstancedPerPixelNormal = material.GetFloat(kEnableInstancedPerPixelNormal) > 0.0f;
|
||||
CoreUtils.SetKeyword(material, "_TERRAIN_INSTANCED_PERPIXEL_NORMAL", enableInstancedPerPixelNormal);
|
||||
}
|
||||
|
||||
static public bool TextureHasAlpha(Texture2D inTex)
|
||||
{
|
||||
if (inTex != null)
|
||||
{
|
||||
return GraphicsFormatUtility.HasAlphaChannel(GraphicsFormatUtility.GetGraphicsFormat(inTex.format, true));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||||
{
|
||||
if (materialEditorIn == null)
|
||||
throw new ArgumentNullException("materialEditorIn");
|
||||
|
||||
FindMaterialProperties(properties);
|
||||
|
||||
bool optionsChanged = false;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
if (enableHeightBlend != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditorIn.ShaderProperty(enableHeightBlend, styles.enableHeightBlend);
|
||||
if (enableHeightBlend.floatValue > 0)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.HelpBox(styles.warningHeightBasedBlending.text, MessageType.Info);
|
||||
materialEditorIn.ShaderProperty(heightTransition, styles.heightTransition);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
optionsChanged = true;
|
||||
}
|
||||
|
||||
bool enablePerPixelNormalChanged = false;
|
||||
|
||||
// Since Instanced Per-pixel normal is actually dependent on instancing enabled or not, it is not
|
||||
// important to check it in the GUI. The shader will make sure it is enabled/disabled properly.s
|
||||
if (enableInstancedPerPixelNormal != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
materialEditorIn.ShaderProperty(enableInstancedPerPixelNormal, styles.enableInstancedPerPixelNormal);
|
||||
enablePerPixelNormalChanged = EditorGUI.EndChangeCheck();
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
if (optionsChanged || enablePerPixelNormalChanged)
|
||||
{
|
||||
foreach (var obj in materialEditorIn.targets)
|
||||
{
|
||||
SetupMaterialKeywords((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
// We should always do this call at the end
|
||||
materialEditorIn.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
bool ITerrainLayerCustomUI.OnTerrainLayerGUI(TerrainLayer terrainLayer, Terrain terrain)
|
||||
{
|
||||
var terrainLayers = terrain.terrainData.terrainLayers;
|
||||
|
||||
// Don't use the member field enableHeightBlend as ShaderGUI.OnGUI might not be called if the material UI is folded.
|
||||
// heightblend shouldn't be available if we are in multi-pass mode, because it is guaranteed to be broken.
|
||||
bool heightBlendAvailable = (terrainLayers.Length <= 4);
|
||||
bool heightBlend = heightBlendAvailable && terrain.materialTemplate.HasProperty(kEnableHeightBlend) && (terrain.materialTemplate.GetFloat(kEnableHeightBlend) > 0);
|
||||
|
||||
terrainLayer.diffuseTexture = EditorGUILayout.ObjectField(styles.diffuseTexture, terrainLayer.diffuseTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateDiffuseTextureUI(terrainLayer.diffuseTexture);
|
||||
|
||||
var diffuseRemapMin = terrainLayer.diffuseRemapMin;
|
||||
var diffuseRemapMax = terrainLayer.diffuseRemapMax;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
bool enableDensity = false;
|
||||
if (terrainLayer.diffuseTexture != null)
|
||||
{
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
rect.y += 16 + 4;
|
||||
rect.width = EditorGUIUtility.labelWidth + 64;
|
||||
rect.height = 16;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
|
||||
var diffuseTint = new Color(diffuseRemapMax.x, diffuseRemapMax.y, diffuseRemapMax.z);
|
||||
diffuseTint = EditorGUI.ColorField(rect, styles.colorTint, diffuseTint, true, false, false);
|
||||
diffuseRemapMax.x = diffuseTint.r;
|
||||
diffuseRemapMax.y = diffuseTint.g;
|
||||
diffuseRemapMax.z = diffuseTint.b;
|
||||
diffuseRemapMin.x = diffuseRemapMin.y = diffuseRemapMin.z = 0;
|
||||
|
||||
if (!heightBlend)
|
||||
{
|
||||
rect.y = rect.yMax + 2;
|
||||
enableDensity = EditorGUI.Toggle(rect, styles.opacityAsDensity, diffuseRemapMin.w > 0);
|
||||
}
|
||||
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
diffuseRemapMax.w = 1;
|
||||
diffuseRemapMin.w = enableDensity ? 1 : 0;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
terrainLayer.diffuseRemapMin = diffuseRemapMin;
|
||||
terrainLayer.diffuseRemapMax = diffuseRemapMax;
|
||||
}
|
||||
|
||||
// Display normal map UI
|
||||
terrainLayer.normalMapTexture = EditorGUILayout.ObjectField(styles.normalMapTexture, terrainLayer.normalMapTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateNormalMapTextureUI(terrainLayer.normalMapTexture, TerrainLayerUtility.CheckNormalMapTextureType(terrainLayer.normalMapTexture));
|
||||
|
||||
if (terrainLayer.normalMapTexture != null)
|
||||
{
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
rect.y += 16 + 4;
|
||||
rect.width = EditorGUIUtility.labelWidth + 64;
|
||||
rect.height = 16;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
terrainLayer.normalScale = EditorGUI.FloatField(rect, styles.normalScale, terrainLayer.normalScale);
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
|
||||
// Display the mask map UI and the remap controls
|
||||
terrainLayer.maskMapTexture = EditorGUILayout.ObjectField(heightBlend ? styles.maskMapTexture : styles.maskMapTextureWithoutHeight, terrainLayer.maskMapTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateMaskMapTextureUI(terrainLayer.maskMapTexture);
|
||||
|
||||
var maskMapRemapMin = terrainLayer.maskMapRemapMin;
|
||||
var maskMapRemapMax = terrainLayer.maskMapRemapMax;
|
||||
var smoothness = terrainLayer.smoothness;
|
||||
var metallic = terrainLayer.metallic;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
m_ShowChannelRemapping = EditorGUILayout.Foldout(m_ShowChannelRemapping, terrainLayer.maskMapTexture != null ? s_Styles.channelRemapping : s_Styles.defaultValues);
|
||||
|
||||
if (m_ShowChannelRemapping)
|
||||
{
|
||||
if (terrainLayer.maskMapTexture != null)
|
||||
{
|
||||
float min, max;
|
||||
min = maskMapRemapMin.x; max = maskMapRemapMax.x;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.metallic, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.x = min; maskMapRemapMax.x = max;
|
||||
|
||||
min = maskMapRemapMin.y; max = maskMapRemapMax.y;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.ao, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.y = min; maskMapRemapMax.y = max;
|
||||
|
||||
if (heightBlend)
|
||||
{
|
||||
EditorGUILayout.LabelField(styles.height);
|
||||
++EditorGUI.indentLevel;
|
||||
m_HeightParametrization = (HeightParametrization)EditorGUILayout.EnumPopup(styles.heightParametrization, m_HeightParametrization);
|
||||
if (m_HeightParametrization == HeightParametrization.Amplitude)
|
||||
{
|
||||
// (height - heightBase) * amplitude
|
||||
float amplitude = Mathf.Max(maskMapRemapMax.z - maskMapRemapMin.z, Mathf.Epsilon); // to avoid divide by zero
|
||||
float heightBase = maskMapRemapMin.z / amplitude;
|
||||
amplitude = EditorGUILayout.FloatField(styles.heightAmplitude, amplitude * 100) / 100;
|
||||
heightBase = EditorGUILayout.FloatField(styles.heightBase, heightBase * 100) / 100;
|
||||
maskMapRemapMin.z = heightBase * amplitude;
|
||||
maskMapRemapMax.z = (1.0f - heightBase) * amplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
maskMapRemapMin.z = EditorGUILayout.FloatField(styles.heightMin, maskMapRemapMin.z * 100) / 100;
|
||||
maskMapRemapMax.z = EditorGUILayout.FloatField(styles.heightMax, maskMapRemapMax.z * 100) / 100;
|
||||
}
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
|
||||
min = maskMapRemapMin.w; max = maskMapRemapMax.w;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.smoothness, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.w = min; maskMapRemapMax.w = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
metallic = EditorGUILayout.Slider(s_Styles.metallic, metallic, 0, 1);
|
||||
// AO and Height are still exclusively controlled via the maskRemap controls
|
||||
// metallic and smoothness have their own values as fields within the LayerData.
|
||||
maskMapRemapMax.y = EditorGUILayout.Slider(s_Styles.ao, maskMapRemapMax.y, 0, 1);
|
||||
if (heightBlend)
|
||||
{
|
||||
maskMapRemapMax.z = EditorGUILayout.FloatField(s_Styles.heightCm, maskMapRemapMax.z * 100) / 100;
|
||||
}
|
||||
|
||||
// There's a possibility that someone could slide max below the existing min value
|
||||
// so we'll just protect against that by locking the min value down a little bit.
|
||||
// In the case of height (Z), we are trying to set min to no lower than zero value unless
|
||||
// max goes negative. Zero is a good sensible value for the minimum. For AO (Y), we
|
||||
// don't need this extra protection step because the UI blocks us from going negative
|
||||
// anyway. In both cases, pushing the slider below the min value will lock them together,
|
||||
// but min will be "left behind" if you go back up.
|
||||
maskMapRemapMin.y = Mathf.Min(maskMapRemapMin.y, maskMapRemapMax.y);
|
||||
maskMapRemapMin.z = Mathf.Min(Mathf.Max(0, maskMapRemapMin.z), maskMapRemapMax.z);
|
||||
|
||||
if (TextureHasAlpha(terrainLayer.diffuseTexture))
|
||||
{
|
||||
GUIStyle warnStyle = new GUIStyle(GUI.skin.label);
|
||||
warnStyle.wordWrap = true;
|
||||
GUILayout.Label("Smoothness is controlled by diffuse alpha channel", warnStyle);
|
||||
}
|
||||
else
|
||||
smoothness = EditorGUILayout.Slider(s_Styles.smoothness, smoothness, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
terrainLayer.maskMapRemapMin = maskMapRemapMin;
|
||||
terrainLayer.maskMapRemapMax = maskMapRemapMax;
|
||||
terrainLayer.smoothness = smoothness;
|
||||
terrainLayer.metallic = metallic;
|
||||
}
|
||||
--EditorGUI.indentLevel;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
TerrainLayerUtility.TilingSettingsUI(terrainLayer);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f2216b7cb5772784daf9ad851edda832
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cb896df09ac2a2c4a8b8227a11cdb5c0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public interface BaseMaterialField
|
||||
{
|
||||
public int GetShaderPropIdx();
|
||||
public abstract void UpdateMaterialProperty(MaterialProperty boundProp);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: da9d9cf7353fd9e42b955b549e395b8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class EmissionToggleField : Toggle, BaseMaterialField
|
||||
{
|
||||
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
bool isIntField = false;
|
||||
string keyword;
|
||||
public delegate void BeforeChangeEvent(ChangeEvent<bool> evt);
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx, string keyword, bool isIntField, bool noStyle = false)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.isIntField = isIntField;
|
||||
this.keyword = keyword;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
bool state = false;
|
||||
if (isIntField)
|
||||
{
|
||||
state = materialProperty.intValue != 0 ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = materialProperty.floatValue > 0 ? true : false;
|
||||
}
|
||||
|
||||
this.SetValueWithoutNotify(state);
|
||||
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
|
||||
if (!noStyle)
|
||||
{
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<bool> evt)
|
||||
{
|
||||
|
||||
if (isIntField)
|
||||
{
|
||||
materialProperty.intValue = evt.newValue ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
materialProperty.floatValue = evt.newValue ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
Object[] targets = materialProperty.targets;
|
||||
int numMats = targets.Length;
|
||||
// Setting the value through the materialProperty already recorded an undo, append to that
|
||||
Undo.RecordObjects(targets, Undo.GetCurrentGroupName());
|
||||
|
||||
SetKeywordOnTargets(evt.newValue);
|
||||
SetGIFlagsOnTargets(evt.newValue);
|
||||
|
||||
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
|
||||
Undo.IncrementCurrentGroup();
|
||||
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
|
||||
void SetKeywordOnTargets(bool value)
|
||||
{
|
||||
|
||||
if (keyword != null)
|
||||
{
|
||||
Object[] materials = materialProperty.targets;
|
||||
int numMaterials = materials.Length;
|
||||
Shader s = (materials[0] as Material).shader;
|
||||
LocalKeyword kw = new LocalKeyword(s, keyword);
|
||||
for (int i = 0; i < numMaterials; i++)
|
||||
{
|
||||
(materials[0] as Material).SetKeyword(kw, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetGIFlagsOnTargets(bool state)
|
||||
{
|
||||
|
||||
Object[] materials = materialProperty.targets;
|
||||
int numMaterials = materials.Length;
|
||||
|
||||
for (int i = 0; i < numMaterials; i++)
|
||||
{
|
||||
(materials[0] as Material).globalIlluminationFlags = state ? MaterialGlobalIlluminationFlags.BakedEmissive : MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
}
|
||||
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
bool state = false;
|
||||
if (isIntField)
|
||||
{
|
||||
state = materialProperty.intValue != 0 ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = materialProperty.floatValue > 0 ? true : false;
|
||||
}
|
||||
if (value != state)
|
||||
{
|
||||
this.SetValueWithoutNotify(state);
|
||||
}
|
||||
this.showMixedValue = materialProperty.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 08421d46ab7f7614eadd68e4e7aca77c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using static UnityEngine.Rendering.DebugUI.MessageBox;
|
||||
|
||||
namespace UnityEditor.UIElements
|
||||
{
|
||||
public class GIFlagsPopup : PopupField<int>
|
||||
{
|
||||
|
||||
static Dictionary<int, string> flagLabels = new Dictionary<int, string>()
|
||||
{
|
||||
{0, "None" },
|
||||
{1, "Realtime" },
|
||||
{2, "Baked" },
|
||||
};
|
||||
|
||||
public GIFlagsPopup(SerializedObject serializedMaterial)
|
||||
{
|
||||
|
||||
List<int> flags = new List<int>() { 0, 1, 2 };
|
||||
this.choices = flags;
|
||||
this.index = 2;
|
||||
this.formatSelectedValueCallback = GetCurrentFlagName;
|
||||
this.formatListItemCallback = GetValidFlagName;
|
||||
|
||||
|
||||
|
||||
this.bindingPath = "m_LightmapFlags";
|
||||
this.label = "Global Illumination";
|
||||
VisualElement label = ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement dropdown = ElementAt(1);
|
||||
dropdown.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
style.marginRight = 3;
|
||||
}
|
||||
|
||||
static string GetCurrentFlagName(int flag)
|
||||
{
|
||||
string label;
|
||||
if (flagLabels.TryGetValue(flag, out label))
|
||||
{
|
||||
return label;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
static string GetValidFlagName(int flag)
|
||||
{
|
||||
return flagLabels[flag];
|
||||
}
|
||||
|
||||
class RenderQueueIntField : IntegerField
|
||||
{
|
||||
public int defaultQueue = 2000;
|
||||
protected override string ValueToString(int v)
|
||||
{
|
||||
if (v == -1)
|
||||
{
|
||||
return defaultQueue.ToString();
|
||||
}
|
||||
return v.ToString(base.formatString, CultureInfo.InvariantCulture.NumberFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6a738a0b3f474af46bd9cf980c7b0627
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SLZMaterialUI;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialColorField : ColorField, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx, bool isPartOfTexField)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify(materialProperty.colorValue);
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
if (isPartOfTexField)
|
||||
{
|
||||
style.alignSelf = Align.Center;
|
||||
style.flexGrow = 1;
|
||||
style.flexShrink = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<Color> evt)
|
||||
{
|
||||
materialProperty.colorValue = evt.newValue;
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
if (value != boundProp.colorValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.colorValue);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b97e041999f2d4a43ad1f83584415ce1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialDummyField : INotifyValueChanged<float>, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
float m_value;
|
||||
public float value
|
||||
{
|
||||
get { return m_value; }
|
||||
set {
|
||||
if (m_value != value)
|
||||
{
|
||||
m_value = value;
|
||||
materialProperty.floatValue = m_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MaterialDummyField(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
SetValueWithoutNotify(materialProperty.floatValue);
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.floatValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.floatValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValueWithoutNotify(float value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a5fccb07f24f1146b93d089e493e007
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialEmissionFlagsField : VisualElement
|
||||
{
|
||||
|
||||
|
||||
static EnumFieldUtils.EnumData s_EmissionFlags;
|
||||
|
||||
static EnumFieldUtils.EnumData emissionFlags
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_EmissionFlags == null)
|
||||
{
|
||||
s_EmissionFlags = new EnumFieldUtils.EnumData()
|
||||
{
|
||||
values = new Enum[] { MaterialGlobalIlluminationFlags.EmissiveIsBlack, MaterialGlobalIlluminationFlags.RealtimeEmissive, MaterialGlobalIlluminationFlags.BakedEmissive },
|
||||
flagValues = new int[] { 0, 1, 2 },
|
||||
displayNames = new string[] { "None", "Realtime", "Baked" },
|
||||
names = new string[] { "EmissiveIsBlack", "RealtimeEmissive", "BakedEmissive" },
|
||||
tooltip = new string[] { "Emission will not emit light during light baking", "Emission will be treated as a real-time source when baking realtime GI", "Emission will emit light when baking lighting" },
|
||||
flags = true,
|
||||
underlyingType = typeof(MaterialGlobalIlluminationFlags),
|
||||
unsigned = false,
|
||||
serializable = true,
|
||||
};
|
||||
}
|
||||
return s_EmissionFlags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static object s_BoxedEnumData;
|
||||
static object boxedEnumData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_BoxedEnumData == null)
|
||||
{
|
||||
s_BoxedEnumData = EnumFieldUtils.GetBoxedEnumData(emissionFlags);
|
||||
}
|
||||
return s_BoxedEnumData;
|
||||
}
|
||||
}
|
||||
|
||||
static Action<EnumField, Enum> s_UpdateValueLabelAction;
|
||||
static Action<EnumField, Enum> UpdateValueLabelAction
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_UpdateValueLabelAction == null)
|
||||
{
|
||||
MethodInfo updateValueInfo = typeof(EnumField).GetMethod("UpdateValueLabel", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
s_UpdateValueLabelAction = (Action<EnumField, Enum>) updateValueInfo.CreateDelegate(typeof(Action<EnumField, Enum>));
|
||||
}
|
||||
return s_UpdateValueLabelAction;
|
||||
}
|
||||
}
|
||||
|
||||
public EnumField internalField;
|
||||
public MaterialEmissionFlagsField(string label, MaterialGlobalIlluminationFlags defaultValue)
|
||||
{
|
||||
internalField = new EnumField(label, defaultValue);
|
||||
SetEnumData(internalField);
|
||||
EnumFieldUtils.UpdateValueLabelAction(internalField, defaultValue);
|
||||
VisualElement labelElement = internalField.ElementAt(0);
|
||||
labelElement.AddToClassList("materialGUILeftBox");
|
||||
labelElement.style.overflow = Overflow.Hidden;
|
||||
labelElement.style.minWidth = 0;
|
||||
VisualElement dropdownElement = internalField.ElementAt(1);
|
||||
dropdownElement.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
Add(internalField);
|
||||
|
||||
}
|
||||
|
||||
public void SetEnumData(EnumField field)
|
||||
{
|
||||
EnumFieldUtils.enumDataField.SetValue(field, boxedEnumData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d6b65ddfa2dcdb459c9ebc448986435
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialFloatField : FloatField, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify(materialProperty.floatValue);
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<float> evt)
|
||||
{
|
||||
materialProperty.floatValue = evt.newValue;
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.floatValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.floatValue);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d3da44cdff624d4ebb0c6b43ad59f8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialIntField : IntegerField, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify(materialProperty.intValue);
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<int> evt)
|
||||
{
|
||||
materialProperty.intValue = evt.newValue;
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.intValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.intValue);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7fa327141ed044147b9a2efea174b00c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialIntPopup : PopupField<int>, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
Dictionary<int, string> choiceLabels;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx, List<int> choices, Dictionary<int, string> choiceLabels)
|
||||
{
|
||||
|
||||
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
|
||||
this.choices = choices;
|
||||
this.choiceLabels = choiceLabels;
|
||||
|
||||
this.formatSelectedValueCallback = GetCurrentFlagName;
|
||||
this.formatListItemCallback = GetValidFlagName;
|
||||
|
||||
VisualElement label = ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement dropdown = ElementAt(1);
|
||||
dropdown.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
style.marginRight = 3;
|
||||
|
||||
RegisterCallback<ChangeEvent<int>>(evt =>
|
||||
{
|
||||
materialProperty.floatValue = (float)evt.newValue;
|
||||
}
|
||||
);
|
||||
|
||||
this.SetValueWithoutNotify((int)materialProperty.floatValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
int newVal = (int)boundProp.floatValue;
|
||||
if (this.value != newVal)
|
||||
{
|
||||
this.SetValueWithoutNotify(newVal);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
|
||||
string GetCurrentFlagName(int type)
|
||||
{
|
||||
string label;
|
||||
if (choiceLabels.TryGetValue(type, out label))
|
||||
{
|
||||
return label;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
string GetValidFlagName(int type)
|
||||
{
|
||||
return choiceLabels[type];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2a265e5d4ddf6f44c9f8c719875f1428
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialIntRangeField : SliderInt, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify((int)materialProperty.floatValue);
|
||||
this.lowValue = (int)materialProperty.rangeLimits.x;
|
||||
this.highValue = (int)materialProperty.rangeLimits.y;
|
||||
this.showInputField = true;
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<int> evt)
|
||||
{
|
||||
materialProperty.floatValue = evt.newValue; // Int ranges are still floats...
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.floatValue)
|
||||
{
|
||||
this.SetValueWithoutNotify((int)boundProp.floatValue);
|
||||
this.lowValue = (int)boundProp.rangeLimits.x;
|
||||
this.highValue = (int)boundProp.rangeLimits.y;
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d75b03261072c5d458af914c4ed8d432
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialRangeField : Slider, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify(materialProperty.floatValue);
|
||||
this.lowValue = materialProperty.rangeLimits.x;
|
||||
this.highValue = materialProperty.rangeLimits.y;
|
||||
this.showInputField = true;
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<float> evt)
|
||||
{
|
||||
materialProperty.floatValue = evt.newValue;
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.floatValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.floatValue);
|
||||
this.lowValue = boundProp.rangeLimits.x;
|
||||
this.highValue = boundProp.rangeLimits.y;
|
||||
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8774bd78aca1ca1438a7328c4e7691a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SLZMaterialUI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialScaleOffsetField : VisualElement, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
Vector2Field tilingField;
|
||||
Vector2Field offsetField;
|
||||
public Vector4 value;
|
||||
public MaterialScaleOffsetField(MaterialProperty boundProp, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = boundProp;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
value = boundProp.textureScaleAndOffset;
|
||||
tilingField = new Vector2Field();
|
||||
tilingField.style.marginRight = 4;
|
||||
tilingField.label = "Tiling";
|
||||
VisualElement tilingLabel = tilingField.ElementAt(0);
|
||||
VisualElement tilingInput = tilingField.ElementAt(1);
|
||||
tilingInput.RemoveAt(2);
|
||||
tilingLabel.AddToClassList("materialGUILeftBox");
|
||||
tilingInput.AddToClassList("materialGUIRightBox");
|
||||
tilingField.SetValueWithoutNotify(new Vector2(value.x, value.y));
|
||||
tilingField.RegisterValueChangedCallback(OnChangedEventTiling);
|
||||
|
||||
offsetField = new Vector2Field();
|
||||
offsetField.style.marginRight = 4;
|
||||
offsetField.label = "Offset";
|
||||
VisualElement offsetLabel = offsetField.ElementAt(0);
|
||||
VisualElement offsetInput = offsetField.ElementAt(1);
|
||||
|
||||
offsetInput.RemoveAt(2);
|
||||
offsetLabel.AddToClassList("materialGUILeftBox");
|
||||
offsetInput.AddToClassList("materialGUIRightBox");
|
||||
offsetField.SetValueWithoutNotify(new Vector2(value.z, value.w));
|
||||
offsetField.RegisterValueChangedCallback(OnChangedEventOffset);
|
||||
|
||||
Add(tilingField);
|
||||
Add(offsetField);
|
||||
}
|
||||
|
||||
public void OnChangedEventTiling(ChangeEvent<Vector2> evt)
|
||||
{
|
||||
Vector4 scaleOffset = new Vector4(evt.newValue.x, evt.newValue.y, value.z, value.w);
|
||||
value = scaleOffset;
|
||||
materialProperty.textureScaleAndOffset = scaleOffset;
|
||||
tilingField.showMixedValue = false;
|
||||
}
|
||||
|
||||
public void OnChangedEventOffset(ChangeEvent<Vector2> evt)
|
||||
{
|
||||
Vector4 scaleOffset = new Vector4(value.x, value.y, evt.newValue.x, evt.newValue.y);
|
||||
value = scaleOffset;
|
||||
materialProperty.textureScaleAndOffset = scaleOffset;
|
||||
tilingField.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (value != boundProp.textureScaleAndOffset)
|
||||
{
|
||||
value = boundProp.textureScaleAndOffset;
|
||||
Vector2 scale = new Vector2(value.x, value.y);
|
||||
Vector2 offset = new Vector2(value.z, value.w);
|
||||
tilingField.SetValueWithoutNotify(scale);
|
||||
offsetField.SetValueWithoutNotify(offset);
|
||||
|
||||
}
|
||||
tilingField.showMixedValue = materialProperty.hasMixedValue;
|
||||
offsetField.showMixedValue = materialProperty.hasMixedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2f7b4173acb2fca4999ffa4a8b1ad615
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialToggleField : Toggle, BaseMaterialField
|
||||
{
|
||||
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
bool isIntField = false;
|
||||
string keyword;
|
||||
public delegate void BeforeChangeEvent(ChangeEvent<bool> evt);
|
||||
//public BeforeChangeEvent BeforeChange;
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx, string keyword, bool isIntField, bool noStyle = false)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.isIntField = isIntField;
|
||||
this.keyword = keyword;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
bool state = false;
|
||||
if (isIntField)
|
||||
{
|
||||
state = materialProperty.intValue != 0 ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = materialProperty.floatValue > 0 ? true : false;
|
||||
}
|
||||
|
||||
this.SetValueWithoutNotify(state);
|
||||
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
|
||||
if (!noStyle)
|
||||
{
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<bool> evt)
|
||||
{
|
||||
//BeforeChange.Invoke(evt);
|
||||
if (isIntField)
|
||||
{
|
||||
materialProperty.intValue = evt.newValue ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
materialProperty.floatValue = evt.newValue ? 1 : 0;
|
||||
}
|
||||
|
||||
if (keyword != null)
|
||||
{
|
||||
Object[] targets = materialProperty.targets;
|
||||
int numMats = targets.Length;
|
||||
// Setting the value through the materialProperty already recorded an undo, append to that
|
||||
Undo.RecordObjects(targets, Undo.GetCurrentGroupName());
|
||||
}
|
||||
SetKeywordOnTargets(evt.newValue);
|
||||
if (keyword != null)
|
||||
{
|
||||
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
|
||||
Undo.IncrementCurrentGroup();
|
||||
}
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
|
||||
void SetKeywordOnTargets(bool value)
|
||||
{
|
||||
|
||||
if (keyword != null)
|
||||
{
|
||||
Object[] materials = materialProperty.targets;
|
||||
int numMaterials = materials.Length;
|
||||
Shader s = (materials[0] as Material).shader;
|
||||
LocalKeyword kw = new LocalKeyword(s, keyword);
|
||||
for (int i = 0; i < numMaterials; i++)
|
||||
{
|
||||
(materials[0] as Material).SetKeyword(kw, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
bool state = false;
|
||||
if (isIntField)
|
||||
{
|
||||
state = materialProperty.intValue != 0 ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = materialProperty.floatValue > 0 ? true : false;
|
||||
}
|
||||
if (this.value != state)
|
||||
{
|
||||
this.SetValueWithoutNotify(state);
|
||||
|
||||
}
|
||||
this.showMixedValue = materialProperty.hasMixedValue;
|
||||
//MarkDirtyRepaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fbe8648b2f113f641a3c1a49f43dcfcd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class MaterialVectorField : Vector4Field, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx)
|
||||
{
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.RegisterValueChangedCallback(OnChangedEvent);
|
||||
this.SetValueWithoutNotify(materialProperty.vectorValue);
|
||||
style.marginRight = 3;
|
||||
if (materialProperty.hasMixedValue)
|
||||
{
|
||||
//this.SetValueWithoutNotify(Color.gray);
|
||||
this.showMixedValue = true;
|
||||
}
|
||||
label = materialProperty.displayName;
|
||||
SetFullLineStyle();
|
||||
}
|
||||
public void SetFullLineStyle()
|
||||
{
|
||||
VisualElement label = this.ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement color = this.ElementAt(1);
|
||||
color.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
}
|
||||
public void OnChangedEvent(ChangeEvent<Vector4> evt)
|
||||
{
|
||||
materialProperty.vectorValue = evt.newValue;
|
||||
this.showMixedValue = false;
|
||||
}
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
if (this.value != boundProp.vectorValue)
|
||||
{
|
||||
this.SetValueWithoutNotify(boundProp.vectorValue);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
//MarkDirtyRepaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ba3f18a26aea39a48851c4f24b173f72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace UnityEditor.UIElements
|
||||
{
|
||||
public class RenderQueueDropdown : VisualElement, INotifyValueChanged<int>
|
||||
{
|
||||
public PopupField<int> renderQueuePresets;
|
||||
RenderQueueIntField renderQueueCustom;
|
||||
int m_value;
|
||||
public int value
|
||||
{
|
||||
get { return m_value; }
|
||||
set {
|
||||
if (value == defaultRenderQueue)
|
||||
SetValue(-1);
|
||||
else
|
||||
SetValue(value);
|
||||
}
|
||||
}
|
||||
int defaultRenderQueue;
|
||||
Dictionary<int, string> queueLabels = new Dictionary<int, string>()
|
||||
{
|
||||
{-1, " From Shader " },
|
||||
{1000, " Background " },
|
||||
{2000, " Geometry " },
|
||||
{2450, " Alpha Test " },
|
||||
{3000, " Transparent " }
|
||||
};
|
||||
|
||||
public RenderQueueDropdown(SerializedObject serializedMaterial, Shader shader)
|
||||
{
|
||||
this.style.flexDirection = FlexDirection.Row;
|
||||
//this.style.
|
||||
this.style.alignSelf = Align.Stretch;
|
||||
this.style.alignItems = Align.Stretch;
|
||||
this.style.flexWrap = Wrap.NoWrap;
|
||||
this.style.justifyContent = Justify.SpaceBetween;
|
||||
|
||||
this.defaultRenderQueue = shader.renderQueue;
|
||||
this.AddToClassList("unity-base-field");
|
||||
List<int> queues = new List<int>() { -1, 1000, 2000, 2450, 3000 };
|
||||
|
||||
//SerializedProperty renderQueueProp = serializedMaterial.FindProperty("m_CustomRenderQueue");
|
||||
|
||||
renderQueuePresets = new PopupField<int>(queues, -1, GetCurrentQueueName, GetValidQueueName);
|
||||
//renderQueuePresets.style.minWidth = 9 * 12;
|
||||
renderQueuePresets.bindingPath = "m_CustomRenderQueue";
|
||||
//renderQueuePresets.Bind(serializedMaterial);
|
||||
renderQueuePresets.style.width = 100;
|
||||
renderQueueCustom = new RenderQueueIntField();
|
||||
|
||||
renderQueueCustom.defaultQueue = shader.renderQueue;
|
||||
renderQueueCustom.style.width = 48;
|
||||
renderQueueCustom.bindingPath = "m_CustomRenderQueue";
|
||||
//renderQueueCustom.Bind(serializedMaterial);
|
||||
renderQueueCustom.style.unityTextAlign = TextAnchor.MiddleRight;
|
||||
VisualElement renderQueueGroup = new VisualElement();
|
||||
renderQueueGroup.style.flexDirection = FlexDirection.Row;
|
||||
renderQueueGroup.style.flexShrink = 0;
|
||||
renderQueueGroup.style.marginRight = 4;
|
||||
renderQueueGroup.Add(renderQueuePresets);
|
||||
renderQueueGroup.Add(renderQueueCustom);
|
||||
|
||||
Label label = new Label("Render Queue");
|
||||
label.style.alignSelf = Align.Center;
|
||||
label.style.textOverflow = TextOverflow.Ellipsis;
|
||||
label.style.flexShrink = 1;
|
||||
|
||||
Add(label);
|
||||
Add(renderQueueGroup);
|
||||
}
|
||||
|
||||
string GetCurrentQueueName(int queue)
|
||||
{
|
||||
string label;
|
||||
if (queueLabels.TryGetValue(queue, out label))
|
||||
{
|
||||
return label;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Custom";
|
||||
}
|
||||
}
|
||||
|
||||
string GetValidQueueName(int queue)
|
||||
{
|
||||
return queueLabels[queue];
|
||||
}
|
||||
|
||||
class RenderQueueIntField : IntegerField
|
||||
{
|
||||
public int defaultQueue = 2000;
|
||||
protected override string ValueToString(int v)
|
||||
{
|
||||
if (v == -1)
|
||||
{
|
||||
return defaultQueue.ToString();
|
||||
}
|
||||
return v.ToString(base.formatString, CultureInfo.InvariantCulture.NumberFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValue(int value)
|
||||
{
|
||||
if (value == defaultRenderQueue) value = -1;
|
||||
m_value = value;
|
||||
renderQueuePresets.value = value;
|
||||
renderQueueCustom.SetValueWithoutNotify(value);
|
||||
}
|
||||
|
||||
public void SetValueWithoutNotify(int value)
|
||||
{
|
||||
if (value == defaultRenderQueue) value = -1;
|
||||
m_value = value;
|
||||
renderQueuePresets.SetValueWithoutNotify(value);
|
||||
renderQueueCustom.SetValueWithoutNotify(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a93dcfdc27a47f54c8409794026ed59a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class SurfaceTypeField : PopupField<int>, BaseMaterialField
|
||||
{
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
public MaterialProperty materialProperty;
|
||||
MaterialProperty MaterialProperty { get { return materialProperty; } }
|
||||
public INotifyValueChanged<float> blendSrc;
|
||||
public INotifyValueChanged<float> blendDst;
|
||||
public INotifyValueChanged<float> zWrite;
|
||||
public INotifyValueChanged<int> renderQueue;
|
||||
|
||||
|
||||
enum SurfaceTypes
|
||||
{
|
||||
Opaque = 0,
|
||||
Transparent = 1,
|
||||
Fade = 2,
|
||||
}
|
||||
|
||||
static Dictionary<int, string> surfaceLabels = new Dictionary<int, string>()
|
||||
{
|
||||
{0, "Opaque" },
|
||||
{1, "Transparent" },
|
||||
{2, "Fade" },
|
||||
};
|
||||
|
||||
|
||||
static Span<int> SurfaceQueue => new int[] { 2000, 3000, 3000 };
|
||||
static Span<int> SurfaceBlendSrc => new int[] { (int)BlendMode.One, (int)BlendMode.One, (int)BlendMode.SrcAlpha };
|
||||
static Span<int> SurfaceBlendDst => new int[] { (int)BlendMode.Zero, (int)BlendMode.OneMinusSrcAlpha, (int)BlendMode.OneMinusSrcAlpha };
|
||||
static Span<int> SurfaceZWrite => new int[] { 1, 0, 0 };
|
||||
|
||||
public void Initialize(MaterialProperty materialProperty, int shaderPropertyIdx,
|
||||
INotifyValueChanged<float> blendSrc,
|
||||
INotifyValueChanged<float> blendDst,
|
||||
INotifyValueChanged<float> zWrite,
|
||||
INotifyValueChanged<int> queueField)
|
||||
{
|
||||
this.formatSelectedValueCallback = GetCurrentFlagName;
|
||||
this.formatListItemCallback = GetValidFlagName;
|
||||
|
||||
this.materialProperty = materialProperty;
|
||||
this.shaderPropertyIdx = shaderPropertyIdx;
|
||||
this.blendSrc = blendSrc;
|
||||
this.blendDst = blendDst;
|
||||
this.zWrite = zWrite;
|
||||
this.renderQueue = queueField;
|
||||
|
||||
this.label = "Surface Type";
|
||||
this.choices = new List<int>() { 0, 1, 2 };
|
||||
VisualElement label = ElementAt(0);
|
||||
label.AddToClassList("materialGUILeftBox");
|
||||
label.style.overflow = Overflow.Hidden;
|
||||
label.style.minWidth = 0;
|
||||
VisualElement dropdown = ElementAt(1);
|
||||
dropdown.AddToClassList("materialGUIRightBox");
|
||||
style.justifyContent = Justify.FlexStart;
|
||||
style.marginRight = 3;
|
||||
|
||||
RegisterCallback<ChangeEvent<int>>(evt =>
|
||||
{
|
||||
|
||||
int newVal = evt.newValue;
|
||||
Debug.Log("Trying to set surface to " + newVal);
|
||||
UnityEngine.Object[] targets = MaterialProperty.targets;
|
||||
//MaterialProperty.floatValue = newVal;
|
||||
int numTargets = targets.Length;
|
||||
Undo.IncrementCurrentGroup();
|
||||
Undo.RecordObjects(targets, "Set Surface Type");
|
||||
Shader s = ((Material)targets[0]).shader;
|
||||
int surfIdx = s.FindPropertyIndex("_Surface");
|
||||
int blendSrcIdx = s.FindPropertyIndex("_BlendSrc");
|
||||
int blendDstIdx = s.FindPropertyIndex("_BlendDst");
|
||||
int zWriteIdx = s.FindPropertyIndex("_ZWrite");
|
||||
Debug.Log(string.Format("Num Targets: {4}, _Surface: {0}, _BlendSrc:{1}, _BlendDst:{2}, _ZWrite:{3} ", surfIdx, blendSrcIdx, blendDstIdx, zWriteIdx, numTargets));
|
||||
int queue = SurfaceQueue[newVal];
|
||||
queue = queue == s.renderQueue ? -1 : queue;
|
||||
for (int i = 0; i < numTargets; i++)
|
||||
{
|
||||
Material mat = (Material)targets[i];
|
||||
mat.SetFloat("_Surface", newVal);
|
||||
mat.SetFloat("_BlendSrc", SurfaceBlendSrc[newVal]);
|
||||
mat.SetFloat("_BlendDst", SurfaceBlendDst[newVal]);
|
||||
mat.SetFloat("_ZWrite", SurfaceZWrite[newVal]);
|
||||
mat.renderQueue = queue;
|
||||
|
||||
}
|
||||
queueField.SetValueWithoutNotify(SurfaceQueue[newVal]);
|
||||
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
|
||||
|
||||
}
|
||||
);
|
||||
this.SetValueWithoutNotify((int)materialProperty.floatValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
materialProperty = boundProp;
|
||||
int newVal = (int)boundProp.floatValue;
|
||||
if (this.value != newVal)
|
||||
{
|
||||
this.SetValueWithoutNotify(newVal);
|
||||
}
|
||||
this.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
|
||||
static string GetCurrentFlagName(int type)
|
||||
{
|
||||
string label;
|
||||
if (surfaceLabels.TryGetValue(type, out label))
|
||||
{
|
||||
return label;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
static string GetValidFlagName(int type)
|
||||
{
|
||||
return surfaceLabels[type];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6e24e45408716b14ca04c507eff19c04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using static UnityEngine.UI.InputField;
|
||||
using Object = UnityEngine.Object;
|
||||
using System;
|
||||
using SLZ.SLZEditorTools;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public class TextureField : VisualElement, BaseMaterialField
|
||||
{
|
||||
|
||||
public MaterialProperty textureProperty;
|
||||
public VisualElement leftAlignBox { get; private set; }
|
||||
public VisualElement rightAlignBox { get; private set; }
|
||||
|
||||
public string tooltip2 { get { return texObjField.tooltip; } set { texObjField.tooltip = value; } }
|
||||
public Texture defaultTexture;
|
||||
|
||||
public UnityEditor.UIElements.ObjectField texObjField;
|
||||
Texture currentValue;
|
||||
|
||||
Image thumbnail;
|
||||
bool isNormalMap;
|
||||
RenderTexture thumbnailRT;
|
||||
|
||||
UnityEngine.Rendering.TextureDimension textureType;
|
||||
|
||||
public int shaderPropertyIdx;
|
||||
public int GetShaderPropIdx() { return shaderPropertyIdx; }
|
||||
|
||||
static Action<ObjectField> s_updateObjDelegate;
|
||||
static Action<ObjectField> UpdateObjDelegate
|
||||
{
|
||||
get {
|
||||
if (s_updateObjDelegate == null)
|
||||
{
|
||||
MethodInfo m = typeof(UnityEditor.UIElements.ObjectField).GetMethod("UpdateDisplay", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (m == null)
|
||||
{
|
||||
Debug.LogError("Missing UpdateDisplay method");
|
||||
}
|
||||
s_updateObjDelegate = (Action<ObjectField>)m.CreateDelegate(typeof(Action<ObjectField>));
|
||||
}
|
||||
return s_updateObjDelegate;
|
||||
}
|
||||
|
||||
}
|
||||
public TextureField(MaterialProperty textureProperty, int texturePropertyIdx, bool isNormalMap, Texture defaultTexture = null)
|
||||
{
|
||||
this.textureProperty = textureProperty;
|
||||
this.currentValue = textureProperty.textureValue;
|
||||
this.shaderPropertyIdx = texturePropertyIdx;
|
||||
this.isNormalMap = isNormalMap;
|
||||
this.defaultTexture = defaultTexture;
|
||||
RegisterCallback<DetachFromPanelEvent>(evt => Dispose());
|
||||
leftAlignBox = new VisualElement();
|
||||
leftAlignBox.AddToClassList("materialGUILeftBox");
|
||||
rightAlignBox = new VisualElement();
|
||||
rightAlignBox.AddToClassList("materialGUIRightBox");
|
||||
|
||||
|
||||
style.flexDirection = FlexDirection.Row;
|
||||
texObjField = new UnityEditor.UIElements.ObjectField();
|
||||
//List<SearchProvider> providers = new List<SearchProvider>() { new SearchProvider("sfklahlkjhsa", "hello") };
|
||||
//textureField.searchContext = new SearchContext(providers, "t:Texture2D", SearchFlags.Default);
|
||||
//textureField.bindingPath = "m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Texture";
|
||||
textureType = textureProperty.textureDimension;
|
||||
switch (textureProperty.textureDimension)
|
||||
{
|
||||
case (UnityEngine.Rendering.TextureDimension.Tex2D):
|
||||
texObjField.objectType = typeof(Texture2D);
|
||||
break;
|
||||
case (UnityEngine.Rendering.TextureDimension.Tex3D):
|
||||
texObjField.objectType = typeof(Texture3D);
|
||||
break;
|
||||
case (UnityEngine.Rendering.TextureDimension.Tex2DArray):
|
||||
texObjField.objectType = typeof(Texture2DArray);
|
||||
break;
|
||||
case (UnityEngine.Rendering.TextureDimension.Cube):
|
||||
texObjField.objectType = typeof(Cubemap);
|
||||
break;
|
||||
case (UnityEngine.Rendering.TextureDimension.CubeArray):
|
||||
texObjField.objectType = typeof(CubemapArray);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
VisualElement background = texObjField.ElementAt(0);
|
||||
background.style.backgroundColor = StyleKeyword.None;
|
||||
background.style.borderBottomColor = StyleKeyword.None;
|
||||
background.style.borderLeftColor = StyleKeyword.None;
|
||||
background.style.borderRightColor = StyleKeyword.None;
|
||||
background.style.borderTopColor = StyleKeyword.None;
|
||||
|
||||
background.style.borderBottomWidth = StyleKeyword.None;
|
||||
background.style.borderLeftWidth = StyleKeyword.None;
|
||||
background.style.borderRightWidth = StyleKeyword.None;
|
||||
background.style.borderTopWidth = StyleKeyword.None;
|
||||
|
||||
background.style.borderTopLeftRadius = StyleKeyword.None;
|
||||
background.style.borderTopRightRadius = StyleKeyword.None;
|
||||
background.style.borderBottomLeftRadius = StyleKeyword.None;
|
||||
background.style.borderBottomRightRadius = StyleKeyword.None;
|
||||
background.style.justifyContent = Justify.FlexStart;
|
||||
background.style.flexWrap = Wrap.NoWrap;
|
||||
|
||||
background.style.overflow = Overflow.Hidden;
|
||||
VisualElement contents = background.ElementAt(0);
|
||||
contents.style.flexShrink = 0;
|
||||
contents.style.flexGrow = 1;
|
||||
contents.style.overflow = Overflow.Hidden;
|
||||
contents.style.flexBasis = StyleKeyword.Auto;
|
||||
|
||||
VisualElement oldlabel = contents.ElementAt(1);
|
||||
oldlabel.style.display = DisplayStyle.None;
|
||||
|
||||
VisualElement searchButton = background.ElementAt(1);
|
||||
|
||||
searchButton.style.width = StyleKeyword.Auto;
|
||||
searchButton.style.backgroundImage = StyleKeyword.None;
|
||||
searchButton.style.flexDirection = FlexDirection.Row;
|
||||
searchButton.style.overflow = Overflow.Hidden;
|
||||
searchButton.style.flexBasis = StyleKeyword.Auto;
|
||||
|
||||
VisualElement fakeRadial = new VisualElement();
|
||||
fakeRadial.AddToClassList("unity-object-field__selector");
|
||||
fakeRadial.pickingMode = PickingMode.Ignore;
|
||||
fakeRadial.style.backgroundColor = Color.clear;
|
||||
|
||||
Label label = new Label(textureProperty.displayName);
|
||||
label.pickingMode = PickingMode.Ignore;
|
||||
|
||||
label.style.textOverflow = TextOverflow.Ellipsis;
|
||||
searchButton.Add(fakeRadial);
|
||||
searchButton.Add(label);
|
||||
|
||||
Image oldThumbnail = contents.ElementAt(0) as Image;
|
||||
oldThumbnail.style.display = DisplayStyle.None;
|
||||
|
||||
thumbnail = new Image();
|
||||
thumbnail.AddToClassList("textureFieldThumb");
|
||||
thumbnail.AddToClassList("unity-object-field-display__icon");
|
||||
thumbnail.pickingMode = PickingMode.Ignore;
|
||||
thumbnail.scaleMode = ScaleMode.StretchToFill;
|
||||
thumbnail.tintColor = Color.white;
|
||||
thumbnailRT = new RenderTexture((int)(32.0f * EditorGUIUtility.pixelsPerPoint), (int)(32.0f * EditorGUIUtility.pixelsPerPoint), 1, RenderTextureFormat.ARGB32, 1);
|
||||
thumbnailRT.depth = 0;
|
||||
thumbnailRT.name = textureProperty.name + "_icon";
|
||||
thumbnailRT.Create();
|
||||
thumbnail.image = thumbnailRT;
|
||||
|
||||
contents.Insert(0, thumbnail);
|
||||
|
||||
texObjField.RegisterValueChangedCallback(OnObjectFieldChanged);
|
||||
|
||||
|
||||
if (textureProperty.hasMixedValue)
|
||||
{
|
||||
currentValue = null;
|
||||
|
||||
texObjField.showMixedValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (textureProperty.textureValue == null && defaultTexture != null)
|
||||
//{
|
||||
// textureProperty.textureValue = defaultTexture;
|
||||
// currentValue = defaultTexture;
|
||||
//}
|
||||
|
||||
texObjField.showMixedValue = false;
|
||||
}
|
||||
texObjField.SetValueWithoutNotify(currentValue);
|
||||
|
||||
UpdateThumbnail();
|
||||
|
||||
leftAlignBox.Add(texObjField);
|
||||
Add(leftAlignBox);
|
||||
Add(rightAlignBox);
|
||||
}
|
||||
|
||||
void OnObjectFieldChanged(ChangeEvent<Object> evt)
|
||||
{
|
||||
value = evt.newValue;
|
||||
}
|
||||
|
||||
public void SetValueWithoutNotify(Object newValue)
|
||||
{
|
||||
if (newValue == null || newValue is Texture)
|
||||
{
|
||||
currentValue = (Texture) newValue;
|
||||
|
||||
if (currentValue == null && defaultTexture != null)
|
||||
{
|
||||
currentValue = defaultTexture;
|
||||
}
|
||||
|
||||
UpdateThumbnail();
|
||||
textureProperty.textureValue = currentValue;
|
||||
texObjField.SetValueWithoutNotify(currentValue);
|
||||
UpdateObjDelegate.Invoke(texObjField);
|
||||
texObjField.showMixedValue = newValue == null;
|
||||
}
|
||||
else throw new System.ArgumentException($"Expected object of type {typeof(Texture2D)}");
|
||||
}
|
||||
|
||||
public Object value
|
||||
{
|
||||
get => currentValue;
|
||||
set
|
||||
{
|
||||
if (value == currentValue)
|
||||
return;
|
||||
|
||||
Object previous = currentValue;
|
||||
SetValueWithoutNotify(value);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateThumbnail()
|
||||
{
|
||||
BlitTextureIcon(thumbnailRT, currentValue, textureType);
|
||||
}
|
||||
|
||||
public void UpdateMaterialProperty(MaterialProperty boundProp)
|
||||
{
|
||||
bool valueChanged = currentValue != boundProp.textureValue;
|
||||
textureProperty = boundProp;
|
||||
if (valueChanged)
|
||||
{
|
||||
|
||||
currentValue = boundProp.textureValue;
|
||||
texObjField.SetValueWithoutNotify(currentValue);
|
||||
UpdateThumbnail();
|
||||
}
|
||||
|
||||
texObjField.showMixedValue = boundProp.hasMixedValue;
|
||||
}
|
||||
|
||||
void Dispose()
|
||||
{
|
||||
if (thumbnailRT != null)
|
||||
{
|
||||
thumbnailRT.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
static Material s_blitMaterial;
|
||||
static LocalKeyword[] dimKeywords;
|
||||
static LocalKeyword normalMapKeyword;
|
||||
static int prop_Blit2D = Shader.PropertyToID("_Blit2D");
|
||||
static int prop_Blit2DArray = Shader.PropertyToID("_Blit2DArray");
|
||||
static int prop_BlitCube = Shader.PropertyToID("_BlitCube");
|
||||
static int prop_BlitCubeArray = Shader.PropertyToID("_BlitCubeArray");
|
||||
static int prop_Blit3D = Shader.PropertyToID("_Blit3D");
|
||||
static int prop_BlitDim = Shader.PropertyToID("_BlitDim");
|
||||
|
||||
static void UpdateKeywords()
|
||||
{
|
||||
Shader blitShader = s_blitMaterial.shader;
|
||||
dimKeywords[(int)TextureDimension.Tex2D - 2] = new LocalKeyword(blitShader, "DIM_2D");
|
||||
dimKeywords[(int)TextureDimension.Tex2DArray - 2] = new LocalKeyword(blitShader, "DIM_2DARRAY");
|
||||
dimKeywords[(int)TextureDimension.Cube - 2] = new LocalKeyword(blitShader, "DIM_CUBE");
|
||||
dimKeywords[(int)TextureDimension.CubeArray - 2] = new LocalKeyword(blitShader, "DIM_CUBEARRAY");
|
||||
dimKeywords[(int)TextureDimension.Tex3D - 2] = new LocalKeyword(blitShader, "DIM_3D");
|
||||
normalMapKeyword = new LocalKeyword(blitShader, "NORMAL_MAP");
|
||||
}
|
||||
void BlitTextureIcon(RenderTexture icon, Texture tex, TextureDimension texType)
|
||||
{
|
||||
if (icon == null) return;
|
||||
RenderTexture active = RenderTexture.active;
|
||||
if (tex == null)
|
||||
{
|
||||
|
||||
RenderTexture.active = icon;
|
||||
GL.Clear(false, true, Color.clear, 0);
|
||||
RenderTexture.active = active;
|
||||
return;
|
||||
}
|
||||
if (s_blitMaterial == null || s_blitMaterial.shader == null || dimKeywords == null)
|
||||
{
|
||||
Shader blitShader = Shader.Find("Hidden/ShaderGUITextureIconBlit");
|
||||
if (blitShader == null)
|
||||
{
|
||||
Debug.LogError("Could not find Blit_ShaderGUI.shader (Hidden/ShaderGUITextureIconBlit), cannot generate material thumbnails");
|
||||
return;
|
||||
}
|
||||
s_blitMaterial = new Material(blitShader);
|
||||
dimKeywords = new LocalKeyword[5];
|
||||
|
||||
}
|
||||
|
||||
UpdateKeywords();
|
||||
|
||||
|
||||
int offsetDimEnum = (int)texType - 2;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (i == offsetDimEnum)
|
||||
s_blitMaterial.EnableKeyword(dimKeywords[i]);
|
||||
else
|
||||
s_blitMaterial.DisableKeyword(dimKeywords[i]);
|
||||
}
|
||||
switch (texType)
|
||||
{
|
||||
case TextureDimension.Tex2D:
|
||||
s_blitMaterial.SetTexture(prop_Blit2D, tex);
|
||||
break;
|
||||
case TextureDimension.Tex2DArray:
|
||||
s_blitMaterial.SetTexture(prop_Blit2DArray, tex);
|
||||
break;
|
||||
case TextureDimension.Cube:
|
||||
s_blitMaterial.SetTexture(prop_BlitCube, tex);
|
||||
s_blitMaterial.SetVector(prop_BlitDim, new Vector4(tex.width, tex.height, 0, 0));
|
||||
break;
|
||||
case TextureDimension.CubeArray:
|
||||
s_blitMaterial.SetTexture(prop_BlitCubeArray, tex);
|
||||
s_blitMaterial.SetVector(prop_BlitDim, new Vector4(tex.width, tex.height, 0, 0));
|
||||
break;
|
||||
case TextureDimension.Tex3D:
|
||||
s_blitMaterial.SetTexture(prop_Blit3D, tex);
|
||||
s_blitMaterial.SetVector(prop_BlitDim, new Vector4(tex.width, tex.height, 0, 0));
|
||||
break;
|
||||
default:
|
||||
Debug.LogError("Shader GUI Icon Blitter: Unknown texture dimension " + texType);
|
||||
return;
|
||||
}
|
||||
if (isNormalMap)
|
||||
{
|
||||
s_blitMaterial.EnableKeyword(normalMapKeyword);
|
||||
}
|
||||
Graphics.Blit(tex, icon, s_blitMaterial);
|
||||
RenderTexture.active = active;
|
||||
if (isNormalMap)
|
||||
{
|
||||
s_blitMaterial.DisableKeyword(normalMapKeyword);
|
||||
}
|
||||
switch (texType)
|
||||
{
|
||||
case TextureDimension.Tex2D:
|
||||
s_blitMaterial.SetTexture(prop_Blit2D, null);
|
||||
break;
|
||||
case TextureDimension.Tex2DArray:
|
||||
s_blitMaterial.SetTexture(prop_Blit2DArray, null);
|
||||
break;
|
||||
case TextureDimension.Cube:
|
||||
s_blitMaterial.SetTexture(prop_BlitCube, null);
|
||||
break;
|
||||
case TextureDimension.CubeArray:
|
||||
s_blitMaterial.SetTexture(prop_BlitCubeArray, null);
|
||||
break;
|
||||
case TextureDimension.Tex3D:
|
||||
s_blitMaterial.SetTexture(prop_Blit3D, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 38c312bdff088324b93a4ff922600f48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Rendering.Universal;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using SLZ.SLZEditorTools;
|
||||
using UnityEditor.Graphing.Util;
|
||||
using System.Reflection;
|
||||
using Unity.Profiling;
|
||||
|
||||
namespace UnityEditor.SLZMaterialUI
|
||||
{
|
||||
public abstract class UIElementsMaterialEditor : MaterialEditor
|
||||
{
|
||||
static ProfilerMarker UpdateProfiler = new ProfilerMarker("UIElementsUpdateUI");
|
||||
static ProfilerMarker PrepareForAnim = new ProfilerMarker("UIElementsUpdateUI_PrepareForAnim");
|
||||
public Shader shader;
|
||||
public List<BaseMaterialField> materialFields;
|
||||
public MaterialProperty[] materialProperties;
|
||||
public virtual void UpdateUI()
|
||||
{
|
||||
UpdateProfiler.Begin();
|
||||
//Debug.Log("Called Update UI");
|
||||
materialProperties = MaterialEditor.GetMaterialProperties(this.targets);
|
||||
PrepareMaterialPropertiesForAnimationMode(materialProperties, true);
|
||||
int[] shaderProp2MatProp = ShaderGUIUtils.GetShaderIdxToMaterialProp(materialProperties, shader);
|
||||
if (materialFields == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int numFields = materialFields.Count;
|
||||
for (int fIdx = 0; fIdx < numFields; fIdx++)
|
||||
{
|
||||
int propIndex = shaderProp2MatProp[materialFields[fIdx].GetShaderPropIdx()];
|
||||
//Debug.Log("Updating with indices: " + materialFields[fIdx].GetShaderPropIdx() + " " + propIndex);
|
||||
materialFields[fIdx].UpdateMaterialProperty(materialProperties[propIndex]);
|
||||
}
|
||||
UpdateProfiler.End();
|
||||
}
|
||||
|
||||
public override bool UseDefaultMargins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the material inspector, getting the shader used by the materials and assigning it to the shader field.
|
||||
/// In a sane world, unity would only attempt to create the material editor when all materials share the same shader.
|
||||
/// But I don't trust unity, so check to make sure that they're all the same and not null.
|
||||
/// </summary>
|
||||
/// <returns>true on success, false on failure</returns>
|
||||
public bool Initialize(VisualElement root, VisualElement window)
|
||||
{
|
||||
materialProperties = MaterialEditor.GetMaterialProperties(this.targets);
|
||||
PrepareMaterialPropertiesForAnimationMode(materialProperties, true);
|
||||
|
||||
SerializedProperty serializedShader = serializedObject.FindProperty("m_Shader");
|
||||
if (serializedShader.hasMultipleDifferentValues || serializedShader.objectReferenceValue == null)
|
||||
{
|
||||
Debug.LogError("SLZ Material Inspector: attempted to draw custom inspector for materials with different shaders");
|
||||
return false;
|
||||
}
|
||||
this.shader = (Shader)serializedShader.objectReferenceValue;
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogError("SLZ Material Inspector: attempted to draw custom inspector for material with null shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
IMGUIContainer OnUpdate = new IMGUIContainer(() => {
|
||||
bool isDisplay = window.style.display != DisplayStyle.None;
|
||||
if (base.isVisible != isDisplay)
|
||||
{
|
||||
window.style.display = base.isVisible ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
root.MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
OnIMGUITick();
|
||||
|
||||
});
|
||||
root.Add(OnUpdate);
|
||||
root.RegisterCallback<AttachToPanelEvent>(evt => Undo.undoRedoPerformed += UpdateUI);
|
||||
root.RegisterCallback<DetachFromPanelEvent>(evt => Undo.undoRedoPerformed -= UpdateUI);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MethodInfo s_RefreshInspectors;
|
||||
|
||||
|
||||
protected override void OnShaderChanged()
|
||||
{
|
||||
ShaderGUIUtils.ForceRebuild(this);
|
||||
}
|
||||
|
||||
void OnIMGUITick()
|
||||
{
|
||||
if ((target as Material).shader != shader)
|
||||
{
|
||||
ShaderGUIUtils.ForceRebuild(this);
|
||||
return;
|
||||
}
|
||||
if (base.isVisible && AnimationMode.InAnimationMode())
|
||||
{
|
||||
PrepareMaterialPropertiesForAnimationMode(materialProperties, true);
|
||||
UpdateUI();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 31b3f9a51f0228e47aa6afcd959ea3b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Add table
Add a link
Reference in a new issue