public bool Add(NativeAPI.stbrp_rect rect) { if (rect.w > m_atlasSize || rect.h > m_atlasSize) { if (IsGrowable()) { Realloc(Mathf.Max(rect.w, rect.h)); } else { throw new Exception(); } } var requireArea = rect.w * rect.h; var totalArea = m_atlasSize * m_atlasSize; if (totalArea - m_usedArea - requireArea <= 0) { return(false); } RETRY: fixed(NativeAPI.stbrp_context *ctx_ = &m_ctx) { NativeAPI.stbrp_pack_rects(ctx_, &rect, 1); } if (rect.was_packed != 0) { var maxx = rect.x + rect.w; var maxy = rect.y + rect.h; if (maxx > m_usedWidth) { m_usedWidth = maxx; } if (maxy > m_usedHeight) { m_usedHeight = maxy; } m_usedArea += requireArea; m_packedRects.Add(rect); return(true); } else { if (IsGrowable()) { Realloc(m_atlasSize << 1); goto RETRY; } } return(false); }
public void Realloc(int maxSize) { maxSize = MathLib.CeilPowerOfTwo(maxSize); if (maxSize != m_atlasSize) { if (m_pool != null) { m_poolHandle.Free(); } m_usedWidth = 0; m_usedHeight = 0; m_usedArea = 0; m_atlasSize = maxSize; m_pool = new NativeAPI.stbrp_node[m_atlasSize * 4]; UDebug.Assert(m_pool != null && m_pool.Length > 0); m_poolHandle = GCHandle.Alloc(m_pool, GCHandleType.Pinned); var packedRects = m_packedRects; m_packedRects = new List <NativeAPI.stbrp_rect>(); m_ctx = new NativeAPI.stbrp_context(); fixed(NativeAPI.stbrp_context *_ctx = &m_ctx) { NativeAPI.stbrp_init_target(_ctx, m_atlasSize, m_atlasSize, (NativeAPI.stbrp_node *)m_poolHandle.AddrOfPinnedObject(), m_pool.Length); NativeAPI.stbrp_setup_allow_out_of_mem(_ctx, 1); } for (int i = 0; i < packedRects.Count; ++i) { var rect = packedRects[i]; var _rect = new NativeAPI.stbrp_rect(); _rect.w = rect.w; _rect.h = rect.h; _rect.id = rect.id; if (!Add(rect)) { UDebug.LogError("Realloc failed!"); break; } } } }