OldBlueWater/BlueWater/Assets/Quibli/Scripts/Editor/QuibliEditor.cs
2023-08-02 18:12:26 +09:00

317 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace Quibli {
public class QuibliEditor : BaseShaderGUI {
private Material _target;
private MaterialProperty[] _properties;
private static readonly Dictionary<string, bool> FoldoutStates = new Dictionary<string, bool> {{"Rendering options", false}};
void DrawStandard(MaterialEditor editor, MaterialProperty property) {
string displayName = property.displayName;
// Remove everything in brackets.
displayName = Regex.Replace(displayName, @" ?\[.*?\]", string.Empty);
displayName = Regex.Replace(displayName, @" ?\{.*?\}", string.Empty);
var tooltip = Tooltips.Get(editor, displayName);
var guiContent = new GUIContent(displayName, tooltip);
if (property.type == MaterialProperty.PropType.Texture && !property.displayName.Contains("Gradient")
&& !property.name.Contains("Ramp")) {
if (!property.name.Contains("_BaseMap") && !property.name.Contains("_EmissionMap")) {
EditorGUILayout.Space(15);
}
materialEditor.TexturePropertySingleLine(guiContent, property);
} else {
materialEditor.ShaderProperty(property, guiContent);
}
}
MaterialProperty FindProperty(string name) {
return FindProperty(name, _properties);
}
bool HasProperty(string name) {
return _target != null && _target.HasProperty(name);
}
#if UNITY_2021_2_OR_NEWER
public override void ValidateMaterial(Material material) {
#else
public override void MaterialChanged(Material material) {
#endif
if (material == null) throw new ArgumentNullException(nameof(material));
SetMaterialKeywords(material);
}
public override void OnGUI(MaterialEditor editor, MaterialProperty[] properties) {
materialEditor = editor;
_properties = properties;
_target = editor.target as Material;
Debug.Assert(_target != null);
FindProperties(properties);
if (_target.IsKeywordEnabled("DR_OUTLINE_ON") && _target.IsKeywordEnabled("_ALPHATEST_ON")) {
EditorGUILayout.HelpBox("The 'Outline' and 'Alpha Clip' features are usually " +
"incompatible. The outline shader pass will not be using alpha " +
"clipping.", MessageType.Warning);
}
int originalIntentLevel = EditorGUI.indentLevel;
int foldoutRemainingItems = 0;
bool latestFoldoutState = false;
foreach (MaterialProperty property in properties) {
string displayName = property.displayName;
if (displayName.Contains("[") && !displayName.Contains("FOLDOUT")) {
EditorGUI.indentLevel += 1;
}
var skipProperty = false;
foreach (Match match in Regex.Matches(displayName, @" ?\[DR_.*?\]")) {
var keyword = match.Value.Replace("[", string.Empty).Replace("]", string.Empty);
skipProperty |= !_target.IsKeywordEnabled(keyword);
}
if (_target.IsKeywordEnabled("DR_ENABLE_LIGHTMAP_DIR") &&
displayName.ToLower().Contains("override light direction")) {
var dirPitch = _target.GetFloat("_LightmapDirectionPitch");
var dirYaw = _target.GetFloat("_LightmapDirectionYaw");
var dirPitchRad = dirPitch * Mathf.Deg2Rad;
var dirYawRad = dirYaw * Mathf.Deg2Rad;
var direction = new Vector4(Mathf.Sin(dirPitchRad) * Mathf.Sin(dirYawRad), Mathf.Cos(dirPitchRad),
Mathf.Sin(dirPitchRad) * Mathf.Cos(dirYawRad), 0.0f);
_target.SetVector("_LightmapDirection", direction);
}
// TODO: Disable texture impact via keyword.
if (_target.HasProperty("_TextureImpact") && _target.HasProperty("_BaseMap") &&
_target.GetTexture("_BaseMap") == null) {
_target.SetFloat("_TextureImpact", 0f);
}
if (displayName.Contains("FOLDOUT")) {
string foldoutName = displayName.Split('(', ')')[1];
string foldoutItemCount = displayName.Split('{', '}')[1];
foldoutRemainingItems = Convert.ToInt32(foldoutItemCount);
if (!FoldoutStates.ContainsKey(property.name)) {
FoldoutStates.Add(property.name, false);
}
EditorGUILayout.Space();
FoldoutStates[property.name] = EditorGUILayout.Foldout(FoldoutStates[property.name], foldoutName);
latestFoldoutState = FoldoutStates[property.name];
}
if (foldoutRemainingItems > 0) {
skipProperty = skipProperty || !latestFoldoutState;
EditorGUI.indentLevel += 1;
--foldoutRemainingItems;
}
bool hideInInspector = (property.flags & MaterialProperty.PropFlags.HideInInspector) != 0;
if (!hideInInspector && !skipProperty) {
EditorGUI.BeginChangeCheck();
DrawStandard(editor, property);
if (EditorGUI.EndChangeCheck()) {
#if UNITY_2021_2_OR_NEWER
ValidateMaterial(_target);
#else
MaterialChanged(_target);
#endif
}
}
if (!skipProperty && property.name.Contains("_EmissionMap")) {
EditorGUILayout.Space(15);
DrawEmissionProperties(_target, true);
EditorGUILayout.Space(15);
DrawTileOffset(editor, FindProperty("_BaseMap"));
}
EditorGUI.indentLevel = originalIntentLevel;
}
EditorGUILayout.Space();
FoldoutStates["Rendering options"] =
EditorGUILayout.Foldout(FoldoutStates["Rendering options"], "Rendering options");
if (FoldoutStates["Rendering options"]) {
EditorGUI.indentLevel += 1;
HandleUrpSettings(_target, materialEditor);
EditorGUILayout.Space();
materialEditor.EnableInstancingField();
}
// Toggle the outline pass.
_target.SetShaderPassEnabled("SRPDefaultUnlit", _target.IsKeywordEnabled("DR_OUTLINE_ON"));
}
// Adapted from BaseShaderGUI.cs.
private void HandleUrpSettings(Material material, MaterialEditor materialEditor) {
bool alphaClip = false;
if (material.HasProperty("_AlphaClip")) {
alphaClip = material.GetFloat("_AlphaClip") >= 0.5;
}
if (alphaClip) {
material.EnableKeyword("_ALPHATEST_ON");
} else {
material.DisableKeyword("_ALPHATEST_ON");
}
if (HasProperty("_Surface")) {
EditorGUI.BeginChangeCheck();
var surfaceProp = FindProperty("_Surface");
EditorGUI.showMixedValue = surfaceProp.hasMixedValue;
var surfaceType = (SurfaceType) surfaceProp.floatValue;
EditorGUILayout.Separator();
surfaceType = (SurfaceType) EditorGUILayout.EnumPopup("Surface Type", surfaceType);
if (EditorGUI.EndChangeCheck()) {
materialEditor.RegisterPropertyChangeUndo("Surface Type");
surfaceProp.floatValue = (float) surfaceType;
}
if (surfaceType == SurfaceType.Opaque) {
if (alphaClip) {
material.renderQueue = (int) UnityEngine.Rendering.RenderQueue.AlphaTest;
material.SetOverrideTag("RenderType", "TransparentCutout");
} else {
material.renderQueue = (int) UnityEngine.Rendering.RenderQueue.Geometry;
material.SetOverrideTag("RenderType", "Opaque");
}
material.renderQueue +=
material.HasProperty("_QueueOffset") ? (int) material.GetFloat("_QueueOffset") : 0;
material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.SetShaderPassEnabled("ShadowCaster", true);
} else // Transparent
{
BlendMode blendMode = (BlendMode) material.GetFloat("_Blend");
// Specific Transparent Mode Settings
switch (blendMode) {
case BlendMode.Alpha:
material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
break;
case BlendMode.Premultiply:
material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
break;
case BlendMode.Additive:
material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.One);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
break;
case BlendMode.Multiply:
material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.Zero);
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.EnableKeyword("_ALPHAMODULATE_ON");
break;
}
// General Transparent Material Settings
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_ZWrite", 0);
material.renderQueue = (int) UnityEngine.Rendering.RenderQueue.Transparent;
material.renderQueue +=
material.HasProperty("_QueueOffset") ? (int) material.GetFloat("_QueueOffset") : 0;
material.SetShaderPassEnabled("ShadowCaster", false);
}
// DR: draw popup.
if (surfaceType == SurfaceType.Transparent && HasProperty("_Blend")) {
EditorGUI.BeginChangeCheck();
var blendModeProp = FindProperty("_Blend");
EditorGUI.showMixedValue = blendModeProp.hasMixedValue;
var blendMode = (BlendMode) blendModeProp.floatValue;
blendMode = (BlendMode) EditorGUILayout.EnumPopup("Blend Mode", blendMode);
if (EditorGUI.EndChangeCheck()) {
materialEditor.RegisterPropertyChangeUndo("Blend Mode");
blendModeProp.floatValue = (float) blendMode;
}
}
}
// DR: draw popup.
if (HasProperty("_Cull")) {
EditorGUILayout.Separator();
EditorGUI.BeginChangeCheck();
var cullingProp = FindProperty("_Cull");
EditorGUI.showMixedValue = cullingProp.hasMixedValue;
var culling = (RenderFace) cullingProp.floatValue;
culling = (RenderFace) EditorGUILayout.EnumPopup("Render Faces", culling);
if (EditorGUI.EndChangeCheck()) {
materialEditor.RegisterPropertyChangeUndo("Render Faces");
cullingProp.floatValue = (float) culling;
material.doubleSidedGI = (RenderFace) cullingProp.floatValue != RenderFace.Front;
}
}
if (HasProperty("_AlphaClip")) {
EditorGUILayout.Separator();
EditorGUI.BeginChangeCheck();
var alphaClipProp = FindProperty("_AlphaClip");
EditorGUI.showMixedValue = alphaClipProp.hasMixedValue;
var alphaClipEnabled = EditorGUILayout.Toggle("Alpha Clipping", alphaClipProp.floatValue == 1);
if (EditorGUI.EndChangeCheck()) alphaClipProp.floatValue = alphaClipEnabled ? 1 : 0;
EditorGUI.showMixedValue = false;
if (alphaClipProp.floatValue == 1 && HasProperty("_Cutoff")) {
var alphaCutoffProp = FindProperty("_Cutoff");
materialEditor.ShaderProperty(alphaCutoffProp, "Threshold", 1);
}
}
}
// Adapted from BaseShaderGUI.cs.
private new static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null,
Action<Material> shaderFunc = null) {
// Setup blending - consistent across all Universal RP shaders
SetupMaterialBlendMode(material);
// Receive Shadows
if (material.HasProperty("_ReceiveShadows"))
CoreUtils.SetKeyword(material, "_RECEIVE_SHADOWS_OFF", material.GetFloat("_ReceiveShadows") == 0.0f);
// Emission
if (material.HasProperty("_EmissionColor")) MaterialEditor.FixupEmissiveFlag(material);
bool shouldEmissionBeEnabled =
(material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled)
shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f;
CoreUtils.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
// Normal Map
if (material.HasProperty("_BumpMap"))
CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
// Shader specific keyword functions
shadingModelFunc?.Invoke(material);
shaderFunc?.Invoke(material);
}
}
}