private IntegerRectangle InsertArea(int width, int height, out int index) { IntegerRectangle result = null; IntegerRectangle freeArea = null; DynamicAtlasPage page = null; for (int i = 0; i < m_PageList.Count; i++) { int fIndex = m_PageList[i].GetFreeAreaIndex(width, height, m_Padding); if (fIndex >= 0) { page = m_PageList[i]; freeArea = page.freeAreasList[fIndex]; break; } } if (freeArea == null) { Log.Error("No Free Area----Create New Page"); page = CreateNewPage(); freeArea = page.freeAreasList[0]; } result = IntegerRectangle.Create(freeArea.x, freeArea.y, width, height); GenerateNewFreeAreas(result, page); page.RemoveFreeArea(freeArea); index = page.index; return(result); }
private void GenerateNewFreeAreas(IntegerRectangle target, DynamicAtlasPage page) { int x = target.x; int y = target.y; int right = target.right + 1 + m_Padding; int top = target.top + 1 + m_Padding; IntegerRectangle targetWithPadding = null; if (m_Padding == 0) { targetWithPadding = target; } for (int i = page.freeAreasList.Count - 1; i >= 0; i--) { IntegerRectangle area = page.freeAreasList[i]; if (!(x >= area.right || right <= area.x || y >= area.top || top <= area.y)) { if (targetWithPadding == null) { targetWithPadding = IntegerRectangle.Create(target.x, target.y, target.width + m_Padding, target.height + m_Padding); } GenerateDividedAreas(targetWithPadding, area, m_WaitAddNewAreaList); IntegerRectangle topOfStack = page.freeAreasList.Pop(); if (i < page.freeAreasList.Count) { // Move the one on the top to the freed position page.freeAreasList[i] = topOfStack; } } } if (targetWithPadding != null && targetWithPadding != target) { targetWithPadding.Dispose(); } FilterSelfSubAreas(m_WaitAddNewAreaList); while (m_WaitAddNewAreaList.Count > 0) { var free = m_WaitAddNewAreaList.Pop(); page.AddFreeArea(free); } // if (target.right > m_PackedWidth) // m_PackedWidth = target.right; // if (target.top > m_PackedHeight) // m_PackedHeight = target.top; }
/// <summary> /// 搜寻空白区域 /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public int GetFreeAreaIndex(int width, int height, int padding) { if (width > m_Width || height > m_Height) { Log.Error("To Large Texture for atlas"); return(-1); } IntegerRectangle best = IntegerRectangle.Create(m_Width + 1, m_Height + 1, 0, 0); int index = -1; int paddedWidth = width + padding; int paddedHeight = height + padding; for (int i = m_FreeAreasList.Count - 1; i >= 0; i--) { IntegerRectangle free = m_FreeAreasList[i]; // if (free.x < width || free.y < height) { if (free.x < best.x && paddedWidth <= free.width && paddedHeight <= free.height)//如果这个Free大小可以容纳目标大小的话 { index = i; if ((paddedWidth == free.width && free.width <= free.height && free.right < m_Width) || (paddedHeight == free.height && free.height <= free.width))//如果这个区域正好可以放得下 { break; } best = free; } else { // Outside the current packed area, no padding required if (free.x < best.x && width <= free.width && height <= free.height)//如果不算padding距离也可以放得下的话,也可以放进去 { index = i; if ((width == free.width && free.width <= free.height && free.right < m_Width) || (height == free.height && free.height <= free.width)) { break; } best = free; } } } } return(index); }
private void GenerateDividedAreas(IntegerRectangle divider, IntegerRectangle area, List <IntegerRectangle> results) { int count = 0; int rightDelta = area.right - divider.right; if (rightDelta > 0) { results.Add(IntegerRectangle.Create(divider.right, area.y, rightDelta, area.height)); count++; } int leftDelta = divider.x - area.x; if (leftDelta > 0) { results.Add(IntegerRectangle.Create(area.x, area.y, leftDelta, area.height)); count++; } int bottomDelta = area.top - divider.top; if (bottomDelta > 0) { results.Add(IntegerRectangle.Create(area.x, divider.top, area.width, bottomDelta)); count++; } int topDelta = divider.y - area.y; if (topDelta > 0) { results.Add(IntegerRectangle.Create(area.x, area.y, area.width, topDelta)); count++; } if (count == 0 && (divider.width < area.width || divider.height < area.height)) { // Only touching the area, store the area itself results.Add(area); } else { area.Dispose(); } }
public static DynamicAtlasPage OnCreate(int index, int width, int height, Color32[] tempColor) { var res = MonoPool.Instance.Fetch(typeof(DynamicAtlasPage)) as DynamicAtlasPage; if (res.m_Width != width || res.m_Height == height) { res.SetData(width, height); } if (tempColor != null) { res.m_Texture.SetPixels32(0, 0, width, height, tempColor); res.m_Texture.Apply(false); } res.m_Texture.name = string.Format("DynamicAtlas-{0}*{1}-{2}", width, height, index); res.m_Index = index; var area = IntegerRectangle.Create(0, 0, res.m_Width, res.m_Height); res.m_FreeAreasList.Add(area); return(res); }