DrawList: amends/review legacy stroke paths + minor tweaks.

This commit is contained in:
ocornut
2026-06-01 17:20:34 +02:00
parent 98f25f94aa
commit e0530d81e1
3 changed files with 37 additions and 39 deletions

View File

@@ -7599,16 +7599,11 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
}
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
if (g_LEGACY_STROKES)
{
float y = window->Pos.y + window->TitleBarHeight - 1;
if (g_LEGACY_STROKES)
window->DrawList->AddLineH(window->Pos.x + border_size * 0.5f, window->Pos.x + window->Size.x - border_size * 0.5f, y, border_col, g.Style.FrameBorderSize);
}
else
{
float y = window->Pos.y + window->TitleBarHeight - g.Style.FrameBorderSize;
window->DrawList->AddLineH(window->Pos.x + border_size, window->Pos.x + window->Size.x - border_size, y, border_col, g.Style.FrameBorderSize);
}
window->DrawList->AddLineH(window->Pos.x + border_size, window->Pos.x + window->Size.x - border_size, y, border_col, g.Style.FrameBorderSize, ImDrawFlags_StrokeCenterBiased);
}
}
@@ -7722,7 +7717,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (g_LEGACY_STROKES)
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size * 0.5f, menu_bar_rect.Max.x - window_border_size * 0.5f, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
else
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size, menu_bar_rect.Max.x - window_border_size, menu_bar_rect.Max.y - style.FrameBorderSize, GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size, menu_bar_rect.Max.x - window_border_size, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize, ImDrawFlags_StrokeCenterBiased);
}
}
@@ -24260,12 +24255,12 @@ void ImGui::DebugDrawLineExtents(ImU32 col)
float curr_x = window->DC.CursorPos.x;
float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y1, col, 1.0f);
window->DrawList->AddLineH(curr_x - 4.0f, curr_x + 5.0f, line_y1, col, 1.0f);
if (g_LEGACY_STROKES)
window->DrawList->AddLineV(curr_x - 0.5f, line_y1, line_y2, col, 1.0f);
else
window->DrawList->AddLineV(curr_x, line_y1, line_y2, col, 1.0f);
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y2, col, 1.0f);
window->DrawList->AddLineH(curr_x - 4.0f, curr_x + 5.0f, line_y2, col, 1.0f);
}
// Draw last item rect in ForegroundDrawList (so it is always visible)

View File

