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 gradientColorKeys = new List(); 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; } } }