Skip to content

Commit

Permalink
ImDrawList: DIrect implementation of AddRect() (WIP) (fixup)
Browse files Browse the repository at this point in the history
  • Loading branch information
thedmd committed Sep 28, 2024
1 parent 66a053c commit 51d7012
Showing 1 changed file with 293 additions and 2 deletions.
295 changes: 293 additions & 2 deletions imgui_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3429,7 +3429,299 @@ void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, fl
if ((col & IM_COL32_A_MASK) == 0 || thickness <= 0.0f) IM_UNLIKELY
return;

if (GImGui->IO.KeyCtrl || (flags & 0x80000000u))
if (flags & 0x40000000u)
{
const ImVec2 uv = this->_Data->TexUvWhitePixel;
const ImVec2 a = ImVec2(p_min.x + 0.50f, p_min.y + 0.50f);
const ImVec2 b = ImVec2(p_max.x - 0.50f, p_max.y - 0.50f);

if (flags & ImDrawFlags_RoundCornersNone) IM_UNLIKELY
rounding = 0.0f;

if (rounding > 0.0f) IM_UNLIKELY // with any rounded corner
{
const float min_inner_offset_x = ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f;
const float min_inner_offset_y = ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f;

int path_count = 0;
ImVec2 path_offsets[4];
ImU32 path_colors[4];
if (this->Flags & ImDrawListFlags_AntiAliasedLines) IM_LIKELY
{
const float screen_thickness = thickness / this->_FringeScale;

if (screen_thickness < 1.0f) IM_UNLIKELY
{
// Blend color alpha using fringe
const ImU32 alpha = (ImU32)(((col >> IM_COL32_A_SHIFT) & 0xFF) * screen_thickness);
if (alpha == 0) IM_UNLIKELY
return;

col = (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
}

if (screen_thickness <= 1.0f) IM_LIKELY // thin
{
path_offsets[0].x = thickness;
path_offsets[0].y = thickness;
path_offsets[1].x = 0.0f;
path_offsets[1].y = 0.0f;
path_offsets[2].x = -ImMin(thickness, min_inner_offset_x);
path_offsets[2].y = -ImMin(thickness, min_inner_offset_y);
path_colors[0] = col & ~IM_COL32_A_MASK;
path_colors[1] = col;
path_colors[2] = col & ~IM_COL32_A_MASK;
path_count = 3;
}
else IM_UNLIKELY // thick
{
path_offsets[0].x = (thickness + this->_FringeScale) * 0.5f;
path_offsets[0].y = (thickness + this->_FringeScale) * 0.5f;
path_offsets[1].x = (thickness - this->_FringeScale) * 0.5f;
path_offsets[1].y = (thickness - this->_FringeScale) * 0.5f;
path_offsets[2].x = -ImMin(path_offsets[1].x, min_inner_offset_x);
path_offsets[2].y = -ImMin(path_offsets[1].y, min_inner_offset_y);
path_offsets[3].x = -ImMin(path_offsets[0].x, min_inner_offset_x);
path_offsets[3].y = -ImMin(path_offsets[0].y, min_inner_offset_y);
path_colors[0] = col & ~IM_COL32_A_MASK;
path_colors[1] = col;
path_colors[2] = col;
path_colors[3] = col & ~IM_COL32_A_MASK;
path_count = 4;
}
}
else IM_UNLIKELY
{
path_offsets[0].x = thickness * 0.5f;
path_offsets[0].y = thickness * 0.5f;
path_offsets[1].x = -ImMin(path_offsets[0].x, min_inner_offset_x);
path_offsets[1].y = -ImMin(path_offsets[0].y, min_inner_offset_y);
path_colors[0] = col;
path_colors[1] = col;
path_count = 2;
}

flags = FixRectCornerFlags(flags);

this->_PathArcToFastEx(ImVec2(0.0f, 0.0f), 1.0f, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 4, IM_DRAWLIST_ARCFAST_SAMPLE_MAX / ImMax(this->_CalcCircleAutoSegmentCount(rounding), 1));
const int segment_count = this->_Path.Size - 1;

const int max_vtx_count = 4 * (segment_count + 1) * path_count;
const int max_idx_count = 4 * segment_count * path_count * 2 * 3;
IM_POLYLINE_PRIM_RESERVE(max_idx_count, max_vtx_count);

int path_size = 0;

//if (flags & ImDrawFlags_RoundCornersTopLeft) IM_LIKELY
//{
// for (int i = 0; i < this->_Path.Size; i++)
// {
// for (int j = 0; j < path_count; j++)
// {
// //IM_POLYLINE_VERTEX(j, a.x + path_offsets[j].x * this->_Path[i].x * 2.0f, a.y + rounding - path_offsets[j].y * this->_Path[i].y * 2.0f, uv, path_colors[j]);
// IM_POLYLINE_VERTEX(j, a.x + path_offsets[j].x * rounding * this->_Path[i].x, a.y + path_offsets[j].y * rounding * this->_Path[i].y, uv, path_colors[j]);
// }

// IM_POLYLINE_PRIM_VTX_WRITE += path_count;
// ++path_size;
// }
//}
//else
{
for (int j = 0; j < path_count; j++)
{
IM_POLYLINE_VERTEX(j, a.x + path_offsets[j].x, a.y + path_offsets[j].y, uv, path_colors[j]);
}

IM_POLYLINE_PRIM_VTX_WRITE += path_count;
++path_size;
}


{
for (int j = 0; j < path_count; j++)
{
IM_POLYLINE_VERTEX(j, b.x - path_offsets[j].x, a.y + path_offsets[j].y, uv, path_colors[j]);
}

IM_POLYLINE_PRIM_VTX_WRITE += path_count;
++path_size;
}

{
for (int j = 0; j < path_count; j++)
{
IM_POLYLINE_VERTEX(j, b.x - path_offsets[j].x, b.y - path_offsets[j].y, uv, path_colors[j]);
}

IM_POLYLINE_PRIM_VTX_WRITE += path_count;
++path_size;
}

{
for (int j = 0; j < path_count; j++)
{
IM_POLYLINE_VERTEX(j, a.x + path_offsets[j].x, b.y - path_offsets[j].y, uv, path_colors[j]);
}

IM_POLYLINE_PRIM_VTX_WRITE += path_count;
++path_size;
}

const int strip_count = path_count - 1;
const int vtx_count = path_size * path_count;

IM_POLYLINE_TRIANGLE_BEGIN(path_size * strip_count * 2 * 3);
for (int i = 0; i < path_size; ++i)
{
for (int j = 0; j < strip_count; j++)
{
IM_POLYLINE_TRIANGLE(i * j * 2 + 0, i * path_count + j + 0, i * path_count + j + 1, i * path_count + j + path_count + 1);
IM_POLYLINE_TRIANGLE(i * j * 2 + 1, i * path_count + j + 0, i * path_count + j + path_count + 1, i * path_count + j + path_count + 0);
}
}
IM_POLYLINE_TRIANGLE_END(path_size * strip_count * 2 * 3);

IM_POLYLINE_PRIM_IDX_BASE += vtx_count;

for (int j = 0; j < (path_count - 1) * 6; j++)
{
if (IM_POLYLINE_PRIM_IDX_WRITE[-j - 1] >= IM_POLYLINE_PRIM_IDX_BASE)
IM_POLYLINE_PRIM_IDX_WRITE[-j - 1] -= vtx_count;
}

IM_POLYLINE_PRIM_COMMIT();

this->_Path.Size = 0;
}
else IM_LIKELY
{
if (this->Flags & ImDrawListFlags_AntiAliasedLines) IM_LIKELY
{
const float screen_thickness = thickness / this->_FringeScale;
const int integer_thickness = (int)screen_thickness;
const float fractional_thickness = screen_thickness - integer_thickness;

const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f);

if (screen_thickness < 1.0f) IM_UNLIKELY
{
// Blend color alpha using fringe
const ImU32 alpha = (ImU32)(((col >> IM_COL32_A_SHIFT) & 0xFF) * screen_thickness);
if (alpha == 0) IM_UNLIKELY
return;

col = (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
}

if (use_texture) IM_LIKELY
{
const float outer_offset = thickness * 0.5f + this->_FringeScale;
const float inner_offset_x = ImMin(outer_offset, ImFabs(b.x - a.x) * 0.5f - 1.0f);
const float inner_offset_y = ImMin(outer_offset, ImFabs(b.y - a.y) * 0.5f - 1.0f);
const ImVec4 tex_uvs = _Data->TexUvLines[integer_thickness];
const ImVec2 uv_outer = ImVec2(tex_uvs.x, tex_uvs.y);
const ImVec2 uv_inner = ImVec2(tex_uvs.z, tex_uvs.w);

IM_POLYLINE_PRIM_RESERVE(24, 8);

IM_POLYLINE_VERTEX(0, a.x - outer_offset, a.y - outer_offset, uv_outer, col); IM_POLYLINE_VERTEX(1, a.x + inner_offset_x, a.y + inner_offset_y, uv_inner, col);
IM_POLYLINE_VERTEX(2, b.x + outer_offset, a.y - outer_offset, uv_outer, col); IM_POLYLINE_VERTEX(3, b.x - inner_offset_x, a.y + inner_offset_y, uv_inner, col);
IM_POLYLINE_VERTEX(4, b.x + outer_offset, b.y + outer_offset, uv_outer, col); IM_POLYLINE_VERTEX(5, b.x - inner_offset_x, b.y - inner_offset_y, uv_inner, col);
IM_POLYLINE_VERTEX(6, a.x - outer_offset, b.y + outer_offset, uv_outer, col); IM_POLYLINE_VERTEX(7, a.x + inner_offset_x, b.y - inner_offset_y, uv_inner, col);

IM_POLYLINE_TRIANGLE_BEGIN(24);
IM_POLYLINE_TRIANGLE(0, 0, 1, 3); IM_POLYLINE_TRIANGLE(1, 0, 3, 2);
IM_POLYLINE_TRIANGLE(2, 2, 3, 5); IM_POLYLINE_TRIANGLE(3, 2, 5, 4);
IM_POLYLINE_TRIANGLE(4, 4, 5, 7); IM_POLYLINE_TRIANGLE(5, 4, 7, 6);
IM_POLYLINE_TRIANGLE(6, 6, 7, 1); IM_POLYLINE_TRIANGLE(7, 6, 1, 0);
IM_POLYLINE_TRIANGLE_END(24);

IM_POLYLINE_VTX_COMMIT(8);

IM_POLYLINE_PRIM_COMMIT();
}
else if (screen_thickness > 1.0f) IM_UNLIKELY
{
const float outer_edge_offset = (thickness + this->_FringeScale) * 0.5f;
const float outer_core_offset = (thickness - this->_FringeScale) * 0.5f;
const float inner_core_offset_x = ImMin(outer_core_offset, ImFabs(b.x - a.x) * 0.5f - 1.0f);
const float inner_core_offset_y = ImMin(outer_core_offset, ImFabs(b.y - a.y) * 0.5f - 1.0f);
const float inner_edge_offset_x = ImMin(outer_edge_offset, ImFabs(b.x - a.x) * 0.5f - 1.0f);
const float inner_edge_offset_y = ImMin(outer_edge_offset, ImFabs(b.y - a.y) * 0.5f - 1.0f);
const ImU32 outer_color = col & ~IM_COL32_A_MASK;

IM_POLYLINE_PRIM_RESERVE(72, 16);

IM_POLYLINE_VERTEX( 0, a.x - outer_edge_offset, a.y - outer_edge_offset, uv, outer_color); IM_POLYLINE_VERTEX( 1, a.x - outer_core_offset, a.y - outer_core_offset, uv, col); IM_POLYLINE_VERTEX( 2, a.x + inner_core_offset_x, a.y + inner_core_offset_y, uv, col); IM_POLYLINE_VERTEX( 3, a.x + inner_edge_offset_x, a.y + inner_edge_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX( 4, b.x + outer_edge_offset, a.y - outer_edge_offset, uv, outer_color); IM_POLYLINE_VERTEX( 5, b.x + outer_core_offset, a.y - outer_core_offset, uv, col); IM_POLYLINE_VERTEX( 6, b.x - inner_core_offset_x, a.y + inner_core_offset_y, uv, col); IM_POLYLINE_VERTEX( 7, b.x - inner_edge_offset_x, a.y + inner_edge_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX( 8, b.x + outer_edge_offset, b.y + outer_edge_offset, uv, outer_color); IM_POLYLINE_VERTEX( 9, b.x + outer_core_offset, b.y + outer_core_offset, uv, col); IM_POLYLINE_VERTEX(10, b.x - inner_core_offset_x, b.y - inner_core_offset_y, uv, col); IM_POLYLINE_VERTEX(11, b.x - inner_edge_offset_x, b.y - inner_edge_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX(12, a.x - outer_edge_offset, b.y + outer_edge_offset, uv, outer_color); IM_POLYLINE_VERTEX(13, a.x - outer_core_offset, b.y + outer_core_offset, uv, col); IM_POLYLINE_VERTEX(14, a.x + inner_core_offset_x, b.y - inner_core_offset_y, uv, col); IM_POLYLINE_VERTEX(15, a.x + inner_edge_offset_x, b.y - inner_edge_offset_y, uv, outer_color);

IM_POLYLINE_TRIANGLE_BEGIN(72);
IM_POLYLINE_TRIANGLE( 0, 0, 5, 4); IM_POLYLINE_TRIANGLE( 1, 0, 1, 5); IM_POLYLINE_TRIANGLE( 2, 1, 6, 5); IM_POLYLINE_TRIANGLE( 3, 1, 2, 6); IM_POLYLINE_TRIANGLE( 4, 2, 7, 6); IM_POLYLINE_TRIANGLE( 5, 2, 3, 7);
IM_POLYLINE_TRIANGLE( 6, 4, 9, 8); IM_POLYLINE_TRIANGLE( 7, 4, 5, 9); IM_POLYLINE_TRIANGLE( 8, 5, 10, 9); IM_POLYLINE_TRIANGLE( 9, 5, 6, 10); IM_POLYLINE_TRIANGLE(10, 6, 11, 10); IM_POLYLINE_TRIANGLE(11, 6, 7, 11);
IM_POLYLINE_TRIANGLE(12, 8, 13, 12); IM_POLYLINE_TRIANGLE(13, 8, 9, 13); IM_POLYLINE_TRIANGLE(14, 9, 14, 13); IM_POLYLINE_TRIANGLE(15, 9, 10, 14); IM_POLYLINE_TRIANGLE(16, 10, 15, 14); IM_POLYLINE_TRIANGLE(17, 10, 11, 15);
IM_POLYLINE_TRIANGLE(18, 12, 1, 0); IM_POLYLINE_TRIANGLE(19, 12, 13, 1); IM_POLYLINE_TRIANGLE(20, 13, 2, 1); IM_POLYLINE_TRIANGLE(21, 13, 14, 2); IM_POLYLINE_TRIANGLE(22, 14, 3, 2); IM_POLYLINE_TRIANGLE(23, 14, 15, 3);
IM_POLYLINE_TRIANGLE_END(72);

IM_POLYLINE_VTX_COMMIT(16);

IM_POLYLINE_PRIM_COMMIT();
}
else IM_LIKELY
{
const float outer_offset = thickness;
const float inner_offset_x = ImMin(outer_offset, ImFabs(b.x - a.x) * 0.5f - 1.0f);
const float inner_offset_y = ImMin(outer_offset, ImFabs(b.y - a.y) * 0.5f - 1.0f);
const ImU32 outer_color = col & ~IM_COL32_A_MASK;

IM_POLYLINE_PRIM_RESERVE(48, 12);

IM_POLYLINE_VERTEX(0, a.x - outer_offset, a.y - outer_offset, uv, outer_color); IM_POLYLINE_VERTEX( 1, a.x, a.y, uv, col); IM_POLYLINE_VERTEX( 2, a.x + inner_offset_x, a.y + inner_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX(3, b.x + outer_offset, a.y - outer_offset, uv, outer_color); IM_POLYLINE_VERTEX( 4, b.x, a.y, uv, col); IM_POLYLINE_VERTEX( 5, b.x - inner_offset_x, a.y + inner_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX(6, b.x + outer_offset, b.y + outer_offset, uv, outer_color); IM_POLYLINE_VERTEX( 7, b.x, b.y, uv, col); IM_POLYLINE_VERTEX( 8, b.x - inner_offset_x, b.y - inner_offset_y, uv, outer_color);
IM_POLYLINE_VERTEX(9, a.x - outer_offset, b.y + outer_offset, uv, outer_color); IM_POLYLINE_VERTEX(10, a.x, b.y, uv, col); IM_POLYLINE_VERTEX(11, a.x + inner_offset_x, b.y - inner_offset_y, uv, outer_color);

IM_POLYLINE_TRIANGLE_BEGIN(48);
IM_POLYLINE_TRIANGLE( 0, 0, 4, 3); IM_POLYLINE_TRIANGLE( 1, 0, 1, 4); IM_POLYLINE_TRIANGLE( 2, 1, 5, 4); IM_POLYLINE_TRIANGLE( 3, 1, 2, 5);
IM_POLYLINE_TRIANGLE( 4, 3, 7, 6); IM_POLYLINE_TRIANGLE( 5, 3, 4, 7); IM_POLYLINE_TRIANGLE( 6, 4, 8, 7); IM_POLYLINE_TRIANGLE( 7, 4, 5, 8);
IM_POLYLINE_TRIANGLE( 8, 6, 10, 9); IM_POLYLINE_TRIANGLE( 9, 6, 7, 10); IM_POLYLINE_TRIANGLE(10, 7, 11, 10); IM_POLYLINE_TRIANGLE(11, 7, 8, 11);
IM_POLYLINE_TRIANGLE(12, 9, 1, 0); IM_POLYLINE_TRIANGLE(13, 9, 10, 1); IM_POLYLINE_TRIANGLE(14, 10, 2, 1); IM_POLYLINE_TRIANGLE(15, 10, 11, 2);
IM_POLYLINE_TRIANGLE_END(48);

IM_POLYLINE_VTX_COMMIT(12);

IM_POLYLINE_PRIM_COMMIT();
}
}
else
{
const float outer_offset = thickness * 0.5f;
const float inner_offset_x = ImMin(outer_offset, ImFabs(b.x - a.x) * 0.5f - 1.0f);
const float inner_offset_y = ImMin(outer_offset, ImFabs(b.y - a.y) * 0.5f - 1.0f);

IM_POLYLINE_PRIM_RESERVE(24, 8);

IM_POLYLINE_VERTEX(0, a.x - outer_offset, a.y - outer_offset, uv, col); IM_POLYLINE_VERTEX(1, a.x + inner_offset_x, a.y + inner_offset_y, uv, col);
IM_POLYLINE_VERTEX(2, b.x + outer_offset, a.y - outer_offset, uv, col); IM_POLYLINE_VERTEX(3, b.x - inner_offset_x, a.y + inner_offset_y, uv, col);
IM_POLYLINE_VERTEX(4, b.x + outer_offset, b.y + outer_offset, uv, col); IM_POLYLINE_VERTEX(5, b.x - inner_offset_x, b.y - inner_offset_y, uv, col);
IM_POLYLINE_VERTEX(6, a.x - outer_offset, b.y + outer_offset, uv, col); IM_POLYLINE_VERTEX(7, a.x + inner_offset_x, b.y - inner_offset_y, uv, col);

IM_POLYLINE_TRIANGLE_BEGIN(24);
IM_POLYLINE_TRIANGLE(0, 0, 1, 3); IM_POLYLINE_TRIANGLE(1, 0, 3, 2);
IM_POLYLINE_TRIANGLE(2, 2, 3, 5); IM_POLYLINE_TRIANGLE(3, 2, 5, 4);
IM_POLYLINE_TRIANGLE(4, 4, 5, 7); IM_POLYLINE_TRIANGLE(5, 4, 7, 6);
IM_POLYLINE_TRIANGLE(6, 6, 7, 1); IM_POLYLINE_TRIANGLE(7, 6, 1, 0);
IM_POLYLINE_TRIANGLE_END(24);

IM_POLYLINE_VTX_COMMIT(8);

IM_POLYLINE_PRIM_COMMIT();
}
}
}
else if (GImGui->IO.KeyCtrl || (flags & 0x80000000u))
{
ImU32 inner_color = 0;
ImU32 outer_color = col;
Expand Down Expand Up @@ -3553,7 +3845,6 @@ if (GImGui->IO.KeyCtrl || (flags & 0x80000000u))
}
else
{

if (Flags & ImDrawListFlags_AntiAliasedLines)
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
else
Expand Down

0 comments on commit 51d7012

Please sign in to comment.