2093 lines
90 KiB
C#
2093 lines
90 KiB
C#
#if UNITY_EDITOR
|
|
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace SpriteShadersUltimate
|
|
{
|
|
public class SSUShaderGUI : ShaderGUI
|
|
{
|
|
//Toggles:
|
|
static bool showMasking = false;
|
|
static bool showNoise = false;
|
|
static bool showTime = false;
|
|
|
|
//GUI Resources:
|
|
GUIStyle labelStyle;
|
|
GUIStyle labelCenterStyle;
|
|
GUIStyle buttonStyle;
|
|
static Color warnColor = new Color(1, 0.7f, 0.65f, 0.7f);
|
|
static Color lightWarnColor = new Color(1f, 0.8f, 0.65f, 0.7f);
|
|
static Color hintColor = new Color(1, 1, 1, 0.7f);
|
|
Shader shader;
|
|
Material defaultMaterial;
|
|
GameObject gameObject;
|
|
Dictionary<string, ShaderHintSSU> allHints;
|
|
ShaderHintSSU currentHint;
|
|
|
|
//Internal:
|
|
HashSet<string> enabledShaders;
|
|
HashSet<string> toggleProperties;
|
|
HashSet<string> hidingProperties;
|
|
HashSet<string> enableProperties;
|
|
HashSet<string> alwaysHiddenProperties;
|
|
HashSet<string> linesAboveProperties;
|
|
List<string> shaderList;
|
|
Dictionary<string, int> shaderDictionary;
|
|
Shader lastShader;
|
|
bool newCategory; //Used to avoid drawing lines at the beginning of a new category.
|
|
bool isDisabled; //Skip shaders.
|
|
bool isHidden; //Used to skip hidden properties.
|
|
bool skipGUI; //Skip GUI refresh after changing the shader.
|
|
float shaderSpace; //Used to skip hidden properties.
|
|
string spaceName; //Used to skip hidden properties.
|
|
float shaderFading; //Used to skip hidden properties.
|
|
int currentBoxColor; //Shader Rainbow Color
|
|
int shaderAmount; //Counter
|
|
int enabledAmount; //Counter
|
|
int textureAmount; //Samples
|
|
float performanceBenchmark;
|
|
float lastTitleHeight; //For Category Lines
|
|
Sprite lastSSF; //Sprite for last SSF.
|
|
static int bakeStackAmount = 1;
|
|
|
|
//Status:
|
|
static Material[] materials;
|
|
bool wasWarned;
|
|
bool requiresFullRectMesh, requiresSpriteSheetFix, requiresInstancing, requiresTiling;
|
|
|
|
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
|
{
|
|
Initialize(materialEditor, properties);
|
|
DrawStatus(materialEditor);
|
|
|
|
if(skipGUI)
|
|
{
|
|
skipGUI = false;
|
|
return;
|
|
}
|
|
|
|
//Properties:
|
|
enabledShaders = new HashSet<string>();
|
|
isDisabled = false;
|
|
isHidden = false;
|
|
EditorGUILayout.BeginVertical();
|
|
for (int n = 0; n < properties.Length; n++)
|
|
{
|
|
newCategory = false;
|
|
MaterialProperty prop = properties[n];
|
|
|
|
//Always Skipped:
|
|
if(alwaysHiddenProperties.Contains(prop.name))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//Space Skipped:
|
|
if (prop.name == "_PixelsPerUnit" && !(shaderSpace < 0.5f || (shaderSpace > 4.5f && shaderSpace < 5.5f))) continue;
|
|
if (prop.name == "_ScreenWidthUnits" && !(shaderSpace > 5.5f)) continue;
|
|
if ((prop.name == "_RectHeight" || prop.name == "_RectWidth") && !(shaderSpace > 4.5f && shaderSpace < 5.5f)) continue;
|
|
|
|
//Fading Skipped:
|
|
if (prop.name == "_FadingFade" && shaderFading < 0.5f) continue;
|
|
if (prop.name == "_FadingMask" && Mathf.RoundToInt(shaderFading) != 2) continue;
|
|
if ((prop.name == "_FadingPosition" || prop.name == "_FadingNoiseFactor") && Mathf.RoundToInt(shaderFading) != 4) continue;
|
|
if ((prop.name == "_FadingWidth" || prop.name == "_FadingNoiseScale") && Mathf.RoundToInt(shaderFading) != 4 && Mathf.RoundToInt(shaderFading) != 3) continue;
|
|
|
|
//Basic:
|
|
if (prop.name == "_MetallicMap" && materials[0].GetFloat("_MetallicMapToggle") < 0.5f) continue;
|
|
|
|
bool isKeyword = toggleProperties.Contains(prop.name);
|
|
|
|
//Enable:
|
|
if (enableProperties.Contains(prop.name))
|
|
{
|
|
isDisabled = DrawShaderToggle(materialEditor, prop);
|
|
isHidden = false;
|
|
|
|
continue; //Dont display shader toggle twice.
|
|
}
|
|
else
|
|
{
|
|
if (isDisabled)
|
|
{
|
|
continue; //Skip disabled properties.
|
|
}
|
|
}
|
|
|
|
string displayName = prop.displayName;
|
|
|
|
//Categories:
|
|
if (prop.name == "_MainTex")
|
|
{
|
|
DrawShaderCategory("Main");
|
|
displayName = "Sprite Texture";
|
|
}
|
|
else if (prop.name == "_ShaderSpace")
|
|
{
|
|
DrawShaderCategory("Space");
|
|
shaderSpace = prop.floatValue;
|
|
|
|
switch (Mathf.RoundToInt(shaderSpace))
|
|
{
|
|
case (0):
|
|
spaceName = "UV";
|
|
break;
|
|
case (1):
|
|
spaceName = "UV Raw";
|
|
break;
|
|
case (2):
|
|
spaceName = "Object";
|
|
requiresInstancing = true;
|
|
break;
|
|
case (3):
|
|
spaceName = "Scaled Object";
|
|
requiresInstancing = true;
|
|
break;
|
|
case (4):
|
|
spaceName = "World";
|
|
break;
|
|
case (5):
|
|
spaceName = "UI Rect";
|
|
break;
|
|
case (6):
|
|
spaceName = "Screen";
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (prop.name == "_ToggleUnscaledTime")
|
|
{
|
|
DrawShaderCategory("Time", ref showTime);
|
|
}
|
|
else if (prop.name == "_ShaderFading")
|
|
{
|
|
//Space Hints:
|
|
switch (Mathf.RoundToInt(shaderSpace))
|
|
{
|
|
case (0):
|
|
DisplayHint("- Uses the <b>UV</b> position with size adjustment.");
|
|
break;
|
|
case (1):
|
|
DisplayHint("- Uses the raw <b>UV</b> position.");
|
|
break;
|
|
case (2):
|
|
DisplayHint("- Uses the <b>local position</b> of the object.");
|
|
break;
|
|
case (3):
|
|
DisplayHint("- Uses the <b>local position</b> with scale adjustment.");
|
|
break;
|
|
case (4):
|
|
DisplayHint("- Uses the <b>world position</b> (good for scene effects).");
|
|
break;
|
|
case (5):
|
|
DisplayHint("- Use this for <b>UI images</b>.");
|
|
DisplayHint("- The <b>ImageSSU</b> component auto-updates <b>rect size</b>.");
|
|
|
|
//Add component:
|
|
if (gameObject != null && gameObject.GetComponent<RectTransform>() != null && gameObject.GetComponent<Image>() != null && gameObject.GetComponent<ImageSSU>() == null)
|
|
{
|
|
EditorGUILayout.Space();
|
|
GUI.color = new Color(0.8f, 1f, 0.8f);
|
|
if (GUILayout.Button("Add Helper Component"))
|
|
{
|
|
if (gameObject.GetComponent<InstancerSSU>() != null)
|
|
{
|
|
MonoBehaviour.DestroyImmediate(gameObject.GetComponent<InstancerSSU>());
|
|
}
|
|
gameObject.AddComponent<ImageSSU>();
|
|
}
|
|
GUI.color = Color.white;
|
|
}
|
|
break;
|
|
case (6):
|
|
DisplayHint("- Use this for non-moving <b>UI Images</b> or <b>fullscreen</b> effects..");
|
|
break;
|
|
}
|
|
|
|
DrawShaderCategory("Fading");
|
|
shaderFading = prop.floatValue;
|
|
}
|
|
else if (prop.name == "_UberNoiseTexture")
|
|
{
|
|
DrawShaderCategory("Noise", ref showNoise);
|
|
}
|
|
else if (prop.name == "_VertexTintFirst")
|
|
{
|
|
DrawShaderCategory("Settings");
|
|
}
|
|
else if (prop.name == "_IsText")
|
|
{
|
|
DrawShaderCategory("GUI Settings");
|
|
}
|
|
else if (prop.name == "_StencilComp")
|
|
{
|
|
DrawShaderCategory("UI Masking", ref showMasking);
|
|
}
|
|
|
|
if (isKeyword && !newCategory && prop.name != "PixelSnap" && prop.name != "_UseUIAlphaClip" && prop.name != "_MetallicMapToggle")
|
|
{
|
|
//Space:
|
|
if (prop.name == "_TogglePixelArt" && shaderSpace > 1.1f)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//GUI:
|
|
if (prop.name == "_IsTextMeshPro" && materials[0].GetFloat("_IsText") < 0.5f)
|
|
{
|
|
isHidden = true;
|
|
continue;
|
|
}
|
|
|
|
//Time:
|
|
if(showTime == false)
|
|
{
|
|
if(prop.name == "_ToggleCustomTime" || prop.name == "_ToggleTimeSpeed" || prop.name == "_ToggleTimeFPS" || prop.name == "_ToggleTimeFrequency")
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//Lines:
|
|
Lines();
|
|
|
|
//Hiding:
|
|
if (hidingProperties.Contains(prop.name))
|
|
{
|
|
isHidden = prop.floatValue < 0.5f;
|
|
}
|
|
}
|
|
else if (isHidden)
|
|
{
|
|
if (prop.name == "_EnchantedLowColor" || prop.name == "_EnchantedHighColor" || prop.name == "_ShiftingColorA" || prop.name == "_ShiftingColorB")
|
|
{
|
|
//No Skipping
|
|
}
|
|
else
|
|
{
|
|
continue; //Skip hidden properties.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (prop.name == "_EnchantedLowColor" || prop.name == "_EnchantedHighColor" || prop.name == "_ShiftingColorA" || prop.name == "_ShiftingColorB")
|
|
{
|
|
continue; //Skipping if not Hidden
|
|
}
|
|
}
|
|
|
|
//Lines Above:
|
|
if (linesAboveProperties.Contains(prop.name))
|
|
{
|
|
Lines();
|
|
}
|
|
|
|
//Name:
|
|
string[] splitName = displayName.Split(':');
|
|
if (splitName.Length > 1)
|
|
{
|
|
displayName = splitName[1];
|
|
if (displayName[0] == ' ')
|
|
{
|
|
displayName = displayName.Substring(1);
|
|
}
|
|
}
|
|
GUIContent displayContent = new GUIContent(displayName, isKeyword ? "" : prop.name + " (C#)");
|
|
|
|
//Display:
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture)
|
|
{
|
|
prop.textureValue = (Texture)EditorGUILayout.ObjectField(displayContent, prop.textureValue, typeof(Texture), false, GUILayout.Height(50));
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Vector)
|
|
{
|
|
if(prop.name == "_SpriteSheetRect")
|
|
{
|
|
prop.vectorValue = EditorGUI.Vector4Field(PropertyLabel(displayContent), GUIContent.none, prop.vectorValue);
|
|
}
|
|
else
|
|
{
|
|
prop.vectorValue = EditorGUI.Vector2Field(PropertyLabel(displayContent), GUIContent.none, prop.vectorValue);
|
|
}
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Range)
|
|
{
|
|
bool isSlider = true;
|
|
if (prop.name == "_FadingFade" && Mathf.RoundToInt(shaderFading) == 4)
|
|
{
|
|
isSlider = false;
|
|
}
|
|
|
|
if (isSlider)
|
|
{
|
|
prop.floatValue = EditorGUI.Slider(GetPropertySize(prop, isKeyword), displayContent, prop.floatValue, prop.rangeLimits.x, prop.rangeLimits.y);
|
|
}
|
|
else
|
|
{
|
|
prop.floatValue = EditorGUI.FloatField(GetPropertySize(prop, isKeyword), displayContent, prop.floatValue);
|
|
}
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Color)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUI.showMixedValue = prop.hasMixedValue;
|
|
|
|
bool showEyedropper = false;
|
|
bool showAlpha = false;
|
|
bool showContrast = false;
|
|
if (prop.name.StartsWith("_Recolor"))
|
|
{
|
|
showAlpha = true;
|
|
showContrast = true;
|
|
}
|
|
if (prop.name == "_ColorReplaceFromColor")
|
|
{
|
|
showEyedropper = true;
|
|
}
|
|
|
|
Color color = EditorGUILayout.ColorField(displayContent, prop.colorValue, showEyedropper, showAlpha, true);
|
|
|
|
if (showContrast)
|
|
{
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.y -= 1;
|
|
GUI.color = new Color(1, 1, 1, 0.5f);
|
|
GUI.Label(lastRect, "<color=#00000000>" + displayContent.text + "</color> <b><size=9>| " + Mathf.RoundToInt(prop.colorValue.a * 200) + "% Contrast</size></b>", labelStyle);
|
|
GUI.color = Color.white;
|
|
}
|
|
|
|
EditorGUI.showMixedValue = false;
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
prop.colorValue = color;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
materialEditor.ShaderProperty(GetPropertySize(prop, isKeyword), prop, displayContent);
|
|
}
|
|
|
|
if (!isKeyword)
|
|
{
|
|
ResetButton(prop);
|
|
HelpButton(prop, displayContent);
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
//Hints:
|
|
if (prop.name == "_ToggleUnscaledTime" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Requires <b>one</b> active <b>UnscaledTimeSSU</b> component in your scene.");
|
|
}
|
|
if (prop.name == "_TimeFPS")
|
|
{
|
|
DisplayHint("- Limits shader animations to <b>" + Mathf.RoundToInt(prop.floatValue) + "</b> frames per second.");
|
|
}
|
|
if (prop.name == "_TimeRange")
|
|
{
|
|
DisplayHint("- Time flows <b>back</b> and <b>forth</b>.");
|
|
}
|
|
if(prop.name == "_VertexTintFirst" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Applies the vertex tint <b>before</b> the applying shaders.");
|
|
}
|
|
if (prop.name == "_TilingFix" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Fixes issues with <b>tiling</b> shaders.");
|
|
DisplayHint("- This is only required on <b>sprite sheets</b>.");
|
|
}
|
|
if (prop.name == "_PixelPerfectSpace" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Snaps the <b>shader space</b> to the sprite's pixels.");
|
|
DisplayHint("- Only works with <b>UV</b> shader space.");
|
|
DisplayHint("- Does not work well with <b>Smooth Pixel Art</b>, use one or the other.");
|
|
}
|
|
if (prop.name == "_PixelPerfectUV" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Snaps the <b>UV manipulation</b> to the sprite's pixels.");
|
|
DisplayHint("- This works best with <b>Point No Filter</b> and <b>Pixel Snap</b>.");
|
|
DisplayHint("- Does not work well with <b>Smooth Pixel Art</b>, use one or the other.");
|
|
}
|
|
if (prop.name == "_BakedMaterial" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Enabled while baking shaders to textures.");
|
|
DisplayHint("- You can <b>ignore</b> this.");
|
|
}
|
|
if (prop.name == "_ForceAlpha" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Forces the alpha to always be <b>100%</b>.");
|
|
DisplayHint("- You can <b>ignore</b> this.");
|
|
}
|
|
if(prop.name == "_WindLocalWind" && prop.floatValue < 0.5f)
|
|
{
|
|
DisplayHint("- Uses and requires <b>WindManagerSSU</b> for <b>global</b> wind.");
|
|
}
|
|
if (prop.name == "_WindMaxIntensity")
|
|
{
|
|
DisplayHint("- Uses <b>local</b> wind settings.");
|
|
}
|
|
if (prop.name == "_WindHighQualityNoise" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Generates less <b>repetitive</b> noise, but costs more performance.");
|
|
}
|
|
if (prop.name == "_SpriteSheetRect")
|
|
{
|
|
DisplayHint("- Requires the <b>SpriteSheetSSU</b> component.");
|
|
DisplayHint("- Fixes sprite sheet issues for shaders like the <b>Wind</b> shader.");
|
|
|
|
Sprite targetSprite = null;
|
|
EditorGUILayout.BeginHorizontal();
|
|
GUI.color = new Color(1, 1, 1, 0.7f);
|
|
EditorGUILayout.PrefixLabel("- Manual Rect Calculation");
|
|
targetSprite = (Sprite) EditorGUILayout.ObjectField(targetSprite, typeof(Sprite), true);
|
|
if (targetSprite != null)
|
|
{
|
|
foreach(Material mat in materials)
|
|
{
|
|
mat.SetVector("_SpriteSheetRect", SpriteSheetSSU.GetSheetVector(targetSprite));
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
GUI.color = Color.white;
|
|
|
|
//Apply to Sprite Renderer:
|
|
if (Selection.activeGameObject != null)
|
|
{
|
|
SpriteRenderer spriteRenderer = Selection.activeGameObject.GetComponent<SpriteRenderer>();
|
|
if(spriteRenderer != null && spriteRenderer.sharedMaterial == materials[0])
|
|
{
|
|
if(spriteRenderer.HasPropertyBlock() && spriteRenderer.sprite != null && spriteRenderer.sprite != lastSSF)
|
|
{
|
|
lastSSF = spriteRenderer.sprite;
|
|
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
|
|
spriteRenderer.GetPropertyBlock(mpb);
|
|
mpb.SetVector("_SpriteSheetRect", SpriteSheetSSU.GetSheetVector(lastSSF));
|
|
spriteRenderer.SetPropertyBlock(mpb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (prop.name == "_WiggleFixedGroundToggle" && prop.floatValue > 0.5f)
|
|
{
|
|
DisplayHint("- Prevents the sprite from <b>sliding</b> on the ground.");
|
|
}
|
|
if(prop.name == "_TMPSmoothness")
|
|
{
|
|
DisplayHint("- Many <b>distortion</b> shaders will not work.");
|
|
DisplayHint("- <b>Bold</b> markups will not work.");
|
|
}
|
|
|
|
//Other:
|
|
if (currentHint != null)
|
|
{
|
|
if(currentHint.hints != null)
|
|
{
|
|
for(int s = 0; s < currentHint.hints.Count; s++)
|
|
{
|
|
HintText suffix = currentHint.hints[s];
|
|
if(suffix.property == prop.name)
|
|
{
|
|
DisplayHint(suffix.text);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(currentHint.spaceHint != null && currentHint.spaceHint == prop.name)
|
|
{
|
|
DisplaySpaceHint();
|
|
}
|
|
if (currentHint.lines != null)
|
|
{
|
|
for (int l = 0; l < currentHint.lines.Count; l++)
|
|
{
|
|
string line = currentHint.lines[l];
|
|
if (line == prop.name)
|
|
{
|
|
Lines();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
|
|
//Final Category Close:
|
|
ShaderTitle("Close");
|
|
|
|
//Additional:
|
|
AdditionalMaterialProperties(materialEditor);
|
|
}
|
|
|
|
void Initialize(MaterialEditor materialEditor, MaterialProperty[] properties)
|
|
{
|
|
gameObject = Selection.activeGameObject;
|
|
|
|
if(allHints == null)
|
|
{
|
|
allHints = new Dictionary<string, ShaderHintSSU>();
|
|
}
|
|
|
|
if(enabledShaders == null)
|
|
{
|
|
enabledShaders = new HashSet<string>();
|
|
}
|
|
|
|
if(shaderList == null || shaderList.Count == 0)
|
|
{
|
|
shaderList = new List<string>();
|
|
shaderList.Add("Sprite Shaders Ultimate/Standard SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/Additive SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/GUI SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/Additive GUI SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/2D Lit URP SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/3D Lit URP SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/3D Lit BuiltIn SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/Multiplicative SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/3D Lit Cutout URP SSU");
|
|
shaderList.Add("Sprite Shaders Ultimate/3D Lit Cutout BuiltIn SSU");
|
|
|
|
shaderDictionary = new Dictionary<string, int>();
|
|
for(int n = 0; n < shaderList.Count; n++)
|
|
{
|
|
shaderDictionary.Add(shaderList[n], n);
|
|
}
|
|
}
|
|
|
|
labelStyle = new GUIStyle(GUI.skin.label);
|
|
labelStyle.richText = true;
|
|
|
|
labelCenterStyle = new GUIStyle(labelStyle);
|
|
labelCenterStyle.alignment = TextAnchor.MiddleCenter;
|
|
|
|
buttonStyle = new GUIStyle(GUI.skin.button);
|
|
buttonStyle.richText = true;
|
|
buttonStyle.alignment = TextAnchor.MiddleCenter;
|
|
|
|
shader = ((Material) materialEditor.target).shader;
|
|
if (defaultMaterial == null || defaultMaterial.shader != shader)
|
|
{
|
|
defaultMaterial = new Material(shader);
|
|
}
|
|
|
|
if (lastShader != shader)
|
|
{
|
|
lastShader = shader;
|
|
|
|
toggleProperties = new HashSet<string>();
|
|
foreach (MaterialProperty prop in properties)
|
|
{
|
|
if (IsKeyword(prop))
|
|
{
|
|
toggleProperties.Add(prop.name);
|
|
}
|
|
}
|
|
|
|
hidingProperties = new HashSet<string>();
|
|
foreach (MaterialProperty prop in properties)
|
|
{
|
|
if (prop.name.StartsWith("_Toggle") || prop.name.EndsWith("Toggle") || prop.name == "_IsTextMeshPro" || prop.name == "_WindLocalWind" || prop.name == "_WindIsParallax" || prop.name == "_SpriteSheetFix")
|
|
{
|
|
hidingProperties.Add(prop.name);
|
|
}
|
|
}
|
|
|
|
enableProperties = new HashSet<string>();
|
|
foreach (MaterialProperty prop in properties)
|
|
{
|
|
if (prop.name.StartsWith("_Enable"))
|
|
{
|
|
enableProperties.Add(prop.name);
|
|
}
|
|
}
|
|
|
|
alwaysHiddenProperties = new HashSet<string>();
|
|
alwaysHiddenProperties.Add("_AlphaTex");
|
|
alwaysHiddenProperties.Add("_texcoord");
|
|
alwaysHiddenProperties.Add("_EmissionColor");
|
|
alwaysHiddenProperties.Add("_AlphaCutoff");
|
|
alwaysHiddenProperties.Add("_UIVertexColorAlwaysGammaSpace");
|
|
|
|
linesAboveProperties = new HashSet<string>();
|
|
linesAboveProperties.Add("_MaskMap");
|
|
linesAboveProperties.Add("_Smoothness");
|
|
linesAboveProperties.Add("_NormalMap");
|
|
linesAboveProperties.Add("_ShadowClip");
|
|
linesAboveProperties.Add("_AlphaClip");
|
|
}
|
|
|
|
materials = new Material[materialEditor.targets.Length];
|
|
for(int m = 0; m < materials.Length; m++)
|
|
{
|
|
materials[m] = (Material) materialEditor.targets[m];
|
|
}
|
|
}
|
|
|
|
void DrawStatus(MaterialEditor materialEditor)
|
|
{
|
|
//Top:
|
|
GUI.color = Color.white;
|
|
EditorGUILayout.BeginVertical("Helpbox");
|
|
|
|
//Shaders Toolbar:
|
|
int selected = -1;
|
|
if(shaderDictionary.ContainsKey(shader.name))
|
|
{
|
|
selected = shaderDictionary[shader.name];
|
|
}
|
|
int newSelection = GUILayout.Toolbar(selected, new string[] { "Standard", "Additive", "GUI", "Additive GUI" });
|
|
int secondSelection = GUILayout.Toolbar(selected - 4, new string[] { "2D Lit URP", "3D Lit URP", "3D Lit Built-In", "Multiplicative" });
|
|
int thirdSelection = GUILayout.Toolbar(selected - 8, new string[] { "3D Lit Cutout URP", "3D Lit Cutout Built-In"});
|
|
if (secondSelection > -1 && secondSelection != selected - 4)
|
|
{
|
|
newSelection = secondSelection + 4;
|
|
}
|
|
if (thirdSelection > -1 && thirdSelection != selected - 8)
|
|
{
|
|
newSelection = thirdSelection + 8;
|
|
}
|
|
|
|
if (newSelection != selected)
|
|
{
|
|
Undo.RecordObjects(materials, "Changed SSU Shader");
|
|
skipGUI = true;
|
|
|
|
foreach(Material mat in materials)
|
|
{
|
|
mat.shader = Shader.Find(shaderList[newSelection]);
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
//Status:
|
|
GUI.color = new Color(0.7f, 1f, 0.7f, EditorGUIUtility.isProSkin ? 1f : 0.7f);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField("- Enabled <b>" + enabledAmount + "</b> out of <b>" + shaderAmount + "</b> shaders.", labelStyle);
|
|
|
|
//Fading:
|
|
switch(Mathf.RoundToInt(shaderFading))
|
|
{
|
|
case (0):
|
|
//No Cost
|
|
break;
|
|
case (1):
|
|
performanceBenchmark += 400;
|
|
break;
|
|
case (2):
|
|
performanceBenchmark += 600;
|
|
textureAmount++;
|
|
break;
|
|
case (3):
|
|
performanceBenchmark += 950;
|
|
textureAmount++;
|
|
break;
|
|
case (4):
|
|
performanceBenchmark += 1150;
|
|
textureAmount++;
|
|
break;
|
|
}
|
|
|
|
//Performance:
|
|
/*if(performanceBenchmark <= 1)
|
|
{
|
|
EditorGUILayout.LabelField("- GPU Performance: " + "<b>" + Mathf.RoundToInt(performanceBenchmark * 0.1f) + "</b> (<size=11>same as unity's built-in shader</size>)", labelStyle);
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.LabelField("- GPU Performance: " + "<b>" + Mathf.RoundToInt(performanceBenchmark * 0.1f) + "</b>", labelStyle);
|
|
}
|
|
|
|
if (textureAmount == 1)
|
|
{
|
|
EditorGUILayout.LabelField("- Texture Samples: <b>" + textureAmount + "</b> (<size=11>the sprite texture</size>)", labelStyle);
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.LabelField("- Texture Samples: <b>" + textureAmount + "</b>", labelStyle);
|
|
}*/
|
|
EditorGUILayout.EndVertical();
|
|
|
|
wasWarned = false;
|
|
|
|
//Color Space:
|
|
if (PlayerSettings.colorSpace != ColorSpace.Linear)
|
|
{
|
|
StartWarning(true);
|
|
EditorGUILayout.LabelField("- The <b>default</b> shader variables are <b>adjusted</b> for <b>Linear</b> color space.", labelStyle);
|
|
EditorGUILayout.LabelField("- Switch to <b>Linear</b> for higher <b>quality</b> and better <b>default</b> settings.", labelStyle);
|
|
|
|
if (GUILayout.Button("Switch to <b>Linear</b> (recommended)", buttonStyle))
|
|
{
|
|
Undo.RecordObjects(materials, "Enabled Linear Color Space");
|
|
|
|
PlayerSettings.colorSpace = ColorSpace.Linear;
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Conflict Warnings:
|
|
if (enabledShaders.Contains("World Tiling") && enabledShaders.Contains("Screen Tiling"))
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>World</b> and <b>Screen Tiling</b> aren't compatible.", labelStyle);
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
if (enabledShaders.Contains("Smooth Pixel Art") && enabledShaders.Contains("Gaussian Blur"))
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>Smooth Pixel Art</b> and <b>Gaussian Blur</b> aren't compatible.", labelStyle);
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Texture Warnings:
|
|
Texture activeTexture = GetTexture(materialEditor);
|
|
Sprite activeSprite = GetSprite();
|
|
TextureImporter textureImporter = GetTextureImporter(activeTexture);
|
|
if (textureImporter != null)
|
|
{
|
|
TextureImporterSettings textureSettings = new TextureImporterSettings();
|
|
textureImporter.ReadTextureSettings(textureSettings);
|
|
|
|
if (textureImporter != null)
|
|
{
|
|
//Tiling and Sheet Conflict:
|
|
if(requiresTiling && textureImporter.spriteImportMode == SpriteImportMode.Multiple && materials[0].GetFloat("_TilingFix") < 0.5f)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>Tiling</b> shaders cause problems with <b>sprite sheets</b>.", labelStyle);
|
|
EditorGUILayout.LabelField("- Please enable <b>Tiling Fix</b> to fix these problems.", labelStyle);
|
|
EditorGUILayout.LabelField("- Also make sure <b>Sprite Sheet Fix</b> is enabled.", labelStyle);
|
|
if (GUILayout.Button("Enable <b>Tiling Fix</b>", buttonStyle))
|
|
{
|
|
Undo.RecordObjects(materials, "Enabled Tiling Fix Option");
|
|
|
|
foreach (Material mat in materials)
|
|
{
|
|
mat.EnableKeyword("_TILINGFIX_ON");
|
|
mat.SetFloat("_TilingFix", 1f);
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Full Rect Mesh:
|
|
if (requiresFullRectMesh && textureSettings.spriteMeshType != SpriteMeshType.FullRect)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- Set <b>Mesh Type</b> to <b>Full Rect</b> to avoid pixel clipping.", labelStyle);
|
|
|
|
if (GUILayout.Button("Set <b>Mesh Type</b> to <b>Full Rect</b>", buttonStyle))
|
|
{
|
|
textureSettings.spriteMeshType = SpriteMeshType.FullRect;
|
|
|
|
Undo.RecordObject(textureImporter, "Changed Mesh Type");
|
|
|
|
textureImporter.SetTextureSettings(textureSettings);
|
|
textureImporter.SaveAndReimport();
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Tiling Fix:
|
|
if (requiresTiling && textureSettings.wrapMode == TextureWrapMode.Clamp)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- Some shaders require <b>Wrap Mode</b> set to <b>Repeat</b>.", labelStyle);
|
|
EditorGUILayout.LabelField("- <b>Tiling</b> won't work properly without this setting.", labelStyle);
|
|
|
|
if (GUILayout.Button("Set <b>Wrap Mode</b> to <b>Repeat</b>", buttonStyle))
|
|
{
|
|
textureSettings.wrapMode = TextureWrapMode.Repeat;
|
|
|
|
Undo.RecordObject(textureImporter, "Changed Wrap Mode");
|
|
|
|
textureImporter.SetTextureSettings(textureSettings);
|
|
textureImporter.SaveAndReimport();
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Sprite Sheet Fix:
|
|
if (enabledShaders.Contains("Wiggle") && materials[0].GetFloat("_WiggleFixedGroundToggle") > 0.5f)
|
|
{
|
|
requiresSpriteSheetFix = true;
|
|
}
|
|
if((requiresSpriteSheetFix || requiresTiling) && textureImporter.spriteImportMode == SpriteImportMode.Multiple && materials[0].GetFloat("_SpriteSheetFix") < 0.5f && activeSprite != null)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- Some shaders require the <b>Sprite Sheet Fix</b> option.", labelStyle);
|
|
if (GUILayout.Button("Enable <b>Sprite Sheet Fix</b>", buttonStyle))
|
|
{
|
|
Undo.RecordObjects(materials, "Enabled Sprite Sheet Fix Option");
|
|
|
|
foreach (Material mat in materials)
|
|
{
|
|
mat.EnableKeyword("_SPRITESHEETFIX_ON");
|
|
mat.SetFloat("_SpriteSheetFix", 1f);
|
|
|
|
mat.SetVector("_SpriteSheetRect", SpriteSheetSSU.GetSheetVector(activeSprite));
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Sprite Sheet Component:
|
|
if (materials[0].GetFloat("_SpriteSheetFix") > 0.5f && Selection.activeGameObject != null && Selection.activeGameObject.GetComponent<SpriteSheetSSU>() == false)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- You might need the <b>SpriteSheetSSU</b> component.", labelStyle);
|
|
EditorGUILayout.LabelField("- It updates the <b>Rect</b> variable depending on the <b>Sprite</b>.", labelStyle);
|
|
|
|
if (GUILayout.Button("Add <b>SpriteSheetSSU</b>", buttonStyle))
|
|
{
|
|
Undo.AddComponent(Selection.activeGameObject, typeof(SpriteSheetSSU));
|
|
}
|
|
|
|
Material mat = materials[0];
|
|
if(activeSprite != null)
|
|
{
|
|
mat.SetVector("_SpriteSheetRect", SpriteSheetSSU.GetSheetVector(activeSprite));
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Instance Required:
|
|
if (requiresInstancing && Selection.activeGameObject != null && Selection.activeGameObject.GetComponent<InstancerSSU>() == null)
|
|
{
|
|
StartWarning();
|
|
if (Mathf.RoundToInt(shaderSpace) == 2 || Mathf.RoundToInt(shaderSpace) == 3)
|
|
{
|
|
EditorGUILayout.LabelField("- <b>Object</b> space requires <b>unique</b> material <b>instances</b>.", labelStyle);
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.LabelField("- Some shaders require <b>unique</b> material <b>instances</b>.", labelStyle);
|
|
}
|
|
EditorGUILayout.LabelField("- <b>Instantiate</b> the material at <b>runtime</b> to fix this.", labelStyle);
|
|
|
|
if (Selection.activeGameObject.GetComponent<SpriteRenderer>() != null)
|
|
{
|
|
EditorGUILayout.LabelField("- <b>Modifying</b> the material at <b>runtime</b> will <b>instantiate</b> it.", labelStyle);
|
|
}
|
|
|
|
bool multiple = false;
|
|
if (enabledShaders.Contains("Wind"))
|
|
{
|
|
multiple = true;
|
|
if (GUILayout.Button("Add <b>InteractiveWindSSU</b>", buttonStyle))
|
|
{
|
|
Undo.AddComponent(Selection.activeGameObject, typeof(InteractiveWindSSU));
|
|
}
|
|
}
|
|
if (GUILayout.Button("Add <b>MaterialInstancerSSU</b>", buttonStyle))
|
|
{
|
|
Undo.AddComponent(Selection.activeGameObject, typeof(MaterialInstancerSSU));
|
|
}
|
|
|
|
if (multiple)
|
|
{
|
|
EditorGUILayout.LabelField("- You only need <b>one</b> of these components.", labelStyle);
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Bilinear:
|
|
if (enabledShaders.Contains("Smooth Pixel Art") && textureSettings.filterMode == FilterMode.Point)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>Smooth Pixel Art</b> requires <b>Bilinear</b> filtering.", labelStyle);
|
|
|
|
if (GUILayout.Button("Set <b>Filter Mode</b> to <b>Bilinear</b>", buttonStyle))
|
|
{
|
|
textureSettings.filterMode = FilterMode.Bilinear;
|
|
|
|
Undo.RecordObject(textureImporter, "Changed Filter Mode");
|
|
|
|
textureImporter.SetTextureSettings(textureSettings);
|
|
textureImporter.SaveAndReimport();
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
if(enabledShaders.Contains("Pixelate"))
|
|
{
|
|
if (textureSettings.mipmapEnabled)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>Pixelate</b> does not work with <b>mip maps</b>.", labelStyle);
|
|
|
|
if (GUILayout.Button("Disable <b>Mip Maps</b>", buttonStyle))
|
|
{
|
|
textureSettings.mipmapEnabled = false;
|
|
|
|
Undo.RecordObject(textureImporter, "Disabled Mip Maps");
|
|
|
|
textureImporter.SetTextureSettings(textureSettings);
|
|
textureImporter.SaveAndReimport();
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//WindParallaxSSU Required:
|
|
if(enabledShaders.Contains("Wind") && materials[0].GetFloat("_WindIsParallax") > 0.5f && Selection.activeGameObject != null && Selection.activeGameObject.GetComponent<WindParallaxSSU>() == null)
|
|
{
|
|
StartWarning();
|
|
EditorGUILayout.LabelField("- <b>Is Parallax</b> requires the <b>WindParallaxSSU</b> component.", labelStyle);
|
|
EditorGUILayout.LabelField("- This will fix any issues with <b>moving</b> the sprite.", labelStyle);
|
|
|
|
if (GUILayout.Button("Add <b>WindParallaxSSU</b>", buttonStyle))
|
|
{
|
|
Undo.AddComponent(Selection.activeGameObject, typeof(WindParallaxSSU));
|
|
}
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
if(!wasWarned)
|
|
{
|
|
GUI.color = new Color(0.7f, 1, 1f, EditorGUIUtility.isProSkin ? 1f : 0.7f);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField("- No <b>issues</b> were detected.", labelStyle);
|
|
EditorGUILayout.LabelField("- Detected issues will be <b>displayed here</b>.", labelStyle);
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
//Reset Requirements:
|
|
requiresSpriteSheetFix = requiresFullRectMesh = requiresInstancing = requiresTiling = false;
|
|
|
|
//Support Box:
|
|
GUI.color = new Color(0.7f, 0.77f, 1f, EditorGUIUtility.isProSkin ? 1f : 0.7f);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
GUI.color = Color.white;
|
|
DisplaySupportInformation();
|
|
EditorGUILayout.EndVertical();
|
|
|
|
//Export Sprite Feature:
|
|
GUI.color = new Color(0.9f, 0.7f, 1f, EditorGUIUtility.isProSkin ? 1f : 0.7f);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
GUI.color = new Color(0.95f, 0.85f, 1, 1f);
|
|
if (GUILayout.Button("<b>Bake Shader</b> to Texture and <b>Export</b>", buttonStyle))
|
|
{
|
|
ExportSprite(materialEditor, bakeStackAmount);
|
|
}
|
|
bakeStackAmount = Mathf.Clamp(EditorGUILayout.IntField("Stack Amount", bakeStackAmount), 1, 20);
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField("- Use a <b>stack amount</b> of <b>10</b> for smooth <b>gaussian blur</b>.", labelStyle);
|
|
GUI.color = Color.white;
|
|
EditorGUILayout.EndVertical();
|
|
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
void StartWarning(bool isLight = false)
|
|
{
|
|
wasWarned = true;
|
|
GUI.color = isLight ? lightWarnColor : warnColor;
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
}
|
|
|
|
void AdditionalMaterialProperties(MaterialEditor materialEditor)
|
|
{
|
|
if (UnityEngine.Rendering.SupportedRenderingFeatures.active.editableMaterialRenderQueue)
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
|
|
materialEditor.RenderQueueField();
|
|
}
|
|
}
|
|
|
|
void DrawShaderCategory(string title)
|
|
{
|
|
newCategory = true;
|
|
isHidden = false;
|
|
|
|
EditorGUILayout.EndVertical();
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.BeginVertical("Helpbox");
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.9f);
|
|
GUILayout.Label("<b><size=14>" + title + "</size></b>", labelStyle);
|
|
Lines();
|
|
}
|
|
void DrawShaderCategory(string title, ref bool toggleVariable)
|
|
{
|
|
newCategory = true;
|
|
isHidden = false;
|
|
EditorGUILayout.EndVertical();
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.BeginVertical("Helpbox");
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.9f);
|
|
GUILayout.Label("<b><size=14>" + title + "</size></b>", labelStyle);
|
|
|
|
//Toggle:
|
|
Rect buttonRect = GUILayoutUtility.GetLastRect();
|
|
buttonRect.x += buttonRect.width - 20;
|
|
buttonRect.width = 20;
|
|
|
|
if(GUI.Button(buttonRect, !toggleVariable ? "<size=12>▶</size>" : "<size=10>▼</size>", buttonStyle))
|
|
{
|
|
toggleVariable = !toggleVariable;
|
|
}
|
|
|
|
if(toggleVariable)
|
|
{
|
|
Lines();
|
|
}
|
|
else
|
|
{
|
|
isHidden = true;
|
|
}
|
|
}
|
|
|
|
void DisplayHint(string text)
|
|
{
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField(text, labelStyle);
|
|
GUI.color = Color.white;
|
|
}
|
|
void DisplaySpaceHint()
|
|
{
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField("- Uses <b>" + spaceName + " Space</b> as configured above.", labelStyle);
|
|
GUI.color = Color.white;
|
|
}
|
|
|
|
bool DrawShaderToggle(MaterialEditor materialEditor, MaterialProperty prop)
|
|
{
|
|
newCategory = true;
|
|
isHidden = false;
|
|
EditorGUILayout.EndVertical();
|
|
|
|
switch (prop.name)
|
|
{
|
|
case ("_EnableStrongTint"):
|
|
ShaderTitle("Color");
|
|
break;
|
|
case ("_EnableHologram"):
|
|
ShaderTitle("Effect");
|
|
break;
|
|
case ("_EnableFullAlphaDissolve"):
|
|
ShaderTitle("Fading");
|
|
break;
|
|
case ("_EnablePixelate"):
|
|
ShaderTitle("Transformation");
|
|
break;
|
|
case ("_EnableWind"):
|
|
ShaderTitle("Interactive");
|
|
break;
|
|
case ("_EnableCheckerboard"):
|
|
ShaderTitle("Other");
|
|
break;
|
|
}
|
|
|
|
shaderAmount++;
|
|
|
|
bool isEnabled = prop.floatValue > 0.5f;
|
|
bool isCollapsed = prop.floatValue == 1.1f;
|
|
|
|
//Box:
|
|
Color color = Color.HSVToRGB((currentBoxColor * 0.05f) % 1, isEnabled ? 0.7f : 0.2f + (EditorGUIUtility.isProSkin ? 0.4f : 0), EditorGUIUtility.isProSkin ? (isEnabled ? 1.8f : 1f) : 1);
|
|
color.a = isEnabled ? 1f : 0.7f;
|
|
GUI.color = color;
|
|
currentBoxColor++;
|
|
EditorGUILayout.BeginVertical("Helpbox");
|
|
|
|
string shaderName = prop.displayName.Replace("Enable ", "");
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.5f);
|
|
GUILayout.Label(shaderAmount + ".", GUILayout.Width(24f));
|
|
GUI.color = new Color(1, 1, 1, isEnabled ? 0.9f : 0.7f);
|
|
GUILayout.Label("<b><size=14>" + shaderName + "</size></b>", labelStyle);
|
|
|
|
//Track:
|
|
if (isEnabled)
|
|
{
|
|
enabledShaders.Add(shaderName);
|
|
}
|
|
|
|
Rect toggleRect = GUILayoutUtility.GetLastRect();
|
|
|
|
//Enabled:
|
|
currentHint = null;
|
|
if (isEnabled)
|
|
{
|
|
enabledAmount++;
|
|
|
|
string resourcePath = "SSU/Hints/" + shaderName;
|
|
if (allHints.ContainsKey(resourcePath))
|
|
{
|
|
currentHint = allHints[resourcePath];
|
|
}
|
|
else
|
|
{
|
|
currentHint = Resources.Load<ShaderHintSSU>(resourcePath);
|
|
|
|
if (currentHint != null)
|
|
{
|
|
allHints.Add(resourcePath, currentHint);
|
|
}
|
|
}
|
|
|
|
DrawShadow("<b><size=14>" + shaderName + "</size></b>");
|
|
}
|
|
|
|
toggleRect.x += toggleRect.width -= 37;
|
|
toggleRect.width = 37;
|
|
|
|
materialEditor.ShaderProperty(toggleRect, prop, GUIContent.none);
|
|
|
|
if (isEnabled)
|
|
{
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.x += lastRect.width - 20;
|
|
lastRect.width = 20;
|
|
|
|
if (GUI.Button(lastRect, isCollapsed ? "<size=12>▶</size>" : "<size=10>▼</size>", buttonStyle))
|
|
{
|
|
isCollapsed = !isCollapsed;
|
|
|
|
if (isCollapsed)
|
|
{
|
|
prop.floatValue = 1.1f;
|
|
}
|
|
else
|
|
{
|
|
prop.floatValue = 1f;
|
|
}
|
|
}
|
|
|
|
if (currentHint != null)
|
|
{
|
|
if (currentHint.requiresFullRectMesh)
|
|
{
|
|
requiresFullRectMesh = true;
|
|
}
|
|
if (currentHint.requiresSpriteSheetFix)
|
|
{
|
|
requiresSpriteSheetFix = true;
|
|
}
|
|
if (currentHint.requiresTiling)
|
|
{
|
|
requiresTiling = true;
|
|
}
|
|
if (currentHint.requiresInstancing)
|
|
{
|
|
requiresInstancing = true;
|
|
}
|
|
if (currentHint.benchmarkValue > 0)
|
|
{
|
|
performanceBenchmark += currentHint.benchmarkValue;
|
|
}
|
|
if (currentHint.textureSamples > 0)
|
|
{
|
|
textureAmount += currentHint.textureSamples;
|
|
}
|
|
if (currentHint.textureToggle != "" && currentHint.textureToggle != null && materials[0].GetFloat(currentHint.textureToggle) > 0.5f)
|
|
{
|
|
textureAmount++;
|
|
}
|
|
if (currentHint.textureToggleExtra != "" && currentHint.textureToggleExtra != null && materials[0].GetFloat(currentHint.textureToggleExtra) > 0.5f)
|
|
{
|
|
textureAmount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
GUI.color = Color.white;
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (isEnabled && !isCollapsed)
|
|
{
|
|
if (currentHint != null && currentHint.shaderDescription != null && currentHint.shaderDescription != "")
|
|
{
|
|
string[] descriptionLines = currentHint.shaderDescription.Split('\n');
|
|
for (int d = 0; d < descriptionLines.Length; d++)
|
|
{
|
|
DisplayHint(descriptionLines[d]);
|
|
}
|
|
|
|
string performanceText = "Relatively Lower";
|
|
if (currentHint.benchmarkValue > 600)
|
|
{
|
|
performanceText = currentHint.benchmarkValue < 1700 ? "Average" : "Relatively Higher";
|
|
}
|
|
|
|
DisplayHint("- GPU Usage: <b>" + performanceText + "</b>");
|
|
}
|
|
|
|
if (prop.name == "_EnableSmoothPixelArt")
|
|
{
|
|
Texture activeTexture = GetTexture(materialEditor);
|
|
TextureImporter textureImporter = GetTextureImporter(activeTexture);
|
|
|
|
if (textureImporter != null)
|
|
{
|
|
if (textureImporter.filterMode == FilterMode.Point)
|
|
{
|
|
GUI.color = warnColor;
|
|
if (GUILayout.Button("Set <b>" + activeTexture.name + "'s</b> filter mode to <b>Bilinear</b>", buttonStyle))
|
|
{
|
|
TextureImporterSettings textureSettings = new TextureImporterSettings();
|
|
textureImporter.ReadTextureSettings(textureSettings);
|
|
|
|
textureSettings.filterMode = FilterMode.Bilinear;
|
|
|
|
Undo.RecordObject(textureImporter, "Changed Filter Mode");
|
|
|
|
textureImporter.SetTextureSettings(textureSettings);
|
|
textureImporter.SaveAndReimport();
|
|
}
|
|
GUI.color = Color.white;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Lines();
|
|
|
|
/*if (prop.name == "_EnableRecolorPalette")
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Generate Source"))
|
|
{
|
|
Texture activeTexture = GetTexture(materialEditor);
|
|
|
|
if (activeTexture != null)
|
|
{
|
|
//Blit to Render Texture:
|
|
RenderTexture rt = new RenderTexture(activeTexture.width, activeTexture.height, 0, RenderTextureFormat.ARGB32);
|
|
Graphics.Blit(activeTexture, rt);
|
|
|
|
//Read RenderTexture to Texture:
|
|
Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
|
|
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
|
tex.Apply();
|
|
|
|
//Get Colors:
|
|
Dictionary<Vector3, float> colorWeights = new Dictionary<Vector3, float>();
|
|
for (int x = 0; x < tex.width; x++)
|
|
{
|
|
for (int y = 0; y < tex.height; y++)
|
|
{
|
|
Color pixel = paletteBilinear ? tex.GetPixelBilinear((float)x / (float)tex.width, (float)y / (float)tex.height) : tex.GetPixel(x, y);
|
|
Vector3 colorKey = new Vector3(pixel.r, pixel.g, pixel.b);
|
|
|
|
if (colorWeights.ContainsKey(colorKey))
|
|
{
|
|
colorWeights[colorKey] += pixel.a;
|
|
}
|
|
else
|
|
{
|
|
colorWeights.Add(colorKey, pixel.a);
|
|
}
|
|
}
|
|
|
|
EditorUtility.DisplayProgressBar("Generating Palette Texture", "Loading Pixels", 0f);
|
|
}
|
|
|
|
//Get Top Colors:
|
|
List<Vector3> paletteColors = new List<Vector3>();
|
|
Dictionary<Vector3, int> colorDictionary = new Dictionary<Vector3, int>(); ;
|
|
int totalColors = paletteSize * paletteSize;
|
|
if(colorWeights.Count > totalColors)
|
|
{
|
|
while (paletteColors.Count < totalColors && colorWeights.Count > 0)
|
|
{
|
|
float highestValue = 0;
|
|
Vector3 highestColor = Vector3.zero;
|
|
foreach (KeyValuePair<Vector3, float> colorWeight in colorWeights)
|
|
{
|
|
if (highestValue < colorWeight.Value)
|
|
{
|
|
highestValue = colorWeight.Value;
|
|
highestColor = colorWeight.Key;
|
|
}
|
|
}
|
|
paletteColors.Add(highestColor);
|
|
colorDictionary.Add(highestColor, paletteColors.Count - 1);
|
|
colorWeights.Remove(highestColor);
|
|
EditorUtility.DisplayProgressBar("Generating Palette Texture", "Sorting colors.", 0.2f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (KeyValuePair<Vector3, float> colorWeight in colorWeights)
|
|
{
|
|
paletteColors.Add(colorWeight.Key);
|
|
colorDictionary.Add(colorWeight.Key, paletteColors.Count - 1);
|
|
}
|
|
}
|
|
|
|
|
|
/*Sort Top Colors:
|
|
List<Vector3> sortedColors = new List<Vector3>();
|
|
sortedColors.Add(topColors[0]);
|
|
topColors.RemoveAt(0);
|
|
while (topColors.Count > 0)
|
|
{
|
|
float closestDistance = 100f;
|
|
int closestIndex = -1;
|
|
for (int c = 0; c < topColors.Count; c++)
|
|
{
|
|
float distance = (sortedColors[sortedColors.Count - 1] - topColors[c]).sqrMagnitude;
|
|
|
|
if (distance < closestDistance)
|
|
{
|
|
closestDistance = distance;
|
|
closestIndex = c;
|
|
}
|
|
}
|
|
|
|
sortedColors.Add(topColors[closestIndex]);
|
|
topColors.RemoveAt(closestIndex);
|
|
EditorUtility.DisplayProgressBar("Generating Palette Texture", "Sorting color palette.", 0.5f);
|
|
}
|
|
|
|
//Creating Texture:
|
|
for (int x = 0; x < tex.width; x++)
|
|
{
|
|
for (int y = 0; y < tex.height; y++)
|
|
{
|
|
Color pixel = paletteBilinear ? tex.GetPixelBilinear((float)x / (float)tex.width, (float)y / (float)tex.height) : tex.GetPixel(x, y);
|
|
Vector3 colorKey = new Vector3(pixel.r, pixel.g, pixel.b);
|
|
|
|
int colorIndex = 0;
|
|
|
|
if (colorDictionary.ContainsKey(colorKey))
|
|
{
|
|
colorIndex = colorDictionary[colorKey];
|
|
}
|
|
else
|
|
{
|
|
float closestDistance = 100f;
|
|
for (int c = 0; c < paletteColors.Count; c++)
|
|
{
|
|
float distance = (paletteColors[c] - colorKey).sqrMagnitude;
|
|
|
|
if (distance < closestDistance)
|
|
{
|
|
closestDistance = distance;
|
|
colorIndex = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
float rValue = (float) (colorIndex % paletteSize) / paletteSize;
|
|
float gValue = Mathf.Floor(colorIndex / paletteSize) / paletteSize;
|
|
tex.SetPixel(x, y, new Color(rValue, gValue, 0, 1));
|
|
}
|
|
|
|
EditorUtility.DisplayProgressBar("Generating Palette Texture", "Mapping colors.", 0.8f);
|
|
}
|
|
|
|
//Export:
|
|
EditorUtility.ClearProgressBar();
|
|
string oldPath = AssetDatabase.GetAssetPath(activeTexture);
|
|
if (oldPath == "")
|
|
{
|
|
oldPath = Application.dataPath + "/";
|
|
}
|
|
|
|
string[] fileEnding = oldPath.Split('.');
|
|
string newPath = oldPath.Replace("." + fileEnding[fileEnding.Length - 1], "");
|
|
string folderPath = "";
|
|
string[] folders = oldPath.Split('/');
|
|
for (int n = 0; n < folders.Length - 1; n++)
|
|
{
|
|
folderPath += folders[n] + "/";
|
|
}
|
|
string fileName = activeTexture.name;
|
|
newPath = EditorUtility.SaveFilePanel("Save Texture", folderPath, activeTexture.name + " (Source)", "png");
|
|
|
|
if (newPath != "")
|
|
{
|
|
newPath = newPath.Substring(Application.dataPath.Length - 9);
|
|
while (newPath.Length > 1 && newPath.StartsWith("Assets") == false)
|
|
{
|
|
newPath = newPath.Substring(1);
|
|
}
|
|
|
|
//Save Texture:
|
|
byte[] bytes = tex.EncodeToPNG();
|
|
bool newFile = AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)) == null;
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.CopyAsset(oldPath, newPath);
|
|
}
|
|
System.IO.File.WriteAllBytes(newPath, bytes);
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.ImportAsset(newPath);
|
|
}
|
|
|
|
//Import new Texture:
|
|
AssetDatabase.Refresh();
|
|
|
|
//Ping:
|
|
EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)));
|
|
}
|
|
|
|
//Clear:
|
|
if (RenderTexture.active == rt)
|
|
{
|
|
RenderTexture.active = null;
|
|
}
|
|
Object.DestroyImmediate(rt);
|
|
Object.DestroyImmediate(tex);
|
|
}
|
|
else
|
|
{
|
|
EditorUtility.DisplayDialog("No texture found.", "Select a SpriteRenderer or Image with this material.\nOr assign a texture to this material.", "Alright");
|
|
}
|
|
}
|
|
if (GUILayout.Button("Generate Palette"))
|
|
{
|
|
Texture activeTexture = GetTexture(materialEditor);
|
|
|
|
if (activeTexture != null)
|
|
{
|
|
//Open Source:
|
|
string currentFile = AssetDatabase.GetAssetPath(activeTexture);
|
|
string[] splitPath = currentFile.Split('/');
|
|
string openPath = EditorUtility.OpenFilePanel("Open Source Texture", currentFile.Substring(0, currentFile.Length - splitPath[splitPath.Length - 1].Length), "png");
|
|
string[] openPathSplit = openPath.Split('/');
|
|
openPath = "";
|
|
|
|
bool ignore = true;
|
|
for(int i = 0; i < openPathSplit.Length; i++)
|
|
{
|
|
if(openPathSplit[i] == "Assets")
|
|
{
|
|
ignore = false;
|
|
}
|
|
|
|
if(!ignore)
|
|
{
|
|
openPath += openPathSplit[i] + (i == openPathSplit.Length - 1 ? "" : "/");
|
|
}
|
|
}
|
|
|
|
|
|
Texture sourceTexture = AssetDatabase.LoadAssetAtPath<Texture>(openPath);
|
|
|
|
//Source Texture:
|
|
if (sourceTexture != null)
|
|
{
|
|
RenderTexture sourceRT = new RenderTexture(sourceTexture.width, sourceTexture.height, 0, RenderTextureFormat.ARGB32);
|
|
Graphics.Blit(sourceTexture, sourceRT);
|
|
Texture2D sourceTex = new Texture2D(sourceRT.width, sourceRT.height, TextureFormat.ARGB32, false);
|
|
sourceTex.ReadPixels(new Rect(0, 0, sourceRT.width, sourceRT.height), 0, 0);
|
|
sourceTex.Apply();
|
|
|
|
//Recolor Texture
|
|
RenderTexture rt = new RenderTexture(activeTexture.width, activeTexture.height, 0, RenderTextureFormat.ARGB32);
|
|
Graphics.Blit(activeTexture, rt);
|
|
Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
|
|
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
|
tex.Apply();
|
|
|
|
//Creating Palette:
|
|
Texture2D paletteTex = new Texture2D(paletteSize, paletteSize);
|
|
for (int x = 0; x < tex.width; x++)
|
|
{
|
|
for (int y = 0; y < tex.height; y++)
|
|
{
|
|
Color pixel = paletteBilinear ? tex.GetPixelBilinear((float)x / (float)tex.width, (float)y / (float)tex.height) : tex.GetPixel(x, y);
|
|
Color pixelSource = paletteBilinear ? sourceTex.GetPixelBilinear((float)x / (float)tex.width, (float)y / (float)tex.height) : tex.GetPixel(x, y);
|
|
paletteTex.SetPixel(Mathf.RoundToInt(pixelSource.r * paletteSize), Mathf.RoundToInt(pixelSource.g * paletteSize), pixel);
|
|
}
|
|
EditorUtility.DisplayProgressBar("Generating Palette Texture", "Saving Pixels", 0f);
|
|
}
|
|
paletteTex.Apply();
|
|
|
|
//Export:
|
|
EditorUtility.ClearProgressBar();
|
|
string oldPath = AssetDatabase.GetAssetPath(activeTexture);
|
|
if (oldPath == "")
|
|
{
|
|
oldPath = Application.dataPath + "/";
|
|
}
|
|
|
|
string[] fileEnding = oldPath.Split('.');
|
|
string newPath = oldPath.Replace("." + fileEnding[fileEnding.Length - 1], "");
|
|
string folderPath = "";
|
|
string[] folders = oldPath.Split('/');
|
|
for (int n = 0; n < folders.Length - 1; n++)
|
|
{
|
|
folderPath += folders[n] + "/";
|
|
}
|
|
string fileName = activeTexture.name;
|
|
newPath = EditorUtility.SaveFilePanel("Save Texture", folderPath, activeTexture.name + " (Source)", "png");
|
|
if (newPath != "")
|
|
{
|
|
newPath = newPath.Substring(Application.dataPath.Length - 9);
|
|
while (newPath.Length > 1 && newPath.StartsWith("Assets") == false)
|
|
{
|
|
newPath = newPath.Substring(1);
|
|
}
|
|
|
|
//Save Texture:
|
|
byte[] bytes = paletteTex.EncodeToPNG();
|
|
bool newFile = AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)) == null;
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.CopyAsset(oldPath, newPath);
|
|
}
|
|
System.IO.File.WriteAllBytes(newPath, bytes);
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.ImportAsset(newPath);
|
|
}
|
|
|
|
//Import new Texture:
|
|
AssetDatabase.Refresh();
|
|
|
|
//Ping:
|
|
EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)));
|
|
}
|
|
|
|
//Clear:
|
|
if (RenderTexture.active == rt || RenderTexture.active == sourceRT)
|
|
{
|
|
RenderTexture.active = null;
|
|
}
|
|
Object.DestroyImmediate(rt);
|
|
Object.DestroyImmediate(tex);
|
|
Object.DestroyImmediate(sourceRT);
|
|
Object.DestroyImmediate(sourceTex);
|
|
Object.DestroyImmediate(paletteTex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorUtility.DisplayDialog("No texture found.", "Select a SpriteRenderer or Image with this material.\nOr assign a texture to this material.", "Alright");
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
paletteSize = EditorGUILayout.IntField("Palette Colors", paletteSize);
|
|
paletteBilinear = EditorGUILayout.Toggle("Bilinear Filter", paletteBilinear);
|
|
GUI.color = hintColor;
|
|
EditorGUILayout.LabelField("- Use these to easily generate palette textures.", labelStyle);
|
|
Lines();
|
|
}*/
|
|
}
|
|
}
|
|
|
|
return !isEnabled || isCollapsed;
|
|
}
|
|
|
|
static Texture GetTexture(MaterialEditor materialEditor)
|
|
{
|
|
Texture activeTexture = null;
|
|
if (Selection.activeGameObject != null)
|
|
{
|
|
SpriteRenderer spriteRenderer = Selection.activeGameObject.GetComponent<SpriteRenderer>();
|
|
|
|
if (spriteRenderer != null)
|
|
{
|
|
if(spriteRenderer.sprite != null)
|
|
{
|
|
activeTexture = spriteRenderer.sprite.texture;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Image image = Selection.activeGameObject.GetComponent<Image>();
|
|
|
|
if (image != null && image.sprite != null)
|
|
{
|
|
activeTexture = image.sprite.texture;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach(Material mat in materials)
|
|
{
|
|
if (mat != null)
|
|
{
|
|
activeTexture = mat.GetTexture("_MainTex");
|
|
|
|
if(activeTexture != null)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return activeTexture;
|
|
}
|
|
public static TextureImporter GetTextureImporter(Texture activeTexture)
|
|
{
|
|
try
|
|
{
|
|
if (activeTexture != null)
|
|
{
|
|
string path = AssetDatabase.GetAssetPath(activeTexture);
|
|
|
|
if (path != null)
|
|
{
|
|
TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(path);
|
|
return textureImporter;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
Sprite GetSprite()
|
|
{
|
|
if (Selection.activeGameObject != null)
|
|
{
|
|
SpriteRenderer spriteRenderer = Selection.activeGameObject.GetComponent<SpriteRenderer>();
|
|
|
|
if (spriteRenderer != null)
|
|
{
|
|
return spriteRenderer.sprite;
|
|
}
|
|
else
|
|
{
|
|
Image image = Selection.activeGameObject.GetComponent<Image>();
|
|
|
|
if (image != null)
|
|
{
|
|
return image.sprite;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
void DrawShadow(string textContent)
|
|
{
|
|
for (int x = -1; x <= 1; x += 2)
|
|
{
|
|
for (int y = -1; y <= 1; y += 2)
|
|
{
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.x += x;
|
|
lastRect.y += y;
|
|
GUI.color = new Color(1, 1, 1, 0.12f);
|
|
EditorGUI.LabelField(lastRect, new GUIContent(textContent), labelStyle);
|
|
}
|
|
}
|
|
GUI.color = Color.white;
|
|
}
|
|
|
|
void ShaderTitle(string title)
|
|
{
|
|
if(title != "Close")
|
|
{
|
|
if(title != "Color")
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.Space();
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.55f);
|
|
EditorGUILayout.LabelField("<size=18><b>" + title + "</b></size>", labelStyle, GUILayout.Height(22));
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.1f);
|
|
for (int x = -1; x <= 1; x += 2)
|
|
{
|
|
for (int y = -1; y <= 1; y += 2)
|
|
{
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.y += x;
|
|
lastRect.x += y;
|
|
EditorGUI.LabelField(lastRect, "<size=18><b>" + title + "</b></size>", labelStyle);
|
|
}
|
|
}
|
|
GUI.color = Color.white;
|
|
}
|
|
|
|
float currentHeight = (title != "Close") ? GUILayoutUtility.GetLastRect().y : GUILayoutUtility.GetLastRect().y + 59;
|
|
|
|
if (title == "Color")
|
|
{
|
|
shaderAmount = enabledAmount = currentBoxColor = 0;
|
|
performanceBenchmark = 0f;
|
|
textureAmount = 1;
|
|
}
|
|
else
|
|
{
|
|
Rect lineRect = GUILayoutUtility.GetLastRect();
|
|
lineRect.x -= 8;
|
|
lineRect.width = 2;
|
|
lineRect.y = lastTitleHeight + 4;
|
|
lineRect.height = currentHeight - lastTitleHeight - 32;
|
|
|
|
if(EditorGUIUtility.isProSkin)
|
|
{
|
|
GUI.color = new Color(1, 1, 1, 0.5f);
|
|
lineRect.x -= 3;
|
|
GUI.Box(lineRect, GUIContent.none, GUI.skin.verticalSlider);
|
|
lineRect.x -= 1;
|
|
GUI.Box(lineRect, GUIContent.none, GUI.skin.verticalSlider);
|
|
}
|
|
else
|
|
{
|
|
GUI.color = new Color(0, 0, 0, 0.3f);
|
|
GUI.Box(lineRect, GUIContent.none);
|
|
lineRect.x += 1;
|
|
GUI.Box(lineRect, GUIContent.none);
|
|
GUI.color = Color.white;
|
|
}
|
|
}
|
|
|
|
lastTitleHeight = currentHeight;
|
|
EditorGUILayout.Space();
|
|
}
|
|
|
|
void ResetButton(MaterialProperty prop)
|
|
{
|
|
GUIContent resetButton = new GUIContent();
|
|
resetButton.text = "R";
|
|
resetButton.tooltip = "Resets this property.";
|
|
|
|
if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Color)
|
|
{
|
|
Color defaultValue = defaultMaterial.GetColor(prop.name);
|
|
|
|
if (prop.colorValue == defaultValue)
|
|
{
|
|
GUI.enabled = false;
|
|
}
|
|
|
|
if (GUILayout.Button(resetButton, GUILayout.Width(20)))
|
|
{
|
|
prop.colorValue = defaultValue;
|
|
}
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Vector)
|
|
{
|
|
Vector4 defaultValue = defaultMaterial.GetVector(prop.name);
|
|
|
|
if (prop.vectorValue == defaultValue)
|
|
{
|
|
GUI.enabled = false;
|
|
}
|
|
|
|
if (GUILayout.Button(resetButton, GUILayout.Width(20)))
|
|
{
|
|
prop.vectorValue = defaultValue;
|
|
}
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Float || prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Range)
|
|
{
|
|
float defaultValue = defaultMaterial.GetFloat(prop.name);
|
|
|
|
if (prop.floatValue == defaultValue)
|
|
{
|
|
GUI.enabled = false;
|
|
}
|
|
|
|
if (GUILayout.Button(resetButton, GUILayout.Width(20)))
|
|
{
|
|
prop.floatValue = defaultValue;
|
|
}
|
|
}
|
|
else if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture)
|
|
{
|
|
Texture defaultValue = defaultMaterial.GetTexture(prop.name);
|
|
|
|
if (prop.textureValue == defaultValue)
|
|
{
|
|
GUI.enabled = false;
|
|
}
|
|
|
|
if (GUILayout.Button(resetButton, GUILayout.Width(20), GUILayout.Height(50)))
|
|
{
|
|
prop.textureValue = defaultValue;
|
|
}
|
|
}
|
|
|
|
GUI.enabled = true;
|
|
}
|
|
|
|
void HelpButton(MaterialProperty prop, GUIContent displayContent)
|
|
{
|
|
GUIContent infoButton = new GUIContent();
|
|
infoButton.text = "<size=1> </size>C<size=10>#</size>";
|
|
infoButton.tooltip = "Useful information for programmers.";
|
|
|
|
if (GUILayout.Button(infoButton, buttonStyle, GUILayout.Width(26), GUILayout.Height((prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture) ? 50 : 20)))
|
|
{
|
|
CodingHelper.Open(displayContent, prop, shader, EditorGUIUtility.currentViewWidth);
|
|
}
|
|
}
|
|
|
|
Rect PropertyLabel(GUIContent labelContent)
|
|
{
|
|
EditorGUILayout.LabelField(" ");
|
|
|
|
Rect labelRect = GUILayoutUtility.GetLastRect();
|
|
Rect fieldRect = new Rect(labelRect);
|
|
|
|
if (labelRect.width > 320)
|
|
{
|
|
labelRect.width -= 160;
|
|
}
|
|
else
|
|
{
|
|
labelRect.width = labelRect.width / 2;
|
|
}
|
|
|
|
fieldRect.width -= labelRect.width;
|
|
fieldRect.x += labelRect.width;
|
|
|
|
EditorGUI.PrefixLabel(labelRect, labelContent);
|
|
|
|
return fieldRect;
|
|
}
|
|
Rect GetPropertySize(MaterialProperty prop, bool isKeyword)
|
|
{
|
|
EditorGUILayout.LabelField(" ");
|
|
|
|
Rect fullRect = GUILayoutUtility.GetLastRect();
|
|
Rect labelRect = new Rect(fullRect);
|
|
Rect fieldRect = new Rect(labelRect);
|
|
|
|
if (labelRect.width > 320)
|
|
{
|
|
labelRect.width -= 160;
|
|
}
|
|
else
|
|
{
|
|
labelRect.width = labelRect.width / 2;
|
|
}
|
|
|
|
if(isKeyword) {
|
|
labelRect.width -= 52;
|
|
}
|
|
|
|
fieldRect.width -= labelRect.width;
|
|
fieldRect.x += labelRect.width;
|
|
|
|
EditorGUIUtility.fieldWidth = fieldRect.width;
|
|
EditorGUIUtility.labelWidth = labelRect.width;
|
|
|
|
if (prop.propertyType == UnityEngine.Rendering.ShaderPropertyType.Range)
|
|
{
|
|
EditorGUIUtility.fieldWidth = 50;
|
|
EditorGUIUtility.labelWidth = labelRect.width;
|
|
}
|
|
|
|
return fullRect;
|
|
}
|
|
|
|
bool IsKeyword(MaterialProperty prop)
|
|
{
|
|
return IsKeyword(prop.name);
|
|
}
|
|
|
|
public static bool IsKeyword(string propertyName)
|
|
{
|
|
if (propertyName.StartsWith("_Toggle") || propertyName.EndsWith("Toggle") || propertyName.EndsWith("Invert") || propertyName == "PixelSnap" || propertyName == "_ShaderSpace" || propertyName == "_ShaderFading" || propertyName == "_BakedMaterial" || propertyName == "_SmokeVertexSeed" || propertyName == "_SpriteSheetFix" || propertyName == "_UseUIAlphaClip" || propertyName == "_IsText" || propertyName == "_IsTextMeshPro" || propertyName == "_TilingFix" || propertyName == "_ForceAlpha" || propertyName == "_VertexTintFirst" || propertyName == "_PixelPerfectSpace" || propertyName == "_PixelPerfectUV" || propertyName == "_WindLocalWind" || propertyName == "_WindHighQualityNoise" || propertyName == "_WindIsParallax" || propertyName == "_WindFlip" || propertyName == "_SquishFlip")
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void Lines()
|
|
{
|
|
GUI.color = new Color(1, 1, 1, 0.5f);
|
|
EditorGUILayout.LabelField("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ", GUILayout.Height(9));
|
|
GUI.color = new Color(1, 1, 1, 1);
|
|
}
|
|
|
|
public static void DisplaySupportInformation()
|
|
{
|
|
GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
|
|
labelStyle.richText = true;
|
|
|
|
GUIStyle linkStyle = new GUIStyle(GUI.skin.label);
|
|
linkStyle.richText = true;
|
|
linkStyle.alignment = TextAnchor.MiddleLeft;
|
|
linkStyle.normal.textColor = linkStyle.focused.textColor = linkStyle.hover.textColor = EditorGUIUtility.isProSkin ? new Color(0.8f, 0.9f, 1f, 1) : new Color(0.1f, 0.2f, 0.4f, 1);
|
|
linkStyle.active.textColor = EditorGUIUtility.isProSkin ? new Color(0.6f, 0.8f, 1f, 1) : new Color(0.15f, 0.4f, 0.6f, 1);
|
|
|
|
DisplayLink("Documentation", "https://ekincantas.com/sprite-shaders-ultimate/", "https://ekincantas.com/sprite-shaders-ultimate/", labelStyle, linkStyle);
|
|
DisplayLink("Discord", "https://discord.gg/nWbRkN8Zxr", "https://discord.gg/nWbRkN8Zxr", labelStyle, linkStyle);
|
|
DisplayLink("Email", "ekincantascontact@gmail.com", "", labelStyle, linkStyle);
|
|
}
|
|
|
|
private static void DisplayLink(string title, string link, string url, GUIStyle labelStyle, GUIStyle linkStyle)
|
|
{
|
|
GUI.color = new Color(1, 1, 1, 0.7f);
|
|
EditorGUILayout.BeginHorizontal();
|
|
GUILayout.Label("<b>" + title + ": </b>", labelStyle);
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
lastRect.x += 100;
|
|
lastRect.width -= 100;
|
|
|
|
GUI.color = Color.white;
|
|
|
|
if (url == "")
|
|
{
|
|
EditorGUI.SelectableLabel(lastRect, link, linkStyle);
|
|
}
|
|
else
|
|
{
|
|
if(GUI.Button(lastRect,link, linkStyle))
|
|
{
|
|
Application.OpenURL(url);
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
public static void ExportSprite(MaterialEditor materialEditor, int count = 1)
|
|
{
|
|
Material material = (Material)materialEditor.target;
|
|
Texture texture = GetTexture(materialEditor);
|
|
|
|
if (material != null && texture != null)
|
|
{
|
|
SaveShadedTexture(material, texture, count);
|
|
}
|
|
else
|
|
{
|
|
EditorUtility.DisplayDialog("No texture found.", "Select a SpriteRenderer or Image with this material.\nOr assign a texture to this material.", "Alright");
|
|
}
|
|
}
|
|
public static void SaveShadedTexture(Material spriteMaterial, Texture spriteTexture, int count = 1)
|
|
{
|
|
//Enable Baked Material:
|
|
Undo.RecordObject(spriteMaterial, "Switched baked material setting.");
|
|
Shader previousShader = spriteMaterial.shader;
|
|
spriteMaterial.shader = Shader.Find("Sprite Shaders Ultimate/Standard SSU");
|
|
spriteMaterial.EnableKeyword("_BAKEDMATERIAL_ON");
|
|
spriteMaterial.SetFloat("_BakedMaterial", 1f);
|
|
|
|
Texture2D tex = (Texture2D) spriteTexture;
|
|
bool first = true;
|
|
for (int n = 0; n < count; n++)
|
|
{
|
|
//Blit to Render Texture:
|
|
RenderTexture rt = new RenderTexture(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
|
|
Graphics.Blit(tex, rt, spriteMaterial);
|
|
|
|
//Destroy Previous Texture:
|
|
if (!first)
|
|
{
|
|
Object.DestroyImmediate(tex);
|
|
}
|
|
first = false;
|
|
|
|
//Read RenderTexture to Texture:
|
|
tex = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
|
|
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
|
tex.Apply();
|
|
|
|
//Clear RenderTexture:
|
|
if (RenderTexture.active == rt)
|
|
{
|
|
RenderTexture.active = null;
|
|
}
|
|
Object.DestroyImmediate(rt);
|
|
}
|
|
|
|
//Disable Baked Material:
|
|
spriteMaterial.DisableKeyword("_BAKEDMATERIAL_ON");
|
|
spriteMaterial.SetFloat("_BakedMaterial", 0f);
|
|
spriteMaterial.shader = previousShader;
|
|
|
|
//Get Paths:
|
|
string oldPath = AssetDatabase.GetAssetPath(spriteTexture);
|
|
if (oldPath == "")
|
|
{
|
|
oldPath = Application.dataPath + "/";
|
|
}
|
|
|
|
string[] fileEnding = oldPath.Split('.');
|
|
string newPath = oldPath.Replace("." + fileEnding[fileEnding.Length - 1], "");
|
|
string folderPath = "";
|
|
string[] folders = oldPath.Split('/');
|
|
for (int n = 0; n < folders.Length - 1; n++)
|
|
{
|
|
folderPath += folders[n] + "/";
|
|
}
|
|
string fileName = spriteTexture.name;
|
|
int number = 1;
|
|
while (AssetDatabase.LoadAssetAtPath(newPath + " (Baked " + number + ").png", typeof(Texture)) != null)
|
|
{
|
|
number++;
|
|
}
|
|
|
|
newPath = EditorUtility.SaveFilePanel("Save Texture", folderPath, spriteTexture.name + " (Baked " + number + ")", "png");
|
|
EditorGUILayout.BeginVertical();
|
|
EditorGUILayout.BeginVertical();
|
|
EditorGUILayout.BeginVertical();
|
|
|
|
if (newPath != "")
|
|
{
|
|
newPath = newPath.Substring(Application.dataPath.Length - 9);
|
|
while (newPath.Length > 1 && newPath.StartsWith("Assets") == false)
|
|
{
|
|
newPath = newPath.Substring(1);
|
|
}
|
|
|
|
//Save Texture:
|
|
byte[] bytes = tex.EncodeToPNG();
|
|
bool newFile = AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)) == null;
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.CopyAsset(oldPath, newPath);
|
|
}
|
|
System.IO.File.WriteAllBytes(newPath, bytes);
|
|
if (newFile)
|
|
{
|
|
AssetDatabase.ImportAsset(newPath);
|
|
}
|
|
|
|
//Import new Texture:
|
|
AssetDatabase.Refresh();
|
|
|
|
//Ping:
|
|
EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(newPath, typeof(Texture)));
|
|
}
|
|
|
|
//Clean Up:
|
|
Object.DestroyImmediate(tex);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif |