| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.IO;
 
- using System.Reflection;
 
- using System.Text;
 
- using System.Text.RegularExpressions;
 
- using FlatKit;
 
- using FlatKit.StylizedSurface;
 
- using JetBrains.Annotations;
 
- using UnityEditor;
 
- using UnityEngine;
 
- using UnityEngine.Rendering;
 
- using Object = UnityEngine.Object;
 
- // ReSharper disable Unity.PreferAddressByIdToGraphicsParams
 
- // ReSharper disable StringLiteralTypo
 
- [HelpURL("https://flatkit.dustyroom.com/")]
 
- public class StylizedSurfaceEditor : BaseShaderGUI {
 
-     private Material _target;
 
-     private MaterialProperty[] _properties;
 
-     private int _celShadingNumSteps = 0;
 
-     private AnimationCurve _gradient = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
 
-     private bool? _smoothNormalsEnabled;
 
-     private static GUIStyle _boxStyle;
 
-     private static GUIStyle _richHelpBoxStyle;
 
-     private static GUIStyle _foldoutStyle;
 
-     private static readonly Dictionary<string, bool> FoldoutStates = new() { { RenderingOptionsName, false } };
 
-     private static readonly Color HashColor = new Color(0.85023f, 0.85034f, 0.85045f, 0.85056f);
 
-     private static readonly int ColorPropertyName = Shader.PropertyToID("_BaseColor");
 
-     private static readonly int LightmapDirection = Shader.PropertyToID("_LightmapDirection");
 
-     private static readonly int LightmapDirectionPitch = Shader.PropertyToID("_LightmapDirectionPitch");
 
-     private static readonly int LightmapDirectionYaw = Shader.PropertyToID("_LightmapDirectionYaw");
 
-     private const string OutlineSmoothNormalsKeyword = "DR_OUTLINE_SMOOTH_NORMALS";
 
-     private const string RenderingOptionsName = "Rendering Options";
 
-     private const string UnityVersion = "JLE8GP";
 
-     private void DrawStandard(MaterialProperty property) {
 
-         // Remove everything in square brackets.
 
-         var cleanName = Regex.Replace(property.displayName, @" ?\[.*?\]", string.Empty);
 
-         if (!Tooltips.Map.TryGetValue(property.displayName, out string tooltip)) {
 
-             Tooltips.Map.TryGetValue(cleanName, out tooltip);
 
-         }
 
-         var guiContent = new GUIContent(cleanName, tooltip);
 
-         if (property.type == MaterialProperty.PropType.Texture) {
 
-             if (!property.name.Contains("_BaseMap")) {
 
-                 EditorGUILayout.Space(10);
 
-             }
 
-             materialEditor.TexturePropertySingleLine(guiContent, property);
 
-         } else {
 
-             materialEditor.ShaderProperty(property, guiContent);
 
-         }
 
-     }
 
-     private MaterialProperty FindProperty(string name) {
 
-         return FindProperty(name, _properties);
 
-     }
 
-     private bool HasProperty(string name) {
 
-         return _target != null && _target.HasProperty(name);
 
-     }
 
- #if UNITY_2021_2_OR_NEWER
 
-     [Obsolete("MaterialChanged has been renamed ValidateMaterial", false)]
 
- #endif
 
-     public override void MaterialChanged(Material material) { }
 
-     public override void OnGUI(MaterialEditor editor, MaterialProperty[] properties) {
 
-         materialEditor = editor;
 
-         _properties = properties;
 
-         _target = editor.target as Material;
 
-         Debug.Assert(_target != null, "_target != null");
 
-         if (_target.shader.name.Equals("FlatKit/Stylized Surface With Outline")) {
 
-             EditorGUILayout.HelpBox(
 
-                 "'Stylized Surface with Outline' shader has been deprecated. Please use the outline section in the 'Stylized Surface' shader.",
 
-                 MessageType.Warning);
 
-         }
 
-         if (!Application.unityVersion.Contains(Rev(UnityVersion)) &&
 
-             !Application.unityVersion.Contains('b') &&
 
-             !Application.unityVersion.Contains('a') &&
 
-             !Application.unityVersion.Replace('.', '^').Contains("23^2")) {
 
-             EditorGUILayout.BeginVertical(EditorStyles.helpBox);
 
-             EditorGUILayout.BeginHorizontal();
 
-             // Icon.
 
-             {
 
-                 EditorGUILayout.BeginVertical();
 
-                 GUILayout.FlexibleSpace();
 
-                 var icon = EditorGUIUtility.IconContent("console.erroricon@2x").image;
 
-                 var iconSize = Mathf.Min(Mathf.Min(60, icon.width), EditorGUIUtility.currentViewWidth - 100);
 
-                 GUILayout.Label(icon, new GUIStyle {
 
-                     alignment = TextAnchor.MiddleCenter,
 
-                     imagePosition = ImagePosition.ImageLeft,
 
-                     fixedWidth = iconSize,
 
-                     fixedHeight = iconSize,
 
-                     padding = new RectOffset(0, 0, 5, 5),
 
-                     margin = new RectOffset(0, 0, 0, 0),
 
-                 });
 
-                 GUILayout.FlexibleSpace();
 
-                 EditorGUILayout.EndVertical();
 
-             }
 
-             var unityMajorVersion = Application.unityVersion.Substring(0, Application.unityVersion.LastIndexOf('.'));
 
-             var m = $"This version of <b>Flat Kit</b> is designed for <b>Unity {Rev(UnityVersion)}</b>. " +
 
-                     $"You are currently using <b>Unity {unityMajorVersion}</b>.\n" +
 
-                     "<i>The shader and the UI below may not work correctly.</i>\n" +
 
-                     "Please <b>re-download Flat Kit</b> to get the compatible version.";
 
-             var style = new GUIStyle(EditorStyles.wordWrappedLabel) {
 
-                 alignment = TextAnchor.MiddleLeft,
 
-                 richText = true,
 
-                 fontSize = 12,
 
-                 padding = new RectOffset(0, 5, 5, 5),
 
-                 margin = new RectOffset(0, 0, 0, 0),
 
-             };
 
-             EditorGUILayout.LabelField(m, style);
 
-             EditorGUILayout.EndHorizontal();
 
-             // Unity version help buttons.
 
-             {
 
-                 EditorGUILayout.BeginHorizontal();
 
-                 GUILayout.FlexibleSpace();
 
-                 const float buttonWidth = 120;
 
-                 if (GUILayout.Button("Package Manager", EditorStyles.miniButton, GUILayout.Width(buttonWidth))) {
 
-                     const string packageName = "Flat Kit: Toon Shading and Water";
 
-                     var type = typeof(UnityEditor.PackageManager.UI.Window);
 
-                     var method = type.GetMethod("OpenFilter", BindingFlags.NonPublic | BindingFlags.Static);
 
-                     if (method != null) {
 
-                         method.Invoke(null, new object[] { $"AssetStore/{packageName}" });
 
-                     } else {
 
-                         UnityEditor.PackageManager.UI.Window.Open(packageName);
 
-                     }
 
-                 }
 
-                 if (GUILayout.Button("Asset Store", EditorStyles.miniButton, GUILayout.Width(buttonWidth))) {
 
-                     const string assetStoreUrl = "https://u3d.as/1uVy";
 
-                     Application.OpenURL(assetStoreUrl);
 
-                 }
 
-                 if (GUILayout.Button("Support", EditorStyles.miniButton, GUILayout.Width(buttonWidth))) {
 
-                     const string contactUrl = "https://flatkit.dustyroom.com/contact-details/";
 
-                     Application.OpenURL(contactUrl);
 
-                 }
 
-                 EditorGUILayout.EndHorizontal();
 
-                 EditorGUILayout.Space(2);
 
-             }
 
-             EditorGUILayout.EndVertical();
 
-             EditorGUILayout.Space();
 
-             foreach (var property in properties) {
 
-                 // materialEditor.ShaderProperty(property, property.displayName);
 
-                 DrawStandard(property);
 
-             }
 
-             return;
 
-         }
 
-         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;
 
-         string foldoutName = string.Empty;
 
-         int foldoutRemainingItems = 0;
 
-         bool latestFoldoutState = false;
 
-         _foldoutStyle ??= new GUIStyle(EditorStyles.foldout) {
 
-             margin = {
 
-                 left = -5
 
-             },
 
-             padding = {
 
-                 left = 20
 
-             },
 
-         };
 
-         _boxStyle ??= new GUIStyle(EditorStyles.helpBox);
 
-         _richHelpBoxStyle ??= new GUIStyle(EditorStyles.helpBox) {
 
-             richText = true
 
-         };
 
-         bool vGroupStarted = false;
 
-         foreach (MaterialProperty property in properties) {
 
-             string displayName = property.displayName;
 
-             if (displayName.Contains("[") && !displayName.Contains("FOLDOUT")) {
 
-                 EditorGUI.indentLevel += 1;
 
-             }
 
-             bool skipProperty = false;
 
-             skipProperty |= displayName.Contains("[_CELPRIMARYMODE_SINGLE]") &&
 
-                             !_target.IsKeywordEnabled("_CELPRIMARYMODE_SINGLE");
 
-             skipProperty |= displayName.Contains("[_CELPRIMARYMODE_STEPS]") &&
 
-                             !_target.IsKeywordEnabled("_CELPRIMARYMODE_STEPS");
 
-             skipProperty |= displayName.Contains("[_CELPRIMARYMODE_CURVE]") &&
 
-                             !_target.IsKeywordEnabled("_CELPRIMARYMODE_CURVE");
 
-             skipProperty |= displayName.Contains("[DR_CEL_EXTRA_ON]") &&
 
-                             !property.name.Equals("_CelExtraEnabled") &&
 
-                             !_target.IsKeywordEnabled("DR_CEL_EXTRA_ON");
 
-             skipProperty |= displayName.Contains("[DR_SPECULAR_ON]") &&
 
-                             !property.name.Equals("_SpecularEnabled") &&
 
-                             !_target.IsKeywordEnabled("DR_SPECULAR_ON");
 
-             skipProperty |= displayName.Contains("[DR_RIM_ON]") &&
 
-                             !property.name.Equals("_RimEnabled") &&
 
-                             !_target.IsKeywordEnabled("DR_RIM_ON");
 
-             skipProperty |= displayName.Contains("[DR_GRADIENT_ON]") &&
 
-                             !property.name.Equals("_GradientEnabled") &&
 
-                             !_target.IsKeywordEnabled("DR_GRADIENT_ON");
 
-             skipProperty |= displayName.Contains("[_UNITYSHADOWMODE_MULTIPLY]") &&
 
-                             !_target.IsKeywordEnabled("_UNITYSHADOWMODE_MULTIPLY");
 
-             skipProperty |= displayName.Contains("[_UNITYSHADOWMODE_COLOR]") &&
 
-                             !_target.IsKeywordEnabled("_UNITYSHADOWMODE_COLOR");
 
-             skipProperty |= displayName.Contains("[DR_ENABLE_LIGHTMAP_DIR]") &&
 
-                             !_target.IsKeywordEnabled("DR_ENABLE_LIGHTMAP_DIR");
 
-             skipProperty |= displayName.Contains("[DR_OUTLINE_ON]") &&
 
-                             !_target.IsKeywordEnabled("DR_OUTLINE_ON");
 
-             skipProperty |= displayName.Contains("[_EMISSION]") &&
 
-                             !_target.IsKeywordEnabled("_EMISSION");
 
-             skipProperty |= displayName.Contains("[_OUTLINESPACE_SCREEN]") &&
 
-                             !_target.IsKeywordEnabled("_OUTLINESPACE_SCREEN");
 
-             bool isOverrideLightDirectionToggle = displayName.ToLower().Contains("override light direction");
 
-             if (Lightmapping.lightingDataAsset != null)
 
-             {
 
-                 // Lightmapping is enabled.
 
-                 _target.EnableKeyword("DR_ENABLE_LIGHTMAP_DIR");
 
-                 if (isOverrideLightDirectionToggle)
 
-                 {
 
-                     skipProperty = true;
 
-                     if (latestFoldoutState && foldoutName.Contains("Advanced Lighting"))
 
-                     {
 
-                         const string m = "<b>Lightmap Direction Override</b> is required because the scene is using baked lighting.";
 
-                         EditorGUILayout.LabelField(m, new GUIStyle(EditorStyles.label)
 
-                         {
 
-                             richText = true,
 
-                             wordWrap = true,
 
-                             padding = new RectOffset(16, 0, 8, 0)
 
-                         });
 
-                     }
 
-                 }
 
-             }
 
-             if (_target.IsKeywordEnabled("DR_ENABLE_LIGHTMAP_DIR") && isOverrideLightDirectionToggle) {
 
-                 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);
 
-             }
 
-             if (displayName.Contains("FOLDOUT")) {
 
-                 foldoutName = displayName.Split('(', ')')[1];
 
-                 string foldoutItemCount = displayName.Split('{', '}')[1];
 
-                 foldoutRemainingItems = Convert.ToInt32(foldoutItemCount);
 
-                 FoldoutStates.TryAdd(property.name, false);
 
-                 EditorGUILayout.Space(10);
 
-                 FoldoutStates[property.name] =
 
-                     EditorGUILayout.Foldout(FoldoutStates[property.name], foldoutName, _foldoutStyle);
 
-                 latestFoldoutState = FoldoutStates[property.name];
 
-                 if (latestFoldoutState) {
 
-                     BeginBox();
 
-                 }
 
-             }
 
-             if (foldoutRemainingItems > 0) {
 
-                 skipProperty = skipProperty || !latestFoldoutState;
 
-                 EditorGUI.indentLevel += 1;
 
-                 --foldoutRemainingItems;
 
-             } else if (!skipProperty) {
 
-                 if (EditorGUI.indentLevel > 0 && !vGroupStarted) {
 
-                     BeginBox();
 
-                     vGroupStarted = true;
 
-                 }
 
-                 if (EditorGUI.indentLevel <= 0 && vGroupStarted) {
 
-                     EndBox();
 
-                     vGroupStarted = false;
 
-                 }
 
-             }
 
-             if (_target.IsKeywordEnabled("_CELPRIMARYMODE_STEPS") && displayName.Contains("[LAST_PROP_STEPS]")) {
 
-                 EditorGUILayout.HelpBox(
 
-                     "This mode creates a step texture that control the light/shadow transition. To use:\n" +
 
-                     "1. Set the number of steps (e.g. 3 means three steps between lit and shaded regions), \n" +
 
-                     "2. Save the steps as a texture - 'Save Ramp Texture' button",
 
-                     MessageType.Info);
 
-                 int currentNumSteps = _target.GetInt("_CelNumSteps");
 
-                 if (currentNumSteps != _celShadingNumSteps) {
 
-                     if (GUILayout.Button("Save Ramp Texture")) {
 
-                         _celShadingNumSteps = currentNumSteps;
 
-                         PromptTextureSave(editor, GenerateStepTexture, "_CelStepTexture", FilterMode.Point);
 
-                     }
 
-                 }
 
-             }
 
-             if (_target.IsKeywordEnabled("_CELPRIMARYMODE_CURVE") && displayName.Contains("[LAST_PROP_CURVE]")) {
 
-                 EditorGUILayout.HelpBox(
 
-                     "This mode uses arbitrary curves to control the light/shadow transition. How to use:\n" +
 
-                     "1. Set shading curve (generally from 0.0 to 1.0)\n" +
 
-                     "2. [Optional] Save the curve preset\n" +
 
-                     "3. Save the curve as a texture.",
 
-                     MessageType.Info);
 
-                 _gradient = EditorGUILayout.CurveField("Shading curve", _gradient);
 
-                 if (GUILayout.Button("Save Ramp Texture")) {
 
-                     PromptTextureSave(editor, GenerateCurveTexture, "_CelCurveTexture",
 
-                         FilterMode.Trilinear);
 
-                 }
 
-             }
 
-             if (!skipProperty &&
 
-                 property.type == MaterialProperty.PropType.Color &&
 
-                 property.colorValue == HashColor) {
 
-                 property.colorValue = _target.GetColor(ColorPropertyName);
 
-             }
 
-             if (!skipProperty && property.name.Contains("_EmissionMap")) {
 
-                 EditorGUILayout.Space(10);
 
-                 bool emission = editor.EmissionEnabledProperty();
 
-                 EditorGUILayout.Space(-10);
 
-                 EditorGUI.indentLevel += 1;
 
-                 if (emission) {
 
-                     _target.EnableKeyword("_EMISSION");
 
-                 } else {
 
-                     _target.DisableKeyword("_EMISSION");
 
-                 }
 
-             }
 
-             if (!skipProperty && property.name.Contains("_EmissionColor")) {
 
-                 EditorGUI.indentLevel += 1;
 
-             }
 
-             bool hideInInspector = (property.flags & MaterialProperty.PropFlags.HideInInspector) != 0;
 
-             if (!hideInInspector && !skipProperty) {
 
-                 EditorGUI.BeginChangeCheck();
 
-                 DrawStandard(property);
 
-                 // Toggle per-object outlines.
 
-                 if (property.name.Equals("_OutlineEnabled")) {
 
-                     var outlineEnabled = _target.IsKeywordEnabled("DR_OUTLINE_ON");
 
-                     if (_target.GetShaderPassEnabled("SRPDEFAULTUNLIT")) {
 
-                         // Legacy per-object outlines.
 
-                         const string m = "Using legacy per-object outlines. Please update to Unity 2022.3+ to use " +
 
-                                          "the new Renderer Feature outlines.";
 
-                         EditorGUILayout.HelpBox(m, MessageType.Info);
 
-                     } else {
 
-                         // Per-object outlines are now handled by a Renderer Feature.
 
-                         var renderer = ObjectOutlineEditorUtils.GetRendererData();
 
-                         if (renderer != null) {
 
-                             GUILayout.Space(-EditorGUIUtility.standardVerticalSpacing -
 
-                                             EditorGUIUtility.singleLineHeight);
 
-                             GUILayout.BeginHorizontal();
 
-                             GUILayout.FlexibleSpace();
 
-                             if (GUILayout.Button("Select Renderer Feature", EditorStyles.miniButtonRight)) {
 
-                                 Selection.activeObject = renderer;
 
-                             }
 
-                             GUILayout.EndHorizontal();
 
-                         }
 
-                     }
 
-                     if (EditorGUI.EndChangeCheck()) {
 
-                         // Outline toggle changed state.
 
- #if UNITY_2022_3_OR_NEWER
 
-                         ObjectOutlineEditorUtils.SetActive(_target, outlineEnabled);
 
- #else
 
-                         _target.SetShaderPassEnabled("SRPDEFAULTUNLIT", outlineEnabled);
 
- #endif
 
-                     }
 
- #if UNITY_2022_3_OR_NEWER
 
-                     // Switch from legacy shader pass per-object outlines (pre-4.7.0) to new Renderer Feature outlines.
 
-                     const string legacyPassName = "SRPDEFAULTUNLIT";
 
-                     if (_target.GetShaderPassEnabled(legacyPassName) && outlineEnabled) {
 
-                         _target.SetShaderPassEnabled(legacyPassName, false);
 
-                         var m = $"<color=grey>[Flat Kit]</color> <b>Per-object outlines</b> are now handled by a " +
 
-                                 $"<b>Renderer Feature</b>. The material <color=green><b>{_target.name}</b></color> " +
 
-                                 $"and the <b>URP Renderer</b> currently in use will be updated now.";
 
-                         Debug.Log(m);
 
-                         ObjectOutlineEditorUtils.SetActive(_target, true);
 
-                     }
 
- #endif
 
-                 }
 
-             }
 
-             if (!skipProperty && displayName.Contains("Detail Impact")) {
 
-                 DrawTileOffset(editor, FindProperty("_DetailMap"));
 
-             }
 
-             // Horizontal line separators.
 
-             {
 
-                 if (FoldoutStates.TryGetValue("_BaseMap", out bool baseMapFoldoutState) && baseMapFoldoutState) {
 
-                     if (displayName.Contains("Texture Impact") ||
 
-                         displayName.Contains("Detail Impact") ||
 
-                         displayName.Contains("Normal Map") ||
 
-                         displayName.Contains("Emission Color")) {
 
-                         var indent = EditorGUI.indentLevel;
 
-                         EditorGUI.indentLevel = originalIntentLevel + 1;
 
-                         EditorGUILayout.Space(5);
 
-                         EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
 
-                         EditorGUILayout.Space(-5);
 
-                         EditorGUI.indentLevel = indent;
 
-                     }
 
-                 }
 
-             }
 
-             if (!skipProperty && property.name.Contains("_EmissionColor")) {
 
-                 EditorGUILayout.Space(10);
 
-                 EditorGUI.indentLevel -= 1;
 
-                 EditorGUILayout.LabelField("Applied to All Maps", EditorStyles.boldLabel);
 
-                 DrawTileOffset(editor, FindProperty("_BaseMap"));
 
-             }
 
-             if (!skipProperty && property.displayName.Contains("Smooth Normals")) {
 
-                 SmoothNormalsUI();
 
-             }
 
-             EditorGUI.indentLevel = originalIntentLevel;
 
-             if (foldoutRemainingItems == 0 && latestFoldoutState) {
 
-                 EndBox();
 
-                 latestFoldoutState = false;
 
-                 if (foldoutName.Contains("Advanced Lighting")) {
 
-                     const string m = "<b>Advanced Lighting</b> features have significantly different impact in real-time and baked lighting.";
 
-                     EditorGUILayout.LabelField(m, _richHelpBoxStyle);
 
-                 }
 
-             }
 
-         }
 
-         EditorGUILayout.Space(10);
 
-         var renderingOptionsName = RenderingOptionsName;
 
-         FoldoutStates[renderingOptionsName] =
 
-             EditorGUILayout.Foldout(FoldoutStates[renderingOptionsName], renderingOptionsName, _foldoutStyle);
 
-         if (FoldoutStates[renderingOptionsName]) {
 
-             EditorGUI.indentLevel += 1;
 
-             BeginBox();
 
-             HandleUrpSettings(_target, editor);
 
-             EndBox();
 
-         }
 
-         if (_target.IsKeywordEnabled("_UNITYSHADOWMODE_NONE")) {
 
-             _target.EnableKeyword("_RECEIVE_SHADOWS_OFF");
 
-         } else {
 
-             _target.DisableKeyword("_RECEIVE_SHADOWS_OFF");
 
-         }
 
-         // Toggle the outline pass. Disabling by name `Outline` doesn't work.
 
-         // _target.SetShaderPassEnabled("SRPDEFAULTUNLIT", _target.IsKeywordEnabled("DR_OUTLINE_ON"));
 
-         /*
 
-         if (HasProperty("_MainTex")) {
 
-             TransferToBaseMap();
 
-         }
 
-         */
 
-     }
 
