306 lines
9.9 KiB
C#
306 lines
9.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace AllIn13DShader
|
|
{
|
|
public class TextureEditorTool
|
|
{
|
|
public Texture2D editorTexInput;
|
|
public Texture2D editorTex;
|
|
public Texture2D cleanEditorTex;
|
|
|
|
public TextureEditorValues values;
|
|
|
|
public void Setup()
|
|
{
|
|
EditorUtils.SetTextureReadWrite(AssetDatabase.GetAssetPath(editorTexInput), true);
|
|
|
|
editorTex = new Texture2D(editorTexInput.width, editorTexInput.height);
|
|
editorTex.SetPixels(editorTexInput.GetPixels());
|
|
editorTex.Apply();
|
|
|
|
float aspectRatio = (float)editorTex.width / (float)editorTex.height;
|
|
int width = Mathf.Min(editorTex.width, 256);
|
|
editorTex = ScaleTexture(editorTex, width, (int)(width / aspectRatio));
|
|
|
|
cleanEditorTex = new Texture2D(editorTex.width, editorTex.height);
|
|
cleanEditorTex.SetPixels(editorTex.GetPixels());
|
|
cleanEditorTex.Apply();
|
|
|
|
values = new TextureEditorValues();
|
|
|
|
RecalculateEditorTexture();
|
|
}
|
|
|
|
//private void SetTextureReadWrite(string assetPath, bool enable)
|
|
//{
|
|
// TextureImporter tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
|
// if (tImporter != null)
|
|
// {
|
|
// tImporter.isReadable = enable;
|
|
// tImporter.SaveAndReimport();
|
|
// }
|
|
//}
|
|
|
|
private Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight)
|
|
{
|
|
targetWidth = Mathf.ClosestPowerOfTwo(targetWidth);
|
|
targetHeight = Mathf.ClosestPowerOfTwo(targetHeight);
|
|
|
|
Texture2D result = new Texture2D(targetWidth, targetHeight, source.format, true);
|
|
Color[] scaledPixels = result.GetPixels(0);
|
|
float incX = ((float)1 / source.width) * ((float)source.width / targetWidth);
|
|
float incY = ((float)1 / source.height) * ((float)source.height / targetHeight);
|
|
for (int px = 0; px < scaledPixels.Length; px++) scaledPixels[px] = source.GetPixelBilinear(incX * ((float)px % targetWidth), incY * (float)Mathf.Floor(px / targetWidth));
|
|
|
|
result.SetPixels(scaledPixels, 0);
|
|
result.Apply();
|
|
return result;
|
|
}
|
|
|
|
public void RecalculateEditorTexture()
|
|
{
|
|
Color[] pixels = cleanEditorTex.GetPixels();
|
|
int texWidth = cleanEditorTex.width;
|
|
int texHeight = cleanEditorTex.height;
|
|
|
|
ComputeImageColorFilters(pixels);
|
|
|
|
editorTex = new Texture2D(texWidth, texHeight);
|
|
editorTex.SetPixels(pixels);
|
|
editorTex.Apply();
|
|
}
|
|
|
|
private void ComputeImageColorFilters(Color[] pixels)
|
|
{
|
|
float cosHsv = values.saturation * Mathf.Cos(values.hue * 3.14159265f / 180f);
|
|
float sinHsv = values.saturation * Mathf.Sin(values.hue * 3.14159265f / 180f);
|
|
|
|
for (int i = 0; i < pixels.Length; i++)
|
|
{
|
|
pixels[i].r = Mathf.Clamp01(((pixels[i].r - 0.5f) * values.contrast) + 0.5f);
|
|
pixels[i].g = Mathf.Clamp01(((pixels[i].g - 0.5f) * values.contrast) + 0.5f);
|
|
pixels[i].b = Mathf.Clamp01(((pixels[i].b - 0.5f) * values.contrast) + 0.5f);
|
|
|
|
pixels[i] = new Color(Mathf.Clamp01(pixels[i].r * (1 + values.brightness)), Mathf.Clamp01(pixels[i].g * (1 + values.brightness)), Mathf.Clamp01(pixels[i].b * (1 + values.brightness)), pixels[i].a);
|
|
|
|
pixels[i].r = Mathf.Pow(Mathf.Abs(pixels[i].r), values.gamma);
|
|
pixels[i].g = Mathf.Pow(Mathf.Abs(pixels[i].g), values.gamma);
|
|
pixels[i].b = Mathf.Pow(Mathf.Abs(pixels[i].b), values.gamma);
|
|
|
|
pixels[i].r = Mathf.Clamp01(pixels[i].r * Mathf.Pow(2, values.exposure));
|
|
pixels[i].g = Mathf.Clamp01(pixels[i].g * Mathf.Pow(2, values.exposure));
|
|
pixels[i].b = Mathf.Clamp01(pixels[i].b * Mathf.Pow(2, values.exposure));
|
|
|
|
pixels[i] *= values.editorColorTint;
|
|
|
|
Color hueShiftColor = pixels[i];
|
|
hueShiftColor.r = Mathf.Clamp01((.299f + .701f * cosHsv + .168f * sinHsv) * pixels[i].r + (.587f - .587f * cosHsv + .330f * sinHsv) * pixels[i].g + (.114f - .114f * cosHsv - .497f * sinHsv) * pixels[i].b);
|
|
hueShiftColor.g = Mathf.Clamp01((.299f - .299f * cosHsv - .328f * sinHsv) * pixels[i].r + (.587f + .413f * cosHsv + .035f * sinHsv) * pixels[i].g + (.114f - .114f * cosHsv + .292f * sinHsv) * pixels[i].b);
|
|
hueShiftColor.b = Mathf.Clamp01((.299f - .3f * cosHsv + 1.25f * sinHsv) * pixels[i].r + (.587f - .588f * cosHsv - 1.05f * sinHsv) * pixels[i].g + (.114f + .886f * cosHsv - .203f * sinHsv) * pixels[i].b);
|
|
pixels[i] = hueShiftColor;
|
|
|
|
if (values.invert) pixels[i] = new Color(1 - pixels[i].r, 1 - pixels[i].g, 1 - pixels[i].b, pixels[i].a);
|
|
|
|
if (values.greyscale || values.fullWhite || values.alphaGreyscale)
|
|
{
|
|
float greyScale = pixels[i].r * 0.59f + pixels[i].g * 0.3f + pixels[i].b * 0.11f;
|
|
|
|
if (values.fullWhite) pixels[i] = new Color(1, 1, 1, greyScale);
|
|
else if (values.greyscale) pixels[i] = new Color(greyScale, greyScale, greyScale, pixels[i].a);
|
|
|
|
if (values.alphaGreyscale) pixels[i] = new Color(pixels[i].r, pixels[i].g, pixels[i].b, greyScale);
|
|
}
|
|
|
|
if (values.alphaIsOne) pixels[i] = new Color(pixels[i].r, pixels[i].g, pixels[i].b, 1f);
|
|
|
|
if (values.blackBackground)
|
|
{
|
|
if (pixels[i].a < 0.05f) pixels[i] = new Color(pixels[i].a, pixels[i].a, pixels[i].a, 1);
|
|
else pixels[i] = new Color(pixels[i].r, pixels[i].g, pixels[i].b, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void FlipEditorTexture(bool isHorizontal)
|
|
{
|
|
Color[] pixels = editorTex.GetPixels();
|
|
Color[] pixelsClean = cleanEditorTex.GetPixels();
|
|
int texWidth = editorTex.width;
|
|
int texHeight = editorTex.height;
|
|
|
|
if (isHorizontal)
|
|
{
|
|
pixels = FlipHorizontal(pixels, texWidth, texHeight);
|
|
pixelsClean = FlipHorizontal(pixelsClean, texWidth, texHeight);
|
|
values.isFlipHorizontal = !values.isFlipHorizontal;
|
|
}
|
|
else
|
|
{
|
|
pixels = FlipVertical(pixels, texWidth, texHeight);
|
|
pixelsClean = FlipVertical(pixelsClean, texWidth, texHeight);
|
|
values.isFlipVertical = !values.isFlipVertical;
|
|
}
|
|
|
|
editorTex = new Texture2D(texWidth, texHeight);
|
|
editorTex.SetPixels(pixels);
|
|
editorTex.Apply();
|
|
cleanEditorTex = new Texture2D(texWidth, texHeight);
|
|
cleanEditorTex.SetPixels(pixelsClean);
|
|
cleanEditorTex.Apply();
|
|
}
|
|
|
|
private Color[] FlipHorizontal(Color[] pixels, int width, int height)
|
|
{
|
|
Color[] outputPixels = new Color[pixels.Length];
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int i1 = GetPixelIndex(x, y, width);
|
|
int i2 = GetPixelIndex(width - 1 - x, y, width);
|
|
outputPixels[i1] = pixels[i2];
|
|
}
|
|
}
|
|
|
|
return outputPixels;
|
|
}
|
|
|
|
private Color[] FlipVertical(Color[] pixels, int width, int height)
|
|
{
|
|
Color[] outputPixels = new Color[pixels.Length];
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int i1 = GetPixelIndex(x, y, width);
|
|
int i2 = GetPixelIndex(x, height - 1 - y, width);
|
|
outputPixels[i1] = pixels[i2];
|
|
}
|
|
}
|
|
|
|
return outputPixels;
|
|
}
|
|
|
|
private int GetPixelIndex(int x, int y, int width)
|
|
{
|
|
return y * width + x;
|
|
}
|
|
|
|
public void RotateEditorTextureLeft()
|
|
{
|
|
Color[] pixels = editorTex.GetPixels();
|
|
Color[] pixelsClean = cleanEditorTex.GetPixels();
|
|
int texWidth = editorTex.width;
|
|
int texHeight = editorTex.height;
|
|
|
|
pixels = RotateClockWise(pixels, texWidth, texHeight);
|
|
pixelsClean = RotateClockWise(pixelsClean, texWidth, texHeight);
|
|
|
|
editorTex = new Texture2D(texHeight, texWidth); //Width and Height get swapped to account for rotation
|
|
editorTex.SetPixels(pixels);
|
|
editorTex.Apply();
|
|
cleanEditorTex = new Texture2D(texHeight, texWidth); //Width and Height get swapped to account for rotation
|
|
cleanEditorTex.SetPixels(pixelsClean);
|
|
cleanEditorTex.Apply();
|
|
|
|
values.rotationAmount = (values.rotationAmount + 1) % 4;
|
|
}
|
|
|
|
public Color[] RotateClockWise(Color[] pixels, int width, int height)
|
|
{
|
|
Color[] outputPixels = new Color[pixels.Length];
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int i1 = GetPixelIndex(x, height - y - 1, width);
|
|
int i2 = GetPixelIndex(y, x, height);
|
|
outputPixels[i2] = pixels[i1];
|
|
}
|
|
}
|
|
|
|
return outputPixels;
|
|
}
|
|
|
|
private void ComputeFinalTexture()
|
|
{
|
|
Color[] pixels;
|
|
int texWidth, texHeight;
|
|
|
|
for (int i = 0; i < values.rotationAmount; i++)
|
|
{
|
|
texWidth = editorTexInput.width;
|
|
texHeight = editorTexInput.height;
|
|
pixels = editorTexInput.GetPixels();
|
|
pixels = RotateClockWise(pixels, texWidth, texHeight);
|
|
editorTexInput = new Texture2D(texHeight, texWidth);
|
|
editorTexInput.SetPixels(pixels);
|
|
editorTexInput.Apply();
|
|
}
|
|
|
|
pixels = editorTexInput.GetPixels();
|
|
texWidth = editorTexInput.width;
|
|
texHeight = editorTexInput.height;
|
|
if (values.isFlipHorizontal)
|
|
{
|
|
pixels = FlipHorizontal(pixels, texWidth, texHeight);
|
|
}
|
|
if (values.isFlipVertical)
|
|
{
|
|
pixels = FlipVertical(pixels, texWidth, texHeight);
|
|
}
|
|
|
|
ComputeImageColorFilters(pixels);
|
|
editorTexInput = new Texture2D(texWidth, texHeight);
|
|
editorTexInput.SetPixels(pixels);
|
|
editorTexInput.Apply();
|
|
|
|
if (Math.Abs(values.exportScale - 1f) > 0.05f)
|
|
{
|
|
editorTexInput = ScaleTexture(editorTexInput, (int)(texWidth * values.exportScale), (int)(texHeight * values.exportScale));
|
|
}
|
|
}
|
|
|
|
public void SaveAsPNG()
|
|
{
|
|
string fullPath = AssetDatabase.GetAssetPath(editorTexInput);
|
|
string path = fullPath.Replace(Path.GetFileName(fullPath), "");
|
|
|
|
fullPath = AssetDatabase.GenerateUniqueAssetPath(fullPath);
|
|
|
|
string fileName = fullPath.Replace(path, "");
|
|
fileName = fileName.Replace(".png", "");
|
|
fullPath = EditorUtility.SaveFilePanel("Save Image", path, fileName, "png");
|
|
if (fullPath.Length == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string pingPath = fullPath;
|
|
|
|
ComputeFinalTexture();
|
|
|
|
byte[] bytes = editorTexInput.EncodeToPNG();
|
|
File.WriteAllBytes(pingPath, bytes);
|
|
AssetDatabase.ImportAsset(pingPath);
|
|
AssetDatabase.Refresh();
|
|
EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(pingPath, typeof(Texture)));
|
|
|
|
EditorUtils.ShowNotification("Edited Image saved to: " + fullPath);
|
|
|
|
editorTexInput = null;
|
|
editorTex = null;
|
|
cleanEditorTex = null;
|
|
|
|
SetTextureEditorDefaultValues();
|
|
}
|
|
|
|
private void SetTextureEditorDefaultValues()
|
|
{
|
|
values.SetDefault();
|
|
}
|
|
}
|
|
} |