@@ -1193,7 +1193,7 @@ void ImDrawList::_SelectFringeTexture(float screen_thickness, ImVec4* out_tex_uv
{
// Handle the thickness between [1..IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH]. The texture scaling in this range will cause slight visual pops, so we generate super sampled textures in this range.
// There are IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX+1 textures, where 0 maps to 1.0 and IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX maps to IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH.
constexpr float base_width = 1.f;
constexpr float base_width = 1.0f;
const int texture_idx = ImClamp((int)((screen_thickness - base_width) * IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT + 0.1f), 0, IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX);
const float tex_width = base_width + (float)texture_idx / IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT;
*out_fringe = _FringeScale * (screen_thickness / tex_width); // Scale the fringe to cover the discrepancy between the texture and requested size.
@@ -2164,12 +2164,12 @@ void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float th
if (_FringeScaleIsInteger && ImIsTruncated4(min_x, max_x, top_y, thickness) && (flags & ImDrawFlags_SquareCap) == 0)
{
float screen_thickness = thickness / _FringeScale;
if (screen_thickness < 1.f / 255.f)
if (screen_thickness < 1.0f / 255.0f)
return;
if (screen_thickness < 1.f)
if (screen_thickness < 1.0f)
{
col = ImAlphaMultiply(col, screen_thickness);
screen_thickness = 1.f;
screen_thickness = 1.0f;
thickness = _FringeScale;
}
@@ -2212,12 +2212,12 @@ void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float th
if (_FringeScaleIsInteger && ImIsTruncated4(left_x, min_y, max_y, thickness) && (flags & ImDrawFlags_SquareCap) == 0)
{
float screen_thickness = thickness / _FringeScale;
if (screen_thickness < 1.f / 255.f)
if (screen_thickness < 1.0f / 255.0f)
return;
if (screen_thickness < 1.f)
if (screen_thickness < 1.0f)
{
col = ImAlphaMultiply(col, screen_thickness);
screen_thickness = 1.f;
screen_thickness = 1.0f;
thickness = _FringeScale;
}
@@ -2679,18 +2679,18 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c
const float width = b_max.x - b_min.x;
const float height = b_max.y - b_min.y;
const float inv_fringe_scale = 1.f / _FringeScale;
const float inv_fringe_scale = 1.0f / _FringeScale;
const float screen_width = width * inv_fringe_scale;
const float screen_height = height * inv_fringe_scale;
if (ImMin(screen_width, screen_height) < 1.f / 255.f)
if (ImMin(screen_width, screen_height) < 1.0f / 255.0f)
return;
if (screen_width < 1.f)
if (screen_width < 1.0f)
{
col = ImAlphaMultiply(col, screen_width);
b_max.x = b_min.x + _FringeScale;
}
if (screen_height < 1.f)
if (screen_height < 1.0f)
{
col = ImAlphaMultiply(col, screen_height);
b_max.y = b_min.y + _FringeScale;
@@ -2976,18 +2976,18 @@ void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, Im
ImVec2 rad = radius;
const float inv_fringe_scale = 1.f / _FringeScale;
float screen_diameter_x = rad.x* 2.f * inv_fringe_scale;
float screen_diameter_y = rad.y * 2.f * inv_fringe_scale;
if (screen_diameter_x < 1.f / 255.f || screen_diameter_y < 1.f / 255.f)
const float inv_fringe_scale = 1.0f / _FringeScale;
float screen_diameter_x = rad.x * 2.0f * inv_fringe_scale;
float screen_diameter_y = rad.y * 2.0f * inv_fringe_scale;
if (screen_diameter_x < 1.0f / 255.0f || screen_diameter_y < 1.0f / 255.0f)
return;
if (screen_diameter_x < 1.f)
if (screen_diameter_x < 1.0f)
{
col = ImAlphaMultiply(col, screen_diameter_x);
rad.x = _FringeScale * 0.5f;
}
if (screen_diameter_y < 1.f)
if (screen_diameter_y < 1.0f)
{
col = ImAlphaMultiply(col, screen_diameter_y);
rad.y = _FringeScale * 0.5f;
@@ -5169,7 +5169,7 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
ImU8 ramp[IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT];
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT; n++)
ramp[n] = (ImU8)(((float)n / IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT) * 255.f);
ramp[n] = (ImU8)(((float)n / IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT) * 255.0f);
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX + 1; n++)
{

View File

@@ -1768,7 +1768,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
if (g_LEGACY_STROKES)
seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.999f);
else
seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + (-separator_thickness * 0.5f + 1.0f) + 0.999f); // Align hline vertically, and snap to pixels.
seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f) + 1.0f;
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
@@ -1782,9 +1782,9 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
const float sep1_x2 = label_pos.x - style.ItemSpacing.x;
const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x;
if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f)
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
if (g.LogEnabled)
LogSetNextTextDecoration("---", NULL);
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
@@ -1794,7 +1794,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
if (g.LogEnabled)
LogText("---");
if (separator_thickness > 0.0f)
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
}
}
@@ -5703,7 +5703,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else
cursor_screen_rect = ImRect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 1.0f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.0f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize);
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize, ImDrawFlags_StrokeInside);
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
// This is required for some backends (SDL3) to start emitting character/text inputs.
@@ -7218,23 +7218,25 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
if (window->DC.TreeDepth == 0 || (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0)
return;
// FIXME: Could this be simplified using new stroke flags?
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
const float half_size = g.Style.TreeLinesSize * 0.5f;
float x1;
if (g_LEGACY_STROKES)
x1 = ImTrunc(parent_data->DrawLinesX1);
else
x1 = ImTrunc(parent_data->DrawLinesX1 - g.Style.TreeLinesSize * 0.5f) + g.Style.TreeLinesSize * 0.5f; // Draw line centered at X1, but snap to pixels boundary.
x1 = ImTrunc(parent_data->DrawLinesX1 - half_size) + half_size; // Draw line centered at X1, but snap to pixels boundary.
float x2 = ImTrunc(target_pos.x - g.Style.ItemInnerSpacing.x);
float y;
if (g_LEGACY_STROKES)
y = ImTrunc(target_pos.y);
else
y = ImTrunc(target_pos.y) + g.Style.TreeLinesSize * 0.5f;
y = ImTrunc(target_pos.y - half_size) + half_size;
float rounding = (g.Style.TreeLinesRounding > 0.0f) ? ImMin(x2 - x1, g.Style.TreeLinesRounding) : 0.0f;
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, y - rounding);
if (x1 >= x2)
return;
if (rounding > 0.0f)
if (rounding > 0.0f && rounding > half_size)
{
if (g_LEGACY_STROKES)
x1 += 0.5f + rounding;
@@ -7248,9 +7250,9 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
else
{
// We use AddLine() instead of AddLineH() as we provide coordinates for line center,
// in order to make the code use same coordinates for both rounded and non-rounded version.
// in order to make the code use same coordinates for both rounded and non-rounded version. (FIXME-OPT)
if (!g_LEGACY_STROKES)
x1 += g.Style.TreeLinesSize * 0.5f; // Avoid overdraw
x1 += half_size; // Avoid overdraw
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
}
@@ -7281,7 +7283,8 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
x = ImTrunc(data->DrawLinesX1 - g.Style.TreeLinesSize * 0.5f) + g.Style.TreeLinesSize * 0.5f; // Draw line centered at X1, but snap to pixels boundary.
if (data->DrawLinesTableColumn != -1)
TablePushColumnChannel(data->DrawLinesTableColumn);
// We use AddLine() instead of AddLineV() as we provide coordinates for line center,
// We use AddLine() instead of AddLineV() as we provide coordinates for line center (FIXME-OPT)
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
if (data->DrawLinesTableColumn != -1)
TablePopColumnChannel();