-     private void BeginBox() {
 
-         EditorGUILayout.BeginVertical(_boxStyle);
 
-         EditorGUILayout.Space(3);
 
-     }
 
-     private void EndBox() {
 
-         EditorGUILayout.Space(3);
 
-         EditorGUILayout.EndVertical();
 
-     }
 
-     private void SmoothNormalsUI() {
 
-         var keywordEnabled = _target.IsKeywordEnabled(OutlineSmoothNormalsKeyword);
 
-         _smoothNormalsEnabled ??= keywordEnabled;
 
-         if (keywordEnabled != _smoothNormalsEnabled) {
 
-             var mesh = GetMeshFromSelection();
 
-             if (mesh == null) {
 
-                 return;
 
-             }
 
-             if (keywordEnabled) {
 
-                 if (!MeshSmoother.HasSmoothNormals(mesh)) {
 
-                     SmoothNormals(mesh);
 
-                 }
 
-             }
 
-         } else if (keywordEnabled) {
 
-             var mesh = GetMeshFromSelection();
 
-             if (mesh == null) {
 
-                 return;
 
-             }
 
-             if (!MeshSmoother.HasSmoothNormals(mesh)) {
 
-                 EditorGUILayout.HelpBox(
 
-                     "Mesh does not have smooth normals. Please use the 'Smooth Normals' button to generate them.",
 
-                     MessageType.Warning);
 
-                 if (mesh.subMeshCount > 1) {
 
-                     EditorGUILayout.HelpBox(
 
-                         "Mesh smoothing is not supported for meshes with multiple sub-meshes. " +
 
-                         "Please combine sub-meshes into a single sub-mesh before smoothing.",
 
-                         MessageType.Warning);
 
-                 }
 
-                 GUILayout.BeginHorizontal();
 
-                 GUILayout.FlexibleSpace();
 
-                 if (GUILayout.Button("Smooth Normals", GUILayout.ExpandWidth(false))) {
 
-                     SmoothNormals(mesh);
 
-                 }
 
-                 GUILayout.EndHorizontal();
 
-             }
 
-         }
 
-         _smoothNormalsEnabled = keywordEnabled;
 
-     }
 
