ImDrawList: upgraded AddRect(), AddRectFilled(), PathRect() to use general ImDrawFlags instead of ImDrawCornersFlags

This commit is contained in:
Rokas Kupstys
2021-03-10 12:15:08 +02:00
committed by ocornut
parent 8b9fedba28
commit c2d6d26139
8 changed files with 136 additions and 88 deletions

View File

@ -1279,12 +1279,45 @@ void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3,
}
}
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawCornerFlags rounding_corners)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline ImDrawFlags FixImDrawCornerFlags(ImDrawFlags flags)
{
rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f);
rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f);
// If following asserts trigger, please update your code replacing all uses of ImDrawCornerFlags_* with ImDrawFlags_*.
if ((flags & ImDrawCornerFlags_All) == ImDrawCornerFlags_All)
{
// All round corners, set new flags to 0 if:
// Legacy Rule 1: first 4 bits of flags are set, ImDrawCornerFlags_All was used
// Legacy Rule 2: first all bits of flags are set, ~0 was used
IM_ASSERT((flags == ImDrawCornerFlags_All || flags == ~0) && "Mixing new and legacy flags is not allowed.");
return 0;
}
else if ((flags & (ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight)) != 0)
{
// Legacy Rule 3: if any of last 4 bits are set, move them to corresponding positions of non-legacy flags and invert them.
IM_ASSERT((flags & 0x0FFFFFFF) == 0 && "Mixing new and legacy flags is not allowed.");
const int legacy_flags_bit_offset = 24; // 32 - num_legacy_flags (4) - new_flags_first_bit (4)
return (flags >> legacy_flags_bit_offset) ^ (ImDrawFlags_NoRoundCornerT | ImDrawFlags_NoRoundCornerB);
}
else
{
IM_ASSERT((flags & 0x0E) == 0 && "Bits 1..3 are unused.");
return flags;
}
}
#endif
if (rounding <= 0.0f || rounding_corners == 0)
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
{
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// Legacy use of ~0 or 0x0F as ImDrawCornerFlags value. Please update your code to use ImDrawFlags_NoRoundCorner* flags.
IM_ASSERT((flags & 0x0E) == 0);
#else
flags = FixImDrawCornerFlags(flags);
#endif
rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_NoRoundCornerT) == 0) || ((flags & ImDrawFlags_NoRoundCornerB) == 0) ? 0.5f : 1.0f ) - 1.0f);
rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_NoRoundCornerL) == 0) || ((flags & ImDrawFlags_NoRoundCornerR) == 0) ? 0.5f : 1.0f ) - 1.0f);
if (rounding <= 0.0f || (flags & ImDrawFlags_NoRoundCorners) == ImDrawFlags_NoRoundCorners)
{
PathLineTo(a);
PathLineTo(ImVec2(b.x, a.y));
@ -1293,10 +1326,10 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr
}
else
{
const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f;
const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f;
const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f;
const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f;
const float rounding_tl = (flags & ImDrawFlags_NoRoundCornerTL) ? 0.0f : rounding;
const float rounding_tr = (flags & ImDrawFlags_NoRoundCornerTR) ? 0.0f : rounding;
const float rounding_br = (flags & ImDrawFlags_NoRoundCornerBR) ? 0.0f : rounding;
const float rounding_bl = (flags & ImDrawFlags_NoRoundCornerBL) ? 0.0f : rounding;
PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
@ -1315,24 +1348,24 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
// p_min = upper-left, p_max = lower-right
// Note we don't render 1 pixels sized rectangles properly.
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness)
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (Flags & ImDrawListFlags_AntiAliasedLines)
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, rounding_corners);
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
else
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes.
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
PathStroke(col, ImDrawFlags_Closed, thickness);
}
void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (rounding > 0.0f)
if (rounding > 0.0f && (flags & ImDrawFlags_NoRoundCorners) != ImDrawFlags_NoRoundCorners)
{
PathRect(p_min, p_max, rounding, rounding_corners);
PathRect(p_min, p_max, rounding, flags);
PathFillConvex(col);
}
else
@ -1568,12 +1601,18 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, con
PopTextureID();
}
void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0)
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// Legacy use of ~0 or 0x0F as ImDrawCornerFlags value. Please update your code to use ImDrawFlags_NoRoundCorner* flags.
IM_ASSERT((flags & 0x0E) == 0);
#else
flags = FixImDrawCornerFlags(flags);
#endif
if (rounding <= 0.0f || (flags & ImDrawFlags_NoRoundCorners) == ImDrawFlags_NoRoundCorners)
{
AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col);
return;
@ -1584,7 +1623,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
PushTextureID(user_texture_id);
int vert_start_idx = VtxBuffer.Size;
PathRect(p_min, p_max, rounding, rounding_corners);
PathRect(p_min, p_max, rounding, flags);
PathFillConvex(col);
int vert_end_idx = VtxBuffer.Size;
ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true);
@ -3814,27 +3853,27 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect
const bool fill_R = (inner.Max.x < outer.Max.x);
const bool fill_U = (inner.Min.y > outer.Min.y);
const bool fill_D = (inner.Max.y < outer.Max.y);
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopLeft) | (fill_D ? 0 : ImDrawCornerFlags_BotLeft));
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopRight) | (fill_D ? 0 : ImDrawCornerFlags_BotRight));
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_TopLeft) | (fill_R ? 0 : ImDrawCornerFlags_TopRight));
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_BotLeft) | (fill_R ? 0 : ImDrawCornerFlags_BotRight));
if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopLeft);
if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopRight);
if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotLeft);
if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotRight);
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? ImDrawFlags_NoRoundCornerTL : 0) | (fill_D ? ImDrawFlags_NoRoundCornerBL : 0));
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? ImDrawFlags_NoRoundCornerTR : 0) | (fill_D ? ImDrawFlags_NoRoundCornerBR : 0));
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? ImDrawFlags_NoRoundCornerTL : 0) | (fill_R ? ImDrawFlags_NoRoundCornerTR : 0));
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? ImDrawFlags_NoRoundCornerBL : 0) | (fill_R ? ImDrawFlags_NoRoundCornerBR : 0));
if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_NoRoundCornerB | ImDrawFlags_NoRoundCornerTR);
if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_NoRoundCornerB | ImDrawFlags_NoRoundCornerTL);
if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_NoRoundCornerT | ImDrawFlags_NoRoundCornerBR);
if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawFlags_NoRoundCornerT | ImDrawFlags_NoRoundCornerBL);
}
// Helper for ColorPicker4()
// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.
// FIXME: uses ImGui::GetColorU32
void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags)
void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags)
{
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
{
ImU32 col_bg1 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
ImU32 col_bg2 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags);
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
int yi = 0;
for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
@ -3847,17 +3886,17 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
if (x2 <= x1)
continue;
int rounding_corners_flags_cell = 0;
if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; }
if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; }
rounding_corners_flags_cell &= rounding_corners_flags;
draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell);
ImDrawFlags cell_flags = ImDrawFlags_NoRoundCorners;
if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags &= ~ImDrawFlags_NoRoundCornerTL; if (x2 >= p_max.x) cell_flags &= ~ImDrawFlags_NoRoundCornerTR; }
if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags &= ~ImDrawFlags_NoRoundCornerBL; if (x2 >= p_max.x) cell_flags &= ~ImDrawFlags_NoRoundCornerBR; }
cell_flags |= flags;
draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding, cell_flags);
}
}
}
else
{
draw_list->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags);
draw_list->AddRectFilled(p_min, p_max, col, rounding, flags);
}
}