ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.84k stars 10.28k forks source link

Frame color visible behind border color #3656

Open nem0 opened 3 years ago

nem0 commented 3 years ago
Dear ImGui 1.80 WIP (17906)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _WIN64
define: _MSC_VER=1927
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_win32
io.BackendRendererName: imgui_impl_dx11
io.ConfigFlags: 0x0000C441
 NavEnableKeyboard
 DockingEnable
 ViewportsEnable
 DpiEnableScaleViewports
 DpiEnableScaleFonts
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1264.00,761.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 5.00
style.FrameBorderSize: 1.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

docking branch Compiler: VS2019 Operating System: win10

My Issue/Question:

Steps to reproduce:

  1. open style editor
  2. set frame rounding to 5
  3. set border size to 1
  4. set border color to red(255 alpha)
  5. set button color to blue(255 alpha)
  6. disable antialiasing
  7. observe that any blue button leaks outside its red border (as in attached screenshot)

Notes:

Screenshots/Video

image

ocornut commented 3 years ago

Thanks for the report.

The problem is that the ideal offsets for a fully opaque border isn't the same as the ideal offset for zero-alpha/no-border, and in-between those two alpha values we have a tricky continuum.

Here's offsetting the filled shape inward by 0.250

image image

I don't have a magic solution but I suppose we should experiment with this a little more and see if interpolating that offset for the filled shape, based on the border alpha would work well enough.

If you add border size into the equation it may or not make that more tricky.

ImGuiStyle& style = ImGui::GetStyle();
style.FrameRounding = 5.0f;
style.FrameBorderSize = 1.0f;
style.Colors[ImGuiCol_Border] = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
style.Colors[ImGuiCol_Button] = ImVec4(0.0f, 0.0f, 1.0f, 1.0f);

[...]

style.AntiAliasedFill = style.AntiAliasedLines = io.KeyShift;
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 7.0f, "%.1f");
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 3.0f, "%.1f");
ImGui::ColorEdit4("ImGuiCol_Border", &style.Colors[ImGuiCol_Border].x);
ImGui::ColorEdit4("ImGuiCol_Button", &style.Colors[ImGuiCol_Button].x);
ImGui::Button("this is a button!");

In imgui.cpp:

static ImVec2 OFFSET(0.0f, 0.0f);

// Render a rectangle shaped with optional rounding and borders
void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;
    if (g.IO.KeyCtrl)
        window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
    else
        window->DrawList->AddRectFilled(p_min - OFFSET, p_max + OFFSET, fill_col, rounding);
[...]
}

There would be some more things to changes but that gives a basic thing to toy with.