-     private void SmoothNormals(Mesh mesh) {
 
-         if (mesh.isReadable) {
 
-             MeshSmoother.SmoothNormals(mesh);
 
-             var path = AssetDatabase.GetAssetPath(mesh);
 
-             var pathSmoothed =
 
-                 $"{Path.GetDirectoryName(path)}\\{Path.GetFileNameWithoutExtension(path)} Smooth Normals.asset";
 
-             var fileExists = File.Exists(pathSmoothed);
 
-             if (fileExists) {
 
-                 var action1 = EditorUtility.DisplayDialogComplex("Smoothing normals",
 
-                     "Asset already exists. Do you want to overwrite it?",
 
-                     "Overwrite", "Cancel", "Open asset");
 
-                 switch (action1) {
 
-                     case 0: {
 
-                         // Overwrite
 
-                         AssetDatabase.DeleteAsset(pathSmoothed);
 
-                         break;
 
-                     }
 
-                     case 1: {
 
-                         // Cancel
 
-                         _target.DisableKeyword(OutlineSmoothNormalsKeyword);
 
-                         return;
 
-                     }
 
-                     case 2: {
 
-                         // Open asset
 
-                         AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<Object>(pathSmoothed));
 
-                         return;
 
-                     }
 
-                 }
 
-             }
 
-             var newMesh = Object.Instantiate(mesh);
 
-             try {
 
-                 AssetDatabase.CreateAsset(newMesh, pathSmoothed);
 
-                 Debug.Log($"<b>[Flat Kit]</b> Created asset <i>{pathSmoothed}</i>.");
 
-             }
 
-             catch (Exception) {
 
-                 Debug.Log("<b>[Flat Kit]</b> Please ignore the error above. It is caused by a Unity bug.");
 
-                 var action2 = EditorUtility.DisplayDialogComplex("Error",
 
-                     $"Could not create asset at path '{pathSmoothed}'. Please check the Console for more information.",
 
-                     "OK", "Show Console", "Save to 'Assets' folder");
 
-                 switch (action2) {
 
-                     case 0: {
 
-                         // OK
 
-                         _target.DisableKeyword(OutlineSmoothNormalsKeyword);
 
-                         return;
 
-                     }
 
-                     case 1: {
 
-                         // Show Console
 
-                         EditorApplication.ExecuteMenuItem("Window/General/Console");
 
-                         return;
 
-                     }
 
-                     case 2: {
 
-                         // Save to Assets folder
 
-                         pathSmoothed = $"Assets/{Path.GetFileName(pathSmoothed)}";
 
-                         AssetDatabase.CreateAsset(newMesh, pathSmoothed);
 
-                         break;
 
-                     }
 
-                 }
 
-             }
 
-             AssetDatabase.SaveAssets();
 
-             AssetDatabase.Refresh();
 
-             var newAsset = AssetDatabase.LoadAssetAtPath<Mesh>(pathSmoothed);
 
-             if (newAsset != null) {
 
-                 SetMeshToSelection(newAsset);
 
-             }
 
-         } else {
 
-             var action = EditorUtility.DisplayDialogComplex("Smoothing normals",
 
-                 "Mesh is not readable. Please enable 'Read/Write Enabled' in the mesh import settings.",
 
-                 "Set readable", "Open import settings", "Cancel");
 
-             switch (action) {
 
-                 case 0: {
 
-                     // Set readable
 
-                     var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(mesh));
 
-                     if (importer != null) {
 
-                         var modelImporter = importer as ModelImporter;
 
-                         if (modelImporter != null) {
 
-                             modelImporter.isReadable = true;
 
-                             modelImporter.SaveAndReimport();
 
-                         }
 
-                     }
 
-                     break;
 
-                 }
 
-                 case 1: {
 
-                     // Open import settings
 
-                     var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(mesh));
 
-                     if (importer != null) {
 
-                         AssetDatabase.OpenAsset(importer);
 
-                     }
 
-                     break;
 
-                 }
 
