public static Rect[] Spliter(Rect[] rects, int maxSize, int padding, ref Rect ret, int startWidth, int startHeight, bool resizeRect, bool isWHSame, int cellSize ) { int w = 1; int h = 1; if (resizeRect) { foreach (Rect rc in rects) { if (w < rc.width) w = (int)rc.width; if (h < rc.height) h = (int)rc.height; } w = Mathf.NextPowerOfTwo(w); h = Mathf.NextPowerOfTwo(h); } else { w = startWidth; h = startHeight; } while (true) { List<Rect> rcs = new List<Rect>(rects); RectSpliter spliter = new RectSpliter(new Rect(0, 0, w, h), cellSize); bool isAllocFail = false; for (int i = 0; i < rcs.Count; i++) { Rect tmp = rcs[i]; tmp.width += padding; tmp.height += padding; bool r = spliter.AllocRect(ref tmp); if (!r) { isAllocFail = true; break; } rcs[i] = tmp; } if (!isAllocFail) { ret = spliter.rect; return rcs.ToArray(); } else { if (!resizeRect) return null; if (!isWHSame) { if (w > h) h *= 2; else w *= 2; } else { w *= 2; h = w; } } if (w > maxSize || h > maxSize) return null; } return null; }
/// <summary> /// Pack sprites into a texture. Usually use to building atlas in runtime. /// The sprite's image texture should be readable. /// </summary> /// <param name="sprites">Array of sprites you want pack.</param> /// <param name="packSize">The target texture size.</param> /// <param name="mipmap">Not used.</param> /// <returns>Return true successed, false means sprites can not layout in the size of texture.</returns> public static bool PackSprites(Sprite[] sprites, int packSize, bool mipmap) { List <Sprite> sprs = new List <Sprite>(sprites); sprs.Sort(sortByHeight); sprs.Reverse(); List <Rect> rects = new List <Rect>(); foreach (Sprite item in sprs) { rects.Add(item.imageRect); } Rect retRc = new Rect(); Rect[] ret = RectSpliter.Spliter(rects.ToArray(), packSize, 1, ref retRc, packSize, packSize, false, true, 4); if (ret != null) { if (ret.Length > 0) { Texture2D tex = new Texture2D(packSize, packSize, TextureFormat.ARGB32, mipmap); Color32 c = new Color32(0, 0, 0, 0); Color32[] _buf = tex.GetPixels32(); for (int ci = 0; ci < _buf.Length; ci++) { _buf[ci] = c; } tex.SetPixels32(_buf); int i = 0; foreach (Rect rc in ret) { Sprite spr = sprs[i]; Rect src = new Rect( spr.imageRect.x, spr.image.height - spr.imageRect.y - spr.imageRect.height, spr.imageRect.width, spr.imageRect.height); Rect dst = new Rect( rc.x, tex.height - rc.y - spr.imageRect.height, spr.imageRect.width, spr.imageRect.height ); Color[] buf = spr.image.GetPixels((int)src.x, (int)src.y, (int)src.width, (int)src.height); tex.SetPixels((int)dst.x, (int)dst.y, (int)dst.width, (int)dst.height, buf); spr.image = tex; spr.atlas = null; spr.imageRect = new Rect(rc.x, rc.y, spr.imageRect.width, spr.imageRect.height); spr.Init(); i++; } tex.Apply(); return(true); } } return(false); }
public static Rect[] Spliter(Rect[] rects, int maxSize, int padding, ref Rect ret, int startWidth, int startHeight, bool resizeRect, bool isWHSame, int cellSize) { int w = 1; int h = 1; if (resizeRect) { foreach (Rect rc in rects) { if (w < rc.width) { w = (int)rc.width; } if (h < rc.height) { h = (int)rc.height; } } w = Mathf.NextPowerOfTwo(w); h = Mathf.NextPowerOfTwo(h); } else { w = startWidth; h = startHeight; } while (true) { List <Rect> rcs = new List <Rect>(rects); RectSpliter spliter = new RectSpliter(new Rect(0, 0, w, h), cellSize); bool isAllocFail = false; for (int i = 0; i < rcs.Count; i++) { Rect tmp = rcs[i]; tmp.width += padding; tmp.height += padding; bool r = spliter.AllocRect(ref tmp); if (!r) { isAllocFail = true; break; } rcs[i] = tmp; } if (!isAllocFail) { ret = spliter.rect; return(rcs.ToArray()); } else { if (!resizeRect) { return(null); } if (!isWHSame) { if (w > h) { h *= 2; } else { w *= 2; } } else { w *= 2; h = w; } } if (w > maxSize || h > maxSize) { return(null); } } return(null); }