|
@@ -0,0 +1,1023 @@
|
|
|
+using UnityEditor;
|
|
|
+using UnityEngine;
|
|
|
+using UnityEngine.Events;
|
|
|
+
|
|
|
+using System;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Reflection;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using LitJson;
|
|
|
+using Object = System.Object;
|
|
|
+using Random = UnityEngine.Random;
|
|
|
+
|
|
|
+[CustomEditor(typeof(AtlasUtil))]
|
|
|
+public class EdAtlasUtil : Editor
|
|
|
+{
|
|
|
+ protected class Box
|
|
|
+ {
|
|
|
+ public int Area
|
|
|
+ {
|
|
|
+ get { return Width*Height; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool Valid
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (Width > 0 && Height > 0)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector2 LowerLeft;
|
|
|
+ public Vector2 UpperLeft
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(0, Height); }
|
|
|
+ }
|
|
|
+ public Vector2 LowerRight
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(Width, 0); }
|
|
|
+ }
|
|
|
+ public Vector2 UpperRight
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(Width, Height); }
|
|
|
+ }
|
|
|
+
|
|
|
+ public int Width;
|
|
|
+ public int Height;
|
|
|
+
|
|
|
+ public Box(int width, int height, Vector2 lowerLeft)
|
|
|
+ {
|
|
|
+ Width = width;
|
|
|
+ Height = height;
|
|
|
+ LowerLeft = lowerLeft;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public bool CanFill(Debris debris)
|
|
|
+ {
|
|
|
+ if (debris.Width <= Width && debris.Height <= Height)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected class JagBox
|
|
|
+ {
|
|
|
+ public class Pair
|
|
|
+ {
|
|
|
+ public int Low;
|
|
|
+ public int High;
|
|
|
+
|
|
|
+ public Pair(int low, int high)
|
|
|
+ {
|
|
|
+ Low = low;
|
|
|
+ High = high;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector2 UpperRight;
|
|
|
+
|
|
|
+ public bool Valid
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (BoxList.Count == 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public int Width
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return (int) BoxList.MySum(box => box.Width);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Box> BoxList;
|
|
|
+
|
|
|
+ public Dictionary<Pair, Pair> XCoordDic;
|
|
|
+ public Dictionary<Pair, Pair> YCoordDic;
|
|
|
+
|
|
|
+ public JagBox(List<Box> boxList)
|
|
|
+ {
|
|
|
+ BoxList = boxList;
|
|
|
+
|
|
|
+ if (boxList.Count == 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ UpperRight = boxList.Back(0).UpperRight;
|
|
|
+
|
|
|
+ XCoordDic = new Dictionary<Pair, Pair>();
|
|
|
+ YCoordDic = new Dictionary<Pair, Pair>();
|
|
|
+
|
|
|
+ for (int i = 0; i < boxList.Count; i++)
|
|
|
+ {
|
|
|
+ Pair xPair = new Pair((int) boxList[i].LowerLeft.x, (int) boxList[i].LowerRight.x);
|
|
|
+ Pair yPair = new Pair((int) boxList[i].LowerLeft.y, (int) boxList[i].UpperRight.y);
|
|
|
+
|
|
|
+ XCoordDic.Add(yPair, xPair);
|
|
|
+ YCoordDic.Add(xPair, yPair);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public int GetMatchHeight(int width, out int boxIndex)
|
|
|
+ {
|
|
|
+ int x = (int)UpperRight.x - width;
|
|
|
+
|
|
|
+ List<Pair> xPairList = YCoordDic.Keys.ToList();
|
|
|
+
|
|
|
+ for (int i = xPairList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ if (xPairList[i].Low <= x && x <= xPairList[i].High)
|
|
|
+ {
|
|
|
+ int y = YCoordDic[xPairList[i]].Low;
|
|
|
+
|
|
|
+ boxIndex = i;
|
|
|
+
|
|
|
+ return (int)UpperRight.y - y;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new Exception("An error occured");
|
|
|
+ }
|
|
|
+
|
|
|
+ public int GetBoxIndexByWidth(int width, out bool onBorder)
|
|
|
+ {
|
|
|
+ int x = (int)UpperRight.x - width;
|
|
|
+
|
|
|
+ List<Pair> xPairList = YCoordDic.Keys.ToList();
|
|
|
+
|
|
|
+ for (int i = 0; i < xPairList.Count; i++)
|
|
|
+ {
|
|
|
+ if (xPairList[i].Low < x && x < xPairList[i].High)
|
|
|
+ {
|
|
|
+ onBorder = false;
|
|
|
+
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ else if (xPairList[i].Low == x || x == xPairList[i].High)
|
|
|
+ {
|
|
|
+ onBorder = true;
|
|
|
+
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new Exception("An error occured");
|
|
|
+ }
|
|
|
+
|
|
|
+ public int GetBoxIndexByHeight(int height, out bool onBorder)
|
|
|
+ {
|
|
|
+ int y = (int)UpperRight.y - height;
|
|
|
+
|
|
|
+ List<Pair> yPairList = XCoordDic.Keys.ToList();
|
|
|
+
|
|
|
+ for (int i = 0; i < yPairList.Count; i++)
|
|
|
+ {
|
|
|
+ if (yPairList[i].Low < y && y < yPairList[i].High)
|
|
|
+ {
|
|
|
+ onBorder = false;
|
|
|
+
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ else if(yPairList[i].Low == y || y == yPairList[i].High)
|
|
|
+ {
|
|
|
+ onBorder = true;
|
|
|
+
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new Exception("An error occured");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public List<JagBox> Fill(Debris debris)
|
|
|
+ {
|
|
|
+ int width = debris.Width;
|
|
|
+ int height = debris.Height;
|
|
|
+ bool verticalCut = width > height;
|
|
|
+
|
|
|
+ debris.LowerLeft = UpperRight + new Vector2(-width, -height);
|
|
|
+
|
|
|
+ int splitIndexA;
|
|
|
+ int splitIndexB;
|
|
|
+ int newBoxWidth;
|
|
|
+ int newBoxHeight;
|
|
|
+ bool border;
|
|
|
+
|
|
|
+ Box newBox;
|
|
|
+ Box splitBoxA;
|
|
|
+ Box splitBoxB;
|
|
|
+ Vector2 newBoxLowerLeft;
|
|
|
+
|
|
|
+ List<Box> newBoxListA = new List<Box>();
|
|
|
+ List<Box> newBoxListB = new List<Box>();
|
|
|
+
|
|
|
+ if (verticalCut)
|
|
|
+ {
|
|
|
+ #region 竖切
|
|
|
+
|
|
|
+ splitIndexA = GetBoxIndexByWidth(width, out border);
|
|
|
+
|
|
|
+ splitIndexB = splitIndexA;
|
|
|
+
|
|
|
+ splitBoxA = BoxList[splitIndexA];
|
|
|
+ splitBoxB = splitBoxA;
|
|
|
+
|
|
|
+ if (border)
|
|
|
+ {
|
|
|
+ if (BoxList.Count > 1)
|
|
|
+ {
|
|
|
+ splitBoxB = BoxList[splitIndexA + 1];
|
|
|
+
|
|
|
+ splitIndexB += 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (BoxList.Count > 1)
|
|
|
+ {
|
|
|
+ splitBoxB = splitBoxA;
|
|
|
+
|
|
|
+ splitIndexB += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for (int i = 0; i < splitIndexA; i++)
|
|
|
+ {
|
|
|
+ newBoxListA.Add(BoxList[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ newBoxWidth = (int) UpperRight.x - (int) splitBoxA.LowerLeft.x - width;
|
|
|
+
|
|
|
+ newBox = new Box(newBoxWidth, splitBoxA.Height, splitBoxA.LowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListA.Add(newBox);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (BoxList.Count > 1)
|
|
|
+ {
|
|
|
+ if (!border)
|
|
|
+ {
|
|
|
+ newBoxWidth = splitBoxB.Width - ((int) UpperRight.x - (int) splitBoxB.LowerLeft.x - width);
|
|
|
+
|
|
|
+ newBoxLowerLeft = new Vector2(UpperRight.x - width, splitBoxB.LowerLeft.y);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newBoxWidth = splitBoxB.Width;
|
|
|
+
|
|
|
+ newBoxLowerLeft = splitBoxB.LowerLeft;
|
|
|
+ }
|
|
|
+
|
|
|
+ newBoxHeight = splitBoxB.Height - height;
|
|
|
+
|
|
|
+ newBox = new Box(newBoxWidth, newBoxHeight, newBoxLowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListB.Add(newBox);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = splitIndexB; i < BoxList.Count; i++)
|
|
|
+ {
|
|
|
+ newBox = BoxList[i];
|
|
|
+
|
|
|
+ newBox.Height -= height;
|
|
|
+
|
|
|
+ newBoxListB.Add(BoxList[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newBoxWidth = width;
|
|
|
+
|
|
|
+ newBoxHeight = splitBoxB.Height - height;
|
|
|
+
|
|
|
+ newBoxLowerLeft = new Vector2(UpperRight.x - width, splitBoxB.LowerLeft.y);
|
|
|
+
|
|
|
+ newBox = new Box(newBoxWidth, newBoxHeight, newBoxLowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListB.Add(newBox);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #region 横切
|
|
|
+
|
|
|
+ splitIndexA = GetBoxIndexByHeight(height, out border);
|
|
|
+
|
|
|
+ splitIndexB = splitIndexA;
|
|
|
+
|
|
|
+ splitBoxA = BoxList[splitIndexA];
|
|
|
+ splitBoxB = splitBoxA;
|
|
|
+
|
|
|
+ if (border)
|
|
|
+ {
|
|
|
+ if (BoxList.Count > splitIndexA + 1)
|
|
|
+ {
|
|
|
+ splitBoxB = BoxList[splitIndexA + 1];
|
|
|
+
|
|
|
+ splitIndexB += 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (BoxList.Count > 1)
|
|
|
+ {
|
|
|
+ splitBoxB = splitBoxA;
|
|
|
+
|
|
|
+ splitIndexB += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for (int i = 0; i < splitIndexA; i++)
|
|
|
+ {
|
|
|
+ newBoxListA.Add(BoxList[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ newBoxWidth = (int) UpperRight.x - (int) splitBoxA.LowerLeft.x - width;
|
|
|
+
|
|
|
+ newBoxHeight = height;
|
|
|
+
|
|
|
+ newBoxLowerLeft = new Vector2(splitBoxA.LowerLeft.x, (int)UpperRight.y - height);
|
|
|
+
|
|
|
+ newBox = new Box(newBoxWidth, newBoxHeight, newBoxLowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListA.Add(newBox);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (BoxList.Count > splitIndexA + 1)
|
|
|
+ {
|
|
|
+ newBoxHeight = (int) UpperRight.y - (int) splitBoxB.LowerLeft.y - height;
|
|
|
+
|
|
|
+ newBox = new Box(splitBoxB.Width, newBoxHeight, splitBoxB.LowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListB.Add(newBox);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = splitIndexB; i < BoxList.Count; i++)
|
|
|
+ {
|
|
|
+ newBox = BoxList[i];
|
|
|
+
|
|
|
+ newBox.Height -= height;
|
|
|
+
|
|
|
+ newBoxListB.Add(newBox);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newBoxWidth = splitBoxB.Width;
|
|
|
+
|
|
|
+ newBoxHeight = splitBoxB.Height - height;
|
|
|
+
|
|
|
+ newBoxLowerLeft = splitBoxB.LowerLeft;
|
|
|
+
|
|
|
+ newBox = new Box(newBoxWidth, newBoxHeight, newBoxLowerLeft);
|
|
|
+
|
|
|
+ if (newBox.Valid)
|
|
|
+ {
|
|
|
+ newBoxListB.Add(newBox);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+
|
|
|
+ JagBox jagBoxBelow = new JagBox(newBoxListB);
|
|
|
+ JagBox jagBoxOnLeft = new JagBox(newBoxListA);
|
|
|
+
|
|
|
+ List<JagBox> newJagBoxList = new List<JagBox>();
|
|
|
+
|
|
|
+ if (jagBoxBelow.Valid)
|
|
|
+ {
|
|
|
+ newJagBoxList.Add(jagBoxBelow);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (jagBoxOnLeft.Valid)
|
|
|
+ {
|
|
|
+ newJagBoxList.Add(jagBoxOnLeft);
|
|
|
+ }
|
|
|
+
|
|
|
+ return newJagBoxList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool CanFill(Debris debris)
|
|
|
+ {
|
|
|
+ if (debris.Width > Width)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ int boxIndex;
|
|
|
+
|
|
|
+ if (GetMatchHeight(debris.Width, out boxIndex) < debris.Height)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = boxIndex; i < BoxList.Count; i++)
|
|
|
+ {
|
|
|
+ if (BoxList[i].Height < debris.Height)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected class Debris
|
|
|
+ {
|
|
|
+ public int Max
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (Width > Height)
|
|
|
+ {
|
|
|
+ return Width;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Height;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public int Area
|
|
|
+ {
|
|
|
+ get { return Width*Height; }
|
|
|
+ }
|
|
|
+ public string Name
|
|
|
+ {
|
|
|
+ get { return Texture.name; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Rect Rect
|
|
|
+ {
|
|
|
+ get { return new Rect(LowerLeft.x, LowerLeft.y, Width, Height); }
|
|
|
+ }
|
|
|
+ public Vector2 UpperLeft
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(0, Height); }
|
|
|
+ }
|
|
|
+ public Vector2 LowerRight
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(Width, 0); }
|
|
|
+ }
|
|
|
+ public Vector2 UpperRight
|
|
|
+ {
|
|
|
+ get { return LowerLeft + new Vector2(Width, Height); }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector4 Pivot;
|
|
|
+ public Vector4 Border;
|
|
|
+ public Vector2 LowerLeft;
|
|
|
+
|
|
|
+ public int Width;
|
|
|
+ public int Height;
|
|
|
+
|
|
|
+ public Texture2D Texture;
|
|
|
+
|
|
|
+
|
|
|
+ public Color GetPixel(int x, int y)
|
|
|
+ {
|
|
|
+ return Texture.GetPixel(x, y);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Debris(int interval, Texture2D texture2D, int width, int height)
|
|
|
+ {
|
|
|
+ Width = width + interval*2;
|
|
|
+ Height = height + interval*2;
|
|
|
+ Texture = texture2D;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Debris(int interval, Texture2D texture2D)
|
|
|
+ {
|
|
|
+ Texture = texture2D;
|
|
|
+
|
|
|
+ string assetPath = AssetDatabase.GetAssetPath(texture2D);
|
|
|
+
|
|
|
+ TextureImporter textureImporter = (TextureImporter) AssetImporter.GetAtPath(assetPath);
|
|
|
+
|
|
|
+ Pivot = textureImporter.spritePivot;
|
|
|
+ Border = textureImporter.spriteBorder;
|
|
|
+
|
|
|
+ if (!textureImporter.isReadable)
|
|
|
+ {
|
|
|
+ textureImporter.isReadable = true;
|
|
|
+
|
|
|
+ textureImporter.SaveAndReimport();
|
|
|
+ }
|
|
|
+
|
|
|
+ object[] args = new object[2];
|
|
|
+
|
|
|
+ MethodInfo methodInfo = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
+
|
|
|
+ methodInfo.Invoke(textureImporter, args);
|
|
|
+
|
|
|
+ Width = (int) args[0] + interval*2;
|
|
|
+ Height = (int) args[1] + interval*2;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static float MaxMinByLength(Debris debris)
|
|
|
+ {
|
|
|
+ if (debris.Width > debris.Height)
|
|
|
+ {
|
|
|
+ return debris.Width;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return debris.Height;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool SortByMax(Debris a, Debris b)
|
|
|
+ {
|
|
|
+ if (a.Max < b.Max)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool SortByWidth(Debris a, Debris b)
|
|
|
+ {
|
|
|
+ if (a.Width < b.Width)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 变量
|
|
|
+
|
|
|
+ public AtlasUtil Script;
|
|
|
+
|
|
|
+ protected int AntiCrush;
|
|
|
+ protected string BuildPath;
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ public void OnEnable()
|
|
|
+ {
|
|
|
+ Script = (AtlasUtil) target;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected List<Debris> CreateDebrisList()
|
|
|
+ {
|
|
|
+ List<Debris> resultList = new List<Debris>();
|
|
|
+
|
|
|
+ for (int i = 0; i < Script.TextureList.Count; i++)
|
|
|
+ {
|
|
|
+ if (Script.TextureList[i] != null)
|
|
|
+ {
|
|
|
+ resultList.Add(new Debris(Script.Padding, Script.TextureList[i]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < Script.VirtualTextureList.Count; i++)
|
|
|
+ {
|
|
|
+ Texture2D texture = new Texture2D(Script.VirtualTextureList[i].Width, Script.VirtualTextureList[i].Height);
|
|
|
+ texture.name = Script.VirtualTextureList[i].Name;
|
|
|
+
|
|
|
+ Color randomColor = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1);
|
|
|
+
|
|
|
+ for (int j = 0; j < Script.VirtualTextureList[i].Width; j++)
|
|
|
+ {
|
|
|
+ for (int k = 0; k < Script.VirtualTextureList[i].Height; k++)
|
|
|
+ {
|
|
|
+ texture.SetPixel(j, k, randomColor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ texture.Apply();
|
|
|
+
|
|
|
+ resultList.Add(new Debris(Script.Padding, texture, Script.VirtualTextureList[i].Width, Script.VirtualTextureList[i].Height));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ StreamWriter streamWriter = new StreamWriter(BuildPath + "DebugInfo_" + Script.BuildName + ".txt");
|
|
|
+
|
|
|
+ for (int i = 0; i < resultList.Count; i++)
|
|
|
+ {
|
|
|
+ streamWriter.WriteLine("Width:{0} Height:{1} Pivot:{2} Border:{3}", resultList[i].Width, resultList[i].Height, resultList[i].Pivot, resultList[i].Border);
|
|
|
+ }
|
|
|
+
|
|
|
+ streamWriter.Close();
|
|
|
+
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected Box GetFirstBox(List<Debris> debrisList)
|
|
|
+ {
|
|
|
+ int totalArea = debrisList.Sum(debris => debris.Area);
|
|
|
+
|
|
|
+ int length = ExMath.NextPOT(Mathf.Sqrt(totalArea));
|
|
|
+
|
|
|
+ length = Mathf.Min(length, Script.MaxSize);
|
|
|
+
|
|
|
+ return new Box(length, length, new Vector2(0, 0));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected void FillBox(bool first, Box parentBox, Debris debris, List<Debris> candidateList, List<Debris> resultDebrisList, List<Box> emptyBoxList)
|
|
|
+ {
|
|
|
+ Box newBoxA;
|
|
|
+ Box newBoxB;
|
|
|
+
|
|
|
+ if (first)
|
|
|
+ {
|
|
|
+ newBoxA = parentBox;
|
|
|
+ newBoxB = new Box(0, 0, new Vector2());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Vector2 lowerLeftA = parentBox.LowerLeft + new Vector2(0, debris.Height);
|
|
|
+ Vector2 lowerLeftB = parentBox.LowerLeft + new Vector2(debris.Width, 0);
|
|
|
+
|
|
|
+ newBoxA = new Box(debris.Width, parentBox.Height - debris.Height, lowerLeftA);
|
|
|
+ newBoxB = new Box(parentBox.Width - debris.Width, parentBox.Height, lowerLeftB);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newBoxA.Valid)
|
|
|
+ {
|
|
|
+ List<Debris> newCandidateListA = new List<Debris>();
|
|
|
+
|
|
|
+ for (int i = 0; i < candidateList.Count; i++)
|
|
|
+ {
|
|
|
+ if (newBoxA.CanFill(candidateList[i]))
|
|
|
+ {
|
|
|
+ newCandidateListA.Add(candidateList[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ newCandidateListA.MySort(Debris.SortByWidth);
|
|
|
+
|
|
|
+ if (newCandidateListA.Count > 0)
|
|
|
+ {
|
|
|
+ Debris newDebris = newCandidateListA[0];
|
|
|
+
|
|
|
+ candidateList.Remove(newDebris);
|
|
|
+
|
|
|
+ newDebris.LowerLeft = debris.UpperLeft;
|
|
|
+ resultDebrisList.Add(newDebris);
|
|
|
+
|
|
|
+ FillBox(false, newBoxA, newDebris, candidateList, resultDebrisList, emptyBoxList);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ emptyBoxList.Add(newBoxA);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newBoxB.Valid)
|
|
|
+ {
|
|
|
+ List<Debris> newCandidateListB = new List<Debris>();
|
|
|
+
|
|
|
+ for (int i = 0; i < candidateList.Count; i++)
|
|
|
+ {
|
|
|
+ if (newBoxB.CanFill(candidateList[i]))
|
|
|
+ {
|
|
|
+ newCandidateListB.Add(candidateList[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ newCandidateListB.MySort(Debris.SortByWidth);
|
|
|
+
|
|
|
+ if (newCandidateListB.Count > 0)
|
|
|
+ {
|
|
|
+ Debris newDebris = newCandidateListB[0];
|
|
|
+
|
|
|
+ candidateList.Remove(newDebris);
|
|
|
+
|
|
|
+ newDebris.LowerLeft = debris.LowerRight;
|
|
|
+ resultDebrisList.Add(newDebris);
|
|
|
+
|
|
|
+ FillBox(false, newBoxB, newDebris, candidateList, resultDebrisList, emptyBoxList);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ emptyBoxList.Add(newBoxB);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected List<Debris> FillFirstBox(int textureIndex, List<Debris> rawDebrisList)
|
|
|
+ {
|
|
|
+ Box box = GetFirstBox(rawDebrisList);
|
|
|
+
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ List<Debris> debrisList = new List<Debris>(rawDebrisList);
|
|
|
+
|
|
|
+ debrisList.MySort(Debris.SortByWidth);
|
|
|
+
|
|
|
+ List<Debris> resultDebrisList = new List<Debris>();
|
|
|
+
|
|
|
+ Debris futileDebris = new Debris(0, null, 0, 0)
|
|
|
+ {
|
|
|
+ LowerLeft = new Vector2(),
|
|
|
+ };
|
|
|
+
|
|
|
+ List<Box> emptyBoxList = new List<Box>();
|
|
|
+
|
|
|
+ FillBox(true, box, futileDebris, debrisList, resultDebrisList, emptyBoxList);
|
|
|
+
|
|
|
+ List<JagBox> jagBoxList = CreateJagBox(emptyBoxList);
|
|
|
+
|
|
|
+ debrisList.MySort(Debris.SortByMax);
|
|
|
+
|
|
|
+ FillJagBox(debrisList, resultDebrisList, jagBoxList);
|
|
|
+
|
|
|
+ if (debrisList.Count == 0)
|
|
|
+ {
|
|
|
+ BuildTexture(textureIndex, box, resultDebrisList);
|
|
|
+
|
|
|
+ return debrisList;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int newLength = ExMath.NextPOT(box.Width + 1);
|
|
|
+
|
|
|
+ if (newLength > Script.MaxSize)
|
|
|
+ {
|
|
|
+ BuildTexture(textureIndex, box, resultDebrisList);
|
|
|
+
|
|
|
+ return debrisList;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ box = new Box(newLength, newLength, Vector2.zero);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected void FillJagBox(List<Debris> rawDebrisList, List<Debris> resultDebrisList, List<JagBox> jagBoxList)
|
|
|
+ {
|
|
|
+ if (jagBoxList.Count == 0)
|
|
|
+ {
|
|
|
+ throw new Exception("An error occured");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < jagBoxList.Count; i++)
|
|
|
+ {
|
|
|
+ for (int j = 0; j < rawDebrisList.Count; j++)
|
|
|
+ {
|
|
|
+ if (jagBoxList[i].CanFill(rawDebrisList[j]))
|
|
|
+ {
|
|
|
+ List<JagBox> newJagBoxList = jagBoxList[i].Fill(rawDebrisList[j]);
|
|
|
+
|
|
|
+ jagBoxList.AddRange(newJagBoxList);
|
|
|
+
|
|
|
+ resultDebrisList.Add(rawDebrisList[j]);
|
|
|
+
|
|
|
+ jagBoxList.RemoveAt(i--);
|
|
|
+
|
|
|
+ rawDebrisList.Remove(rawDebrisList[j]);
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected List<JagBox> CreateJagBox(List<Box> emptyBoxList)
|
|
|
+ {
|
|
|
+ List<JagBox> jagBoxList = new List<JagBox>();
|
|
|
+
|
|
|
+ List<Box> boxList = new List<Box>() { emptyBoxList[0]};
|
|
|
+
|
|
|
+ for (int i = 0; i < emptyBoxList.Count - 1; i++)
|
|
|
+ {
|
|
|
+ int x1 = (int)emptyBoxList[i].LowerRight.x;
|
|
|
+ int x2 = (int)emptyBoxList[i + 1].LowerLeft.x;
|
|
|
+
|
|
|
+ if (x1 == x2)
|
|
|
+ {
|
|
|
+ boxList.Add(emptyBoxList[i + 1]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ jagBoxList.Add(new JagBox(boxList));
|
|
|
+
|
|
|
+ boxList = new List<Box>();
|
|
|
+
|
|
|
+ boxList.Add(emptyBoxList[i + 1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ jagBoxList.Add(new JagBox(boxList));
|
|
|
+
|
|
|
+ return jagBoxList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected void BuildTexture(int textureIndex, Box box, List<Debris> resultDebrisList)
|
|
|
+ {
|
|
|
+ Texture2D texture2D = new Texture2D(box.Width, box.Height, Script.TextureFormat, false);
|
|
|
+
|
|
|
+ SpriteMetaData[] spriteMetaDatas = new SpriteMetaData[resultDebrisList.Count];
|
|
|
+
|
|
|
+ for (int i = 0; i < box.Width; i++)
|
|
|
+ {
|
|
|
+ for (int j = 0; j < box.Height; j++)
|
|
|
+ {
|
|
|
+ texture2D.SetPixel(i, j, new Color(0, 0, 0, 0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < resultDebrisList.Count; i++)
|
|
|
+ {
|
|
|
+ Debris debris = resultDebrisList[i];
|
|
|
+
|
|
|
+ Vector2 lowerLeft = debris.LowerLeft + new Vector2(Script.Padding, Script.Padding);
|
|
|
+
|
|
|
+ int width;
|
|
|
+ int height;
|
|
|
+
|
|
|
+ spriteMetaDatas[i].rect = debris.Rect;
|
|
|
+ spriteMetaDatas[i].pivot = debris.Pivot;
|
|
|
+ spriteMetaDatas[i].name = debris.Name;
|
|
|
+ spriteMetaDatas[i].border = debris.Border;
|
|
|
+ spriteMetaDatas[i].alignment = (int) SpriteAlignment.Custom;
|
|
|
+
|
|
|
+ width = debris.Width - Script.Padding*2;
|
|
|
+ height = debris.Height - Script.Padding*2;
|
|
|
+
|
|
|
+ for (int j = 0; j < width; j++)
|
|
|
+ {
|
|
|
+ for (int k = 0; k < height; k++)
|
|
|
+ {
|
|
|
+ texture2D.SetPixel((int) lowerLeft.x + j, (int) lowerLeft.y + k, debris.GetPixel(j, k));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ texture2D.Apply();
|
|
|
+
|
|
|
+
|
|
|
+ string buildName;
|
|
|
+
|
|
|
+ if (textureIndex == 0)
|
|
|
+ {
|
|
|
+ buildName = Script.BuildName + ".png";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buildName = Script.BuildName + textureIndex + ".png";
|
|
|
+ }
|
|
|
+
|
|
|
+ string assetPath = BuildPath + buildName;
|
|
|
+
|
|
|
+ File.WriteAllBytes(assetPath, texture2D.EncodeToPNG());
|
|
|
+
|
|
|
+ AssetDatabase.Refresh();
|
|
|
+
|
|
|
+
|
|
|
+ TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(assetPath);
|
|
|
+
|
|
|
+ textureImporter.spritesheet = spriteMetaDatas;
|
|
|
+ textureImporter.maxTextureSize = box.Width;
|
|
|
+ textureImporter.isReadable = true;
|
|
|
+ textureImporter.alphaIsTransparency = true;
|
|
|
+ textureImporter.textureType = TextureImporterType.Sprite;
|
|
|
+ textureImporter.spriteImportMode = SpriteImportMode.Multiple;
|
|
|
+
|
|
|
+ textureImporter.SaveAndReimport();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void PrepareBuildParameter()
|
|
|
+ {
|
|
|
+ BuildPath = Script.BuildPath.TrimEnd('/', '\\') + "/";
|
|
|
+
|
|
|
+ if (Script.MaxSize <= 0)
|
|
|
+ {
|
|
|
+ Script.MaxSize = 8192;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Script.MaxSize = ExMath.PrevPOT(Script.MaxSize);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Script.Padding < 0)
|
|
|
+ {
|
|
|
+ Script.Padding = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public override void OnInspectorGUI()
|
|
|
+ {
|
|
|
+ base.OnInspectorGUI();
|
|
|
+
|
|
|
+ if (GUILayout.Button("TempTest"))
|
|
|
+ {
|
|
|
+ #region
|
|
|
+
|
|
|
+ Box box1 = new Box(10, 10, new Vector2(0, 90));
|
|
|
+ Box box2 = new Box(20, 20, new Vector2(10, 80));
|
|
|
+ Box box3 = new Box(20, 40, new Vector2(30, 60));
|
|
|
+ Box box4 = new Box(20, 60, new Vector2(50, 40));
|
|
|
+ Box box5 = new Box(20, 80, new Vector2(70, 20));
|
|
|
+ Box box6 = new Box(10, 100, new Vector2(90, 0));
|
|
|
+
|
|
|
+ List<Box> emptyBoxList = new List<Box>();
|
|
|
+ emptyBoxList.Add(box1);
|
|
|
+ emptyBoxList.Add(box2);
|
|
|
+ emptyBoxList.Add(box3);
|
|
|
+ emptyBoxList.Add(box4);
|
|
|
+ emptyBoxList.Add(box5);
|
|
|
+ emptyBoxList.Add(box6);
|
|
|
+
|
|
|
+ List<JagBox> jagBoxList = CreateJagBox(emptyBoxList);
|
|
|
+
|
|
|
+ for (int i = 0; i < jagBoxList.Count; i++)
|
|
|
+ {
|
|
|
+ Debug.Log(jagBoxList[i].Width);
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+
|
|
|
+ if (GUILayout.Button("Test"))
|
|
|
+ {
|
|
|
+ PrepareBuildParameter();
|
|
|
+
|
|
|
+ List<Debris> tempDebrisList = CreateDebrisList();
|
|
|
+
|
|
|
+ if (tempDebrisList.Count == 0)
|
|
|
+ {
|
|
|
+ throw new Exception("TextureList is empty");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tempDebrisList.MyMax(Debris.MaxMinByLength) > Script.MaxSize)
|
|
|
+ {
|
|
|
+ throw new Exception("A texture's width or height is bigger than MaxSize");
|
|
|
+ }
|
|
|
+
|
|
|
+ int textureIndex = 0;
|
|
|
+
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ tempDebrisList = FillFirstBox(textureIndex++, tempDebrisList);
|
|
|
+
|
|
|
+ if (tempDebrisList.Count == 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|