-                 case 2: {
 
-                     // Cancel
 
-                     _target.DisableKeyword(OutlineSmoothNormalsKeyword);
 
-                     break;
 
-                 }
 
-             }
 
-         }
 
-     }
 
-     private static Mesh GetMeshFromSelection() {
 
-         var go = Selection.activeGameObject;
 
-         if (go == null) {
 
-             EditorGUILayout.HelpBox(
 
-                 "All meshes using smooth normals need processing. To process a mesh, select it in a scene and " +
 
-                 "re-enable 'Smooth Normals' in the inspector.",
 
-                 MessageType.Info);
 
-             return null;
 
-         }
 
-         var meshFilter = go.GetComponent<MeshFilter>();
 
-         if (meshFilter != null) {
 
-             return meshFilter.sharedMesh;
 
-         }
 
-         var skinnedMeshRenderer = go.GetComponent<SkinnedMeshRenderer>();
 
-         if (skinnedMeshRenderer != null) {
 
-             return skinnedMeshRenderer.sharedMesh;
 
-         }
 
-         return null;
 
-     }
 
-     private static void SetMeshToSelection(Mesh mesh) {
 
-         var go = Selection.activeGameObject;
 
-         if (go == null) {
 
-             return;
 
-         }
 
-         var meshFilter = go.GetComponent<MeshFilter>();
 
-         if (meshFilter != null) {
 
-             meshFilter.sharedMesh = mesh;
 
-             return;
 
-         }
 
-         var skinnedMeshRenderer = go.GetComponent<SkinnedMeshRenderer>();
 
-         if (skinnedMeshRenderer != null) {
 
-             skinnedMeshRenderer.sharedMesh = mesh;
 
-         }
 
-     }
 
