mirror of
https://github.com/ocornut/imgui.git
synced 2026-08-21 06:41:09 +00:00
DrawList: added vertex offset 16-bit ImDrawIdx support for _AddPolyline
This commit is contained in:
@@ -859,8 +859,8 @@ float ImDrawList::_CalculateCenterBiasedOffset(float thickness)
|
||||
_IdxWritePtr += 3; \
|
||||
} (void)0
|
||||
|
||||
#define IM_POLYLINE_MITER_ANGLE_LIMIT (-0.9999619f) // cos(179.5)
|
||||
#define IM_POLYLINE_MITER_LIMIT (4.0f) // ~29 deg
|
||||
#define IM_POLYLINE_MITER_ANGLE_LIMIT (-0.9999619f) // cos(179.5)
|
||||
#define IM_POLYLINE_MITER_LIMIT (4.0f) // ~29 deg
|
||||
#define IM_POLYLINE_CONVEX_POLY_MAX_BEVELS (2) // (int)(360/floor(180-29))
|
||||
|
||||
// In debug builds the functions are likely not inlined, so inlined check is cheaper.
|
||||
@@ -872,6 +872,41 @@ float ImDrawList::_CalculateCenterBiasedOffset(float thickness)
|
||||
#define IM_IS_TRUNCATED(a) ImIsTruncated(a)
|
||||
#endif
|
||||
|
||||
// Called when the current vertex count for a polyline call would overflow the index range.
|
||||
// Commit the vertices so far, reserve new buffers, reset index, and duplicate the base vertices so that they can be accessed by the new indices.
|
||||
static void SplitPolyline(ImDrawList* draw_list, int& start_idx_offset, int& start_vtx_offset, int& base_idx)
|
||||
{
|
||||
// Make copy of current base points.
|
||||
ImDrawVert base0 = draw_list->VtxBuffer.Data[draw_list->_CmdHeader.VtxOffset + base_idx + 0];
|
||||
ImDrawVert base1 = draw_list->VtxBuffer.Data[draw_list->_CmdHeader.VtxOffset + base_idx + 1];
|
||||
|
||||
// Release unused verts and indices.
|
||||
const int cur_idx_offset = (int)(draw_list->_IdxWritePtr - draw_list->IdxBuffer.Data);
|
||||
const int cur_vtx_offset = (int)(draw_list->_VtxWritePtr - draw_list->VtxBuffer.Data);
|
||||
const int remaining_idx_count = draw_list->IdxBuffer.Size - cur_idx_offset;
|
||||
const int remaining_vtx_count = draw_list->VtxBuffer.Size - cur_vtx_offset;
|
||||
|
||||
IM_ASSERT(remaining_vtx_count >= 0 && remaining_idx_count >= 0);
|
||||
draw_list->PrimUnreserve(remaining_idx_count, remaining_vtx_count);
|
||||
|
||||
// Reserve remaining verts and indices.
|
||||
draw_list->PrimReserve(remaining_idx_count, remaining_vtx_count + 2); // +2 for the duplicated base points.
|
||||
|
||||
start_idx_offset = cur_idx_offset;
|
||||
start_vtx_offset = cur_vtx_offset;
|
||||
base_idx = (int)draw_list->_VtxCurrentIdx;
|
||||
|
||||
// Duplicate base points
|
||||
draw_list->_VtxWritePtr[0] = base0;
|
||||
draw_list->_VtxWritePtr[1] = base1;
|
||||
draw_list->_VtxWritePtr += 2;
|
||||
draw_list->_VtxCurrentIdx += 2;
|
||||
}
|
||||
|
||||
#define IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(new_verts) \
|
||||
if (sizeof(ImDrawIdx) == 2 && (Flags & ImDrawListFlags_AllowVtxOffset) && _VtxCurrentIdx + (new_verts) > (1 << 16)) IM_UNLIKELY \
|
||||
SplitPolyline(this, start_idx_offset, start_vtx_offset, base_idx)
|
||||
|
||||
void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_lengths, const int points_count, ImU32 col, float thickness, ImDrawFlags flags, const ImVec4& tex_uvs, float fringe)
|
||||
{
|
||||
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
|
||||
@@ -924,9 +959,10 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
|
||||
PrimReserve(idx_count, vtx_count);
|
||||
|
||||
ImDrawVert* start_vtx_ptr = _VtxWritePtr;
|
||||
ImDrawIdx* start_idx_ptr = _IdxWritePtr;
|
||||
|
||||
// These offsets change if we need to create new draw command mid shape.
|
||||
const int first_vtx_offset = (int)(_VtxWritePtr - VtxBuffer.Data);
|
||||
int start_vtx_offset = (int)(_VtxWritePtr - VtxBuffer.Data);
|
||||
int start_idx_offset = (int)(_IdxWritePtr - IdxBuffer.Data);
|
||||
int base_idx = (int)_VtxCurrentIdx;
|
||||
|
||||
ImVec2 pa, pb, dir;
|
||||
@@ -956,6 +992,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
|
||||
if (flags & ImDrawFlags_NoAAEnds)
|
||||
{
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(2);
|
||||
|
||||
base_idx = (int)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(p1.x - n1.x * thickness0, p1.y - n1.y * thickness0, uv0, col);
|
||||
IM_APPEND_VTX(p1.x + n1.x * thickness1, p1.y + n1.y * thickness1, uv1, col);
|
||||
@@ -967,6 +1005,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
pb.x = p1.x + dir.x * half_aa;
|
||||
pb.y = p1.y + dir.y * half_aa;
|
||||
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(4);
|
||||
|
||||
base_idx = (int)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(pa.x - n1.x * thickness0, pa.y - n1.y * thickness0, uv0, col_trans);
|
||||
IM_APPEND_VTX(pa.x + n1.x * thickness1, pa.y + n1.y * thickness1, uv1, col_trans);
|
||||
@@ -989,6 +1029,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
len_sqr1 = sqr_lengths[points_count-1];
|
||||
|
||||
// This will be filled later, allocate space.
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(2);
|
||||
|
||||
base_idx = (int)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(0, 0, uv0, col);
|
||||
IM_APPEND_VTX(0, 0, uv1, col);
|
||||
@@ -1012,6 +1054,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
const float miter_offset_y = (n0.y + n1.y) * miter_scale_factor;
|
||||
|
||||
// Miter
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(2);
|
||||
|
||||
const int next_base_idx = (ImDrawIdx)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(p1.x - miter_offset_x * thickness0, p1.y - miter_offset_y * thickness0, uv0, col); // 2
|
||||
IM_APPEND_VTX(p1.x + miter_offset_x * thickness1, p1.y + miter_offset_y * thickness1, uv1, col); // 3
|
||||
@@ -1074,6 +1118,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
// Bevel
|
||||
if (sin_theta < 0.0f)
|
||||
{
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(4);
|
||||
|
||||
IM_APPEND_VTX(p1.x - (bn_x + sd_x) * thickness0, p1.y - (bn_y + sd_y) * thickness0, uv0, col); // 2
|
||||
IM_APPEND_VTX(p1.x, p1.y, uv2, col); // 3
|
||||
const int next_base_idx = (ImDrawIdx)_VtxCurrentIdx;
|
||||
@@ -1091,6 +1137,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(4);
|
||||
|
||||
IM_APPEND_VTX(p1.x + (bn_x + sd_x) * thickness1, p1.y + (bn_y + sd_y) * thickness1, uv1, col); // 2
|
||||
IM_APPEND_VTX(p1.x, p1.y, uv2, col); // 3
|
||||
const int next_base_idx = (ImDrawIdx)_VtxCurrentIdx;
|
||||
@@ -1109,6 +1157,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(4);
|
||||
|
||||
// Miter
|
||||
const int next_base_idx = (ImDrawIdx)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(p1.x - miter_offset_x * thickness0, p1.y - miter_offset_y * thickness0, uv0, col); // 2
|
||||
@@ -1142,6 +1192,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
|
||||
if (flags & ImDrawFlags_NoAAEnds)
|
||||
{
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(2);
|
||||
|
||||
IM_APPEND_VTX(p1.x - n1.x * thickness0, p1.y - n1.y * thickness0, uv0, col);
|
||||
IM_APPEND_VTX(p1.x + n1.x * thickness1, p1.y + n1.y * thickness1, uv1, col);
|
||||
|
||||
@@ -1156,6 +1208,8 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
pb.x = p1.x + dir.x * half_aa;
|
||||
pb.y = p1.y + dir.y * half_aa;
|
||||
|
||||
IM_ADD_POLYLINE_HANDLE_VTX_OFFSET_OVERFLOW(4);
|
||||
|
||||
int next_base_idx = (int)_VtxCurrentIdx;
|
||||
IM_APPEND_VTX(pa.x - n1.x * thickness0, pa.y - n1.y * thickness0, uv0, col);
|
||||
IM_APPEND_VTX(pa.x + n1.x * thickness1, pa.y + n1.y * thickness1, uv1, col);
|
||||
@@ -1176,15 +1230,17 @@ void ImDrawList::_AddPolyline(const ImVec2* points, ImVec2* normals, float* sqr_
|
||||
else
|
||||
{
|
||||
// Connect the path.
|
||||
start_vtx_ptr[0] = VtxBuffer.Data[_CmdHeader.VtxOffset + base_idx+0];
|
||||
start_vtx_ptr[1] = VtxBuffer.Data[_CmdHeader.VtxOffset + base_idx+1];
|
||||
VtxBuffer.Data[first_vtx_offset + 0] = VtxBuffer.Data[_CmdHeader.VtxOffset + base_idx+0];
|
||||
VtxBuffer.Data[first_vtx_offset + 1] = VtxBuffer.Data[_CmdHeader.VtxOffset + base_idx+1];
|
||||
}
|
||||
|
||||
// Restore unused memory
|
||||
const int vtx_used = (int)(_VtxWritePtr - start_vtx_ptr);
|
||||
const int idx_used = (int)(_IdxWritePtr - start_idx_ptr);
|
||||
IM_ASSERT(vtx_used <= vtx_count && idx_used <= idx_count);
|
||||
PrimUnreserve(idx_count - idx_used, vtx_count - vtx_used);
|
||||
const int cur_idx_offset = (int)(_IdxWritePtr - IdxBuffer.Data);
|
||||
const int cur_vtx_offset = (int)(_VtxWritePtr - VtxBuffer.Data);
|
||||
const int remaining_idx_count = IdxBuffer.Size - cur_idx_offset;
|
||||
const int remaining_vtx_count = VtxBuffer.Size - cur_vtx_offset;
|
||||
IM_ASSERT_PARANOID(remaining_idx_count >= 0 && remaining_vtx_count >= 0);
|
||||
PrimUnreserve(remaining_idx_count, remaining_vtx_count);
|
||||
}
|
||||
|
||||
static ImU32 ImAlphaMultiply(ImU32 col, float alpha_mul)
|
||||
@@ -1243,8 +1299,6 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
||||
thickness = _FringeScale;
|
||||
}
|
||||
|
||||
// TODO: support splitting very long lines to multiple draw calls.
|
||||
|
||||
// Allocate data for temp buffers
|
||||
_Data->TempBuffer.reserve_discard(points_count * 2);
|
||||
ImVec2* normals = _Data->TempBuffer.Data;
|
||||
|
||||
Reference in New Issue
Block a user