using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace Editor.Utility { public static class EdgeMapUtils { public const int EDGE_SIZE = 2; public static void Update(IEnumerable spr) { foreach (var s in spr) Update(s); } private static void Update(Sprite s) { //aaahaha, ok, oh boy. Yeah, scan the sprite on the cpu, look for edges and plug those into a texture //make sprite readable var test = s.texture; var path = AssetDatabase.GetAssetPath(s); var spriteTi = (TextureImporter)TextureImporter.GetAtPath(path); spriteTi.isReadable = true; AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); //DO STUFF var edges = BuildEdgeTexture(s); var savedEdgePath = SaveEdges(s, path, edges); //link it to sprite as a secondary map SpriteUtils.TryAddSecondaryTexture(spriteTi, "_EdgeMap", savedEdgePath); //put sprite back the way it was. spriteTi.isReadable = false; } private static string SaveEdges(Sprite s, string path, Texture2D edges) { var folder = path.Remove(path.LastIndexOf(s.name) - 1); EditorUtils.LazyCreateFolder(folder, "EdgeMaps"); var edgePath = $"{folder}/EdgeMaps/{s.name}_edges.png"; var bytes = edges.EncodeToPNG(); System.IO.File.WriteAllBytes(edgePath, bytes); AssetDatabase.ImportAsset(edgePath, ImportAssetOptions.ForceSynchronousImport); //AssetDatabase.CreateAsset(edges, edgePath); var ti = AssetImporter.GetAtPath(edgePath) as TextureImporter; ti.textureType = TextureImporterType.Sprite; ti.filterMode = FilterMode.Point; ti.textureCompression = TextureImporterCompression.Uncompressed; ti.mipmapEnabled = false; ti.alphaIsTransparency = false; EditorUtility.SetDirty(ti); ti.SaveAndReimport(); return edgePath; } private static Texture2D BuildEdgeTexture(Sprite s) { var edges = new Texture2D(s.texture.width, s.texture.height, TextureFormat.RGBA32, false); for (int x = 0; x < s.texture.width; x++) { for (int y = 0; y < s.texture.height; y++) { edges.SetPixel(x, y, GetEdge(s, x, y)); } } edges.Apply(); return edges; } //encodes edge information into 1 channel of the texture private static Color GetEdge(Sprite s, int x, int y) { //MY COUNTERPART IS CustomRenderGraphBlock.hlsl.getSpriteEdges_float var col = new Color(0, 0, 0, 0); var px = s.texture.GetPixel(x, y); if (px.a < 1) { return col; } else { for (int edgeTest = EDGE_SIZE; edgeTest >= 0; edgeTest--) { float edgeAlpha = 1f - (float)edgeTest / ((float)EDGE_SIZE + 1f); //test up if (IsEdge(s, x, y + edgeTest)) col.r = edgeAlpha; //test right if (IsEdge(s, x + edgeTest, y)) col.g = edgeAlpha; //test left if (IsEdge(s, x - edgeTest, y)) col.b = edgeAlpha; //test bot if (IsEdge(s, x, y - edgeTest)) col.a = edgeAlpha; } } return col; } private static bool IsEdge(Sprite s, int x, int y) { if (x < 0 || y < 0 || x >= s.texture.width || y >= s.texture.height) return true; else return s.texture.GetPixel(x, y).a == 0f; } } }