- // Adapted from BaseShaderGUI.cs.
 
-     private void HandleUrpSettings(Material material, MaterialEditor editor) {
 
-         queueOffsetProp = FindProperty("_QueueOffset");
 
-         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;
 
-             surfaceType = (SurfaceType)EditorGUILayout.EnumPopup("Surface Type", surfaceType);
 
-             if (EditorGUI.EndChangeCheck()) {
 
-                 editor.RegisterPropertyChangeUndo("Surface Type");
 
-                 surfaceProp.floatValue = (float)surfaceType;
 
-             }
 
-             if (surfaceType == SurfaceType.Opaque) {
 
-                 if (alphaClip) {
 
-                     material.renderQueue = (int)RenderQueue.AlphaTest;
 
-                     material.SetOverrideTag("RenderType", "TransparentCutout");
 
-                 } else {
 
-                     material.renderQueue = (int)RenderQueue.Geometry;
 
-                     material.SetOverrideTag("RenderType", "Opaque");
 
-                 }
 
-                 material.renderQueue += queueOffsetProp != null ? (int)queueOffsetProp.floatValue : 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)RenderQueue.Transparent;
 
-                 material.renderQueue += queueOffsetProp != null ? (int)queueOffsetProp.floatValue : 0;
 
-                 material.SetShaderPassEnabled("ShadowCaster", false);
 
-             }
 
