You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			167 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			167 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using Aseprite.Utils;
 | |
| using AsepriteImporter.Data;
 | |
| using UnityEditor;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace AsepriteImporter
 | |
| {
 | |
|     public class SpriteAtlasBuilder
 | |
|     {
 | |
|         private readonly Vector2Int spriteSize;
 | |
|         private int padding = 1;
 | |
| 
 | |
|         
 | |
|         public SpriteAtlasBuilder()
 | |
|         {
 | |
|             spriteSize = new Vector2Int(16, 16);
 | |
|         }
 | |
| 
 | |
|         public SpriteAtlasBuilder(Vector2Int spriteSize, int padding = 1)
 | |
|         {
 | |
|             this.spriteSize = spriteSize;
 | |
|             this.padding = padding;
 | |
|         }
 | |
| 
 | |
|         public SpriteAtlasBuilder(int width, int height, int padding = 1)
 | |
|         {
 | |
|             spriteSize = new Vector2Int(width, height);
 | |
|             this.padding = padding;
 | |
|         }
 | |
| 
 | |
|         public Texture2D GenerateAtlas(Texture2D[] sprites, out AseFileSpriteImportData[] spriteImportData, bool baseTwo = true)
 | |
|         {
 | |
|             int cols, rows;
 | |
| 
 | |
|             CalculateColsRows(sprites.Length, spriteSize, out cols, out rows);
 | |
| 
 | |
|             return GenerateAtlas(sprites, cols, rows, out spriteImportData, baseTwo);
 | |
|         }
 | |
| 
 | |
|         public Texture2D GenerateAtlas(Texture2D[] sprites, int cols, int rows, out AseFileSpriteImportData[] spriteImportData, bool baseTwo = false)
 | |
|         {
 | |
|             spriteImportData = new AseFileSpriteImportData[sprites.Length];
 | |
| 
 | |
|             var width = cols * spriteSize.x;
 | |
|             var height = rows * spriteSize.y;
 | |
| 
 | |
|             if (baseTwo)
 | |
|             {
 | |
|                 var baseTwoValue = CalculateNextBaseTwoValue(Math.Max(width, height));
 | |
|                 width = baseTwoValue;
 | |
|                 height = baseTwoValue;
 | |
|             }
 | |
| 
 | |
|             var atlas = Texture2DUtil.CreateTransparentTexture(width, height);
 | |
|             var index = 0;
 | |
| 
 | |
|             for (var row = 0; row < rows; ++row)
 | |
|             {
 | |
|                 for (var col = 0; col < cols; ++col)
 | |
|                 {
 | |
|                     Rect spriteRect = new Rect(col * spriteSize.x, atlas.height - ((row + 1) * spriteSize.y), spriteSize.x, spriteSize.y);
 | |
|                     Color[] colors = sprites[index].GetPixels();
 | |
|                     atlas.SetPixels((int)spriteRect.x, (int)spriteRect.y, (int)spriteRect.width, (int)spriteRect.height, sprites[index].GetPixels());
 | |
|                     atlas.Apply();
 | |
| 
 | |
|                     List<Vector2[]> outline = GenerateRectOutline(spriteRect);
 | |
|                     spriteImportData[index] = CreateSpriteImportData(index.ToString(), spriteRect, outline);
 | |
| 
 | |
|                     index++;
 | |
|                     if (index >= sprites.Length)
 | |
|                         break;
 | |
|                 }
 | |
|                 if (index >= sprites.Length)
 | |
|                     break;
 | |
|             }
 | |
| 
 | |
|             return atlas;
 | |
|         }
 | |
| 
 | |
|         public static List<Vector2Int[]> GenerateRectOutline(RectInt rect)
 | |
|         {
 | |
|             List<Vector2Int[]> outline = new List<Vector2Int[]>();
 | |
| 
 | |
|             outline.Add(new Vector2Int[] { new Vector2Int(rect.x, rect.y), new Vector2Int(rect.x, rect.yMax) });
 | |
|             outline.Add(new Vector2Int[] { new Vector2Int(rect.x, rect.yMax), new Vector2Int(rect.xMax, rect.yMax) });
 | |
|             outline.Add(new Vector2Int[] { new Vector2Int(rect.xMax, rect.yMax), new Vector2Int(rect.xMax, rect.y) });
 | |
|             outline.Add(new Vector2Int[] { new Vector2Int(rect.xMax, rect.y), new Vector2Int(rect.x, rect.yMax) });
 | |
| 
 | |
|             return outline;
 | |
|         }
 | |
|         
 | |
|         public static List<Vector2[]> GenerateRectOutline(Rect rect)
 | |
|         {
 | |
|             List<Vector2[]> outline = new List<Vector2[]>();
 | |
| 
 | |
|             outline.Add(new Vector2[] { new Vector2(rect.x, rect.y), new Vector2(rect.x, rect.yMax) });
 | |
|             outline.Add(new Vector2[] { new Vector2(rect.x, rect.yMax), new Vector2(rect.xMax, rect.yMax) });
 | |
|             outline.Add(new Vector2[] { new Vector2(rect.xMax, rect.yMax), new Vector2(rect.xMax, rect.y) });
 | |
|             outline.Add(new Vector2[] { new Vector2(rect.xMax, rect.y), new Vector2(rect.x, rect.yMax) });
 | |
| 
 | |
|             return outline;
 | |
|         }
 | |
| 
 | |
|         private AseFileSpriteImportData CreateSpriteImportData(string name, Rect rect, List<Vector2[]> outline)
 | |
|         {
 | |
|             return new AseFileSpriteImportData()
 | |
|             {
 | |
|                 alignment = SpriteAlignment.Center,
 | |
|                 border = Vector4.zero,
 | |
|                 name = name,
 | |
|                 outline = outline,
 | |
|                 pivot = new Vector2(0.5f, 0.5f),
 | |
|                 rect = rect,
 | |
|                 spriteID = GUID.Generate().ToString(),
 | |
|                 tessellationDetail = 0
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         private static void CalculateColsRows(int spritesCount, Vector2 spriteSize, out int cols, out int rows)
 | |
|         {
 | |
|             float minDifference = float.MaxValue;
 | |
|             cols = spritesCount;
 | |
|             rows = 1;
 | |
|             
 | |
|             float width = spriteSize.x * cols;
 | |
|             float height = spriteSize.y * rows;
 | |
| 
 | |
|             
 | |
|             
 | |
|             for (rows = 1; rows < spritesCount; ++rows)
 | |
|             {
 | |
|                 cols = Mathf.CeilToInt((float)spritesCount / rows);
 | |
|                 
 | |
|                 width = spriteSize.x * cols;
 | |
|                 height = spriteSize.y * rows;
 | |
| 
 | |
|                 float difference = Mathf.Abs(width - height);
 | |
|                 if (difference < minDifference)
 | |
|                 {
 | |
|                     minDifference = difference;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     rows -= 1;
 | |
|                     cols = Mathf.CeilToInt((float)spritesCount / rows);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static int CalculateNextBaseTwoValue(int value)
 | |
|         {
 | |
|             var exponent = 0;
 | |
|             var baseTwo = 0;
 | |
| 
 | |
|             while (baseTwo < value)
 | |
|             {
 | |
|                 baseTwo = (int)Math.Pow(2, exponent);
 | |
|                 exponent++;
 | |
|             }
 | |
| 
 | |
|             return baseTwo;
 | |
|         }
 | |
|     }
 | |
| } |