Files
2026-02-23 22:01:07 +07:00

332 lines
8.3 KiB
C#

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace AllIn13DShader
{
public class GradientEditorDrawer
{
private const float OFFSET = 5f;
private Gradient gradient;
private Rect lastRect;
private Texture2D previewTex;
private GradientCreatorTool gradientCreatorTool;
private bool createGradientToggle;
private bool textureSaved;
private bool usingPreviewTex;
private bool isModifyingExistingTexture;
private Texture lastSavedTexture;
private Gradient lastGradient;
private GradientTexture gradientTextureAsset;
private void RefreshReferences(Texture lastTexture)
{
if (gradient == null)
{
gradient = new Gradient();
}
if (previewTex == null)
{
previewTex = new Texture2D(128, 128);
}
if (gradientCreatorTool == null)
{
gradientCreatorTool = new GradientCreatorTool();
}
if (lastSavedTexture == null)
{
lastSavedTexture = lastTexture;
}
if (lastGradient == null)
{
lastGradient = new Gradient();
}
}
private Texture RefreshGradientState(Texture texValue)
{
Texture res = texValue;
if (createGradientToggle)
{
lastSavedTexture = texValue;
isModifyingExistingTexture = EditorUtils.IsProjectAsset(lastSavedTexture);
this.gradientTextureAsset = GradientCreatorTool.FindGradientTexureByTex(texValue);
if (this.gradientTextureAsset != null)
{
GradientCreatorTool.CopyGradient(gradientTextureAsset.gradient, gradient);
}
else
{
if (texValue != null)
{
gradient = CreateGradientFromTexture(texValue);
}
else
{
gradient = new Gradient();
}
}
previewTex = gradientCreatorTool.CreateGradientTexture(gradient);
res = previewTex;
}
else
{
GradientCreatorTool.CopyGradient(gradient, lastGradient);
previewTex = null;
res = lastSavedTexture;
}
return res;
}
private Gradient CreateGradientFromTexture(Texture texSource)
{
int width = texSource.width;
int height = texSource.height;
RenderTexture renderTex = RenderTexture.GetTemporary(
width,
height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
Graphics.Blit(texSource, renderTex);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTex;
Texture2D readableText = new Texture2D(texSource.width, texSource.height);
readableText.filterMode = texSource.filterMode;
readableText.wrapMode = texSource.wrapMode;
readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
readableText.Apply();
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTex);
Gradient res = new Gradient();
List<GradientColorKey> gradientColorKeys = new List<GradientColorKey>();
int numSamples = 5;
float step = (((float)width) / numSamples) / width;
Vector2 sampleUV = Vector2.zero;
sampleUV.y = renderTex.height * 0.5f;
for (int i = 0; i < numSamples; i++)
{
Color col = readableText.GetPixelBilinear(sampleUV.x, sampleUV.y);
gradientColorKeys.Add(new GradientColorKey(col, sampleUV.x));
sampleUV.x += step;
}
Color lastCol = readableText.GetPixelBilinear(sampleUV.x, sampleUV.y);
gradientColorKeys.Add(new GradientColorKey(lastCol, sampleUV.x));
res.colorKeys = gradientColorKeys.ToArray();
res.mode = GradientMode.Blend;
return res;
}
public Texture Draw(Rect position, Texture gradientTexture)
{
RefreshReferences(gradientTexture);
lastRect = position;
Texture texValue = gradientTexture;
EditorGUI.BeginChangeCheck();
if (createGradientToggle && texValue == null)
{
texValue = lastSavedTexture;
createGradientToggle = false;
}
texValue = DrawTextureField(texValue, 60f, "Color ramp texture");
bool changes = EditorGUI.EndChangeCheck();
if (changes)
{
createGradientToggle = false;
lastSavedTexture = texValue;
}
EditorGUI.BeginChangeCheck();
DrawCreateGradientToggle(15f, "Create Gradient");
bool createGradientToggleChanged = EditorGUI.EndChangeCheck();
if (createGradientToggleChanged)
{
texValue = RefreshGradientState(texValue);
}
EditorGUI.BeginChangeCheck();
if (createGradientToggle)
{
texValue = DrawGradientField(40f, "Gradient", texValue);
}
EditorGUI.showMixedValue = false;
bool gradientFieldChanged = EditorGUI.EndChangeCheck();
if (gradientFieldChanged && !textureSaved)
{
previewTex = gradientCreatorTool.CreateGradientTexture(TextureSizes._256, FilterMode.Bilinear, gradient);
texValue = previewTex;
usingPreviewTex = true;
}
textureSaved = false;
return texValue;
}
private Texture DrawTextureField(Texture tex, float height, string label)
{
Rect rect = new Rect(lastRect);
rect.height = height;
GUIStyle labelStyle = EditorStyles.label;
labelStyle.alignment = TextAnchor.UpperLeft;
Rect labelRect = new Rect(rect);
labelRect.width = 200f;
EditorGUI.LabelField(labelRect, new GUIContent(label), labelStyle);
GUIStyle textureStyle = EditorStyles.objectField;
textureStyle.alignment = TextAnchor.MiddleLeft;
Rect textureRect = new Rect(rect);
textureRect.width = height;
textureRect.height = height;
textureRect.x = rect.width - textureRect.width - 10f;
Texture res = (Texture)EditorGUI.ObjectField(textureRect, tex, typeof(Texture), false);
lastRect.y += height;
return res;
}
private Texture DrawGradientField(float height, string label, Texture texValue)
{
Texture res = texValue;
Rect rect = new Rect(lastRect);
rect.height = height;
rect.y += height * 0.5f;
float createButtonWidth = 100f;
GUIStyle labelStyle = EditorStyles.label;
labelStyle.alignment = TextAnchor.UpperLeft;
Rect labelRect = new Rect(rect);
labelRect.width = 200f;
EditorGUI.LabelField(labelRect, new GUIContent(label), labelStyle);
GUIStyle textureStyle = EditorStyles.objectField;
textureStyle.alignment = TextAnchor.MiddleLeft;
Rect gradientAndButtonRect = new Rect(rect);
gradientAndButtonRect.width = rect.width - labelRect.width;
gradientAndButtonRect.height = rect.height;
gradientAndButtonRect.x = labelRect.x + labelRect.width;
Rect gradientRect = new Rect(gradientAndButtonRect);
gradientRect.width = gradientAndButtonRect.width * 0.5f;
gradientRect.height = rect.height * 0.5f;
gradientRect.x = rect.x + rect.width - gradientRect.width - (createButtonWidth * 2f) - 10f;
gradient = EditorGUI.GradientField(gradientRect, gradient);
Rect createButtonRect = new Rect(gradientAndButtonRect);
createButtonRect.width = createButtonWidth;
createButtonRect.height = gradientRect.height;
createButtonRect.x = gradientRect.x + gradientRect.width + 10f;
Rect modifyButtonRect = new Rect(createButtonRect);
modifyButtonRect.x = createButtonRect.x + createButtonRect.width + 10f;
if (GUI.Button(createButtonRect, "Save Texture"))
{
res = ChangeTextureOnDisk(true);
}
EditorGUI.BeginDisabledGroup(!isModifyingExistingTexture || gradientTextureAsset == null);
if (GUI.Button(modifyButtonRect, "Overwrite"))
{
res = ChangeTextureOnDisk(false);
}
EditorGUI.EndDisabledGroup();
lastRect.y += height + OFFSET;
if (usingPreviewTex && !textureSaved)
{
Rect helpBoxRect = new Rect(lastRect);
helpBoxRect.height = 40f;
EditorGUI.HelpBox(helpBoxRect, "Texture is not saved! Click on Save Texture to save it", MessageType.Warning);
lastRect.y += helpBoxRect.height + OFFSET;
}
return res;
}
private Texture ChangeTextureOnDisk(bool createNew)
{
gradientCreatorTool.CreateGradientTexture(gradient);
Texture savedTex = gradientCreatorTool.SaveGradientTexture(gradientTextureAsset, createNew);
Texture res = savedTex;
lastSavedTexture = savedTex;
textureSaved = true;
usingPreviewTex = false;
createGradientToggle = false;
gradientTextureAsset = null;
return res;
}
private void DrawCreateGradientToggle(float height, string label)
{
Rect rect = new Rect(lastRect);
rect.height = height;
Rect toggleRect = new Rect(rect);
createGradientToggle = EditorGUI.ToggleLeft(toggleRect, label, createGradientToggle);
lastRect.y += height;
}
public float GetPropertyHeight()
{
float res = 80f;
if (createGradientToggle)
{
res += 45f;
if (usingPreviewTex)
{
res += 40f;
}
}
return res;
}
}
}