-             // DR: draw popup.
 
-             if (surfaceType == SurfaceType.Transparent && HasProperty("_Blend")) {
 
-                 EditorGUI.BeginChangeCheck();
 
-                 var blendModeProperty = FindProperty("_Blend");
 
-                 EditorGUI.showMixedValue = blendModeProperty.hasMixedValue;
 
-                 var blendMode = (BlendMode)blendModeProperty.floatValue;
 
-                 blendMode = (BlendMode)EditorGUILayout.EnumPopup("Blend Mode", blendMode);
 
-                 if (EditorGUI.EndChangeCheck()) {
 
-                     editor.RegisterPropertyChangeUndo("Blend Mode");
 
-                     blendModeProperty.floatValue = (float)blendMode;
 
-                 }
 
-             }
 
-         }
 
-         DrawQueueOffsetField();
 
-         // DR: draw popup.
 
-         if (HasProperty("_Cull")) {
 
-             EditorGUI.BeginChangeCheck();
 
-             var cullProp = FindProperty("_Cull");
 
-             EditorGUI.showMixedValue = cullProp.hasMixedValue;
 
-             var culling = (RenderFace)cullProp.floatValue;
 
-             culling = (RenderFace)EditorGUILayout.EnumPopup("Render Faces", culling);
 
-             if (EditorGUI.EndChangeCheck()) {
 
-                 editor.RegisterPropertyChangeUndo("Render Faces");
 
-                 cullProp.floatValue = (float)culling;
 
-                 material.doubleSidedGI = (RenderFace)cullProp.floatValue != RenderFace.Front;
 
-             }
 
-         }
 
-         if (HasProperty("_AlphaClip")) {
 
-             EditorGUI.BeginChangeCheck();
 
-             var clipProp = FindProperty("_AlphaClip");
 
-             EditorGUI.showMixedValue = clipProp.hasMixedValue;
 
-             // ReSharper disable once CompareOfFloatsByEqualityOperator
 
-             var alphaClipEnabled = EditorGUILayout.Toggle("Alpha Clipping", clipProp.floatValue == 1);
 
-             if (EditorGUI.EndChangeCheck())
 
-                 clipProp.floatValue = alphaClipEnabled ? 1 : 0;
 
-             EditorGUI.showMixedValue = false;
 
-             // ReSharper disable once CompareOfFloatsByEqualityOperator
 
-             if (clipProp.floatValue == 1 && HasProperty("_Cutoff")) {
 
-                 var cutoffProp = FindProperty("_Cutoff");
 
-                 editor.ShaderProperty(cutoffProp, "Threshold", 1);
 
-             }
 
-         }
 
-         editor.EnableInstancingField();
 
-     }
 
-     private void PromptTextureSave(MaterialEditor editor, Func<Texture2D> generate, string propertyName,
 
-         FilterMode filterMode) {
 
-         var rampTexture = generate();
 
-         var pngNameNoExtension = $"{editor.target.name}{propertyName}-ramp";
 
-         var fullPath =
 
-             EditorUtility.SaveFilePanel("Save Ramp Texture", "Assets", pngNameNoExtension, "png");
 
-         if (fullPath.Length > 0) {
 
-             SaveTextureAsPng(rampTexture, fullPath, filterMode);
 
-             var loadedTexture = LoadTexture(fullPath);
 
-             if (loadedTexture != null) {
 
-                 _target.SetTexture(propertyName, loadedTexture);
 
-             } else {
 
-                 Debug.LogWarning("Could not save the texture. Make sure the destination is in the Assets folder.");
 
-             }
 
-         }
 
-     }
 
-     private Texture2D GenerateStepTexture() {
 
-         int numSteps = _celShadingNumSteps;
 
-         var t2d = new Texture2D(numSteps + 1, /*height=*/1, TextureFormat.R8, /*mipChain=*/false) {
 
-             filterMode = FilterMode.Point,
 
-             wrapMode = TextureWrapMode.Clamp
 
-         };
 
-         for (int i = 0; i < numSteps + 1; i++) {
 
-             var color = Color.white * i / numSteps;
 
-             t2d.SetPixel(i, 0, color);
 
-         }
 
-         t2d.Apply();
 
-         return t2d;
 
-     }
 
-     private Texture2D GenerateCurveTexture() {
 
-         const int width = 256;
 
-         const int height = 1;
 
-         var lut = new Texture2D(width, height, TextureFormat.R8, /*mipChain=*/false) {
 
-             alphaIsTransparency = false,
 
-             wrapMode = TextureWrapMode.Clamp,
 
-             hideFlags = HideFlags.HideAndDontSave,
 
-             filterMode = FilterMode.Trilinear
 
-         };
 
-         for (float x = 0; x < width; x++) {
 
-             float value = _gradient.Evaluate(x / width);
 
-             for (float y = 0; y < height; y++) {
 
-                 var color = Color.white * value;
 
-                 lut.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
 
-             }
 
-         }
 
-         return lut;
 
-     }
 
-     private static void SaveTextureAsPng(Texture2D texture, string fullPath, FilterMode filterMode) {
 
-         byte[] bytes = texture.EncodeToPNG();
 
-         File.WriteAllBytes(fullPath, bytes);
 
-         AssetDatabase.Refresh();
 
-         Debug.Log($"<b>[Flat Kit]</b> Texture saved as: {fullPath}");
 
-         string pathRelativeToAssets = ConvertFullPathToAssetPath(fullPath);
 
-         TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(pathRelativeToAssets);
 
-         if (importer != null) {
 
-             importer.filterMode = filterMode;
 
-             importer.textureType = TextureImporterType.SingleChannel;
 
-             importer.textureCompression = TextureImporterCompression.Uncompressed;
 
-             importer.mipmapEnabled = false;
 
-             var textureSettings = new TextureImporterPlatformSettings {
 
-                 format = TextureImporterFormat.R8
 
-             };
 
-             importer.SetPlatformTextureSettings(textureSettings);
 
-             EditorUtility.SetDirty(importer);
 
-             importer.SaveAndReimport();
 
-         }
 
-         // 22b5f7ed-989d-49d1-90d9-c62d76c3081a
 
-         Debug.Assert(importer,
 
-             string.Format("[FlatKit] Could not change import settings of {0} [{1}]",
 
-                 fullPath, pathRelativeToAssets));
 
-     }
 
-     private static Texture2D LoadTexture(string fullPath) {
 
-         string pathRelativeToAssets = ConvertFullPathToAssetPath(fullPath);
 
-         if (pathRelativeToAssets.Length == 0) {
 
-             return null;
 
-         }
 
-         var loadedTexture = AssetDatabase.LoadAssetAtPath(pathRelativeToAssets, typeof(Texture2D)) as Texture2D;
 
-         if (loadedTexture == null) {
 
-             Debug.LogError(string.Format("[FlatKit] Could not load texture from {0} [{1}].", fullPath,
 
-                 pathRelativeToAssets));
 
-             return null;
 
-         }
 
-         loadedTexture.filterMode = FilterMode.Point;
 
-         loadedTexture.wrapMode = TextureWrapMode.Clamp;
 
-         return loadedTexture;
 
-     }
 
-     private static string ConvertFullPathToAssetPath(string fullPath) {
 
-         int count = (Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar).Length;
 
-         return fullPath.Remove(0, count);
 
-     }
 
-     private static string Rev(string a) {
 
-         StringBuilder b = new StringBuilder(a.Length);
 
-         int i = 0;
 
-         foreach (char c in a) {
 
-             b.Append((char)(c - "8<3F9="[i] % 32));
 
-             i = (i + 1) % 6;
 
-         }
 
-         return b.ToString();
 
-     }
 
- #if !UNITY_2020_3_OR_NEWER
 
-     private new void DrawQueueOffsetField() {
 
-         GUIContent queueSlider = new GUIContent("     Priority",
 
-             "Determines the chronological rendering order for a Material. High values are rendered first.");
 
-         const int queueOffsetRange = 50;
 
-         MaterialProperty queueOffsetProp = FindProperty("_QueueOffset", _properties, false);
 
-         if (queueOffsetProp == null) return;
 
-         EditorGUI.BeginChangeCheck();
 
-         EditorGUI.showMixedValue = queueOffsetProp.hasMixedValue;
 
-         var queue = EditorGUILayout.IntSlider(queueSlider, (int) queueOffsetProp.floatValue, -queueOffsetRange,
 
-             queueOffsetRange);
 
-         if (EditorGUI.EndChangeCheck())
 
-             queueOffsetProp.floatValue = queue;
 
-         EditorGUI.showMixedValue = false;
 
-         _target.renderQueue = (int)RenderQueue.Transparent + queue;
 
-     }
 
- #endif
 
-     [UsedImplicitly]
 
-     private void TransferToBaseMap() {
 
-         var baseMapProperty = FindProperty("_MainTex");
 
-         var baseColorProperty = FindProperty("_Color");
 
-         _target.SetTexture("_BaseMap", baseMapProperty.textureValue);
 
-         var baseMapTiling = baseMapProperty.textureScaleAndOffset;
 
-         _target.SetTextureScale("_BaseMap", new Vector2(baseMapTiling.x, baseMapTiling.y));
 
-         _target.SetTextureOffset("_BaseMap", new Vector2(baseMapTiling.z, baseMapTiling.w));
 
-         _target.SetColor("_BaseColor", baseColorProperty.colorValue);
 
-     }
 
-     [UsedImplicitly]
 
-     private void TransferToMainTex() {
 
-         var baseMapProperty = FindProperty("_BaseMap");
 
-         var baseColorProperty = FindProperty("_BaseColor");
 
-         _target.SetTexture("_MainTex", baseMapProperty.textureValue);
 
-         var baseMapTiling = baseMapProperty.textureScaleAndOffset;
 
-         _target.SetTextureScale("_MainTex", new Vector2(baseMapTiling.x, baseMapTiling.y));
 
-         _target.SetTextureOffset("_MainTex", new Vector2(baseMapTiling.z, baseMapTiling.w));
 
-         _target.SetColor("_Color", baseColorProperty.colorValue);
 
-     }
 
- }
 
 
  |