-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rounded clipping / rounded AddRectFilledMultiColor #3710
Comments
I forgot to mention, I don't really consider the compromises of losing the edges of the color picker, my previous fix for this was to simply have the picker's cursor navigate between all 4 spots to their complete end as if it was not gone or clipped. I never exceeded something like 5.f in rounding if anyone was curious. |
No. Regardless, I don't think you need rounded cliprect to achieve so I believe this request for "rounded cliprect" is a XY Problem (http://xyproblem.info).
Thanks for the clarification, that makes a big difference actually. If you look at An alternative solution: use
With
But it will override the anti-aliased alpha fringe and therefore break outer alpha, so that function would need to be reworked. |
Looks great, I will test to see if this is exactly what I need. I was considering one of my other ideas last night where you would do an inverted fill rect where the parts it doesn't render to (like where it would be rounded) would be filled instead of the center. Either way this looks like a good enough solution as is, so thank you so much! |
Finished that other idea I had with the inverted rect. Please note though that if you plan to use my solution it will not work with transparency, it is not clipping nor is it trying to round the picker itself, it is the third solution I thought up where it draws over the edges of the pickers ends. For reference here are the differences between yours (second photo) and my solution (first photo): If anyone is curious here is the code for my solution (probably won't ever be used outside of my use case though): void ImDrawList::AddInvertedRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (rounding > 0.0f)
PathInvertedRect(p_min, p_max, col, rounding, rounding_corners);
}
void ImDrawList::PathInvertedRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{
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 (rounding <= 0.0f || rounding_corners == 0)
return;
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;
PathLineTo(a);
PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
PathFillConvex(col);
PathLineTo(ImVec2(b.x, a.y));
PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
PathFillConvex(col);
PathLineTo(ImVec2(b.x, b.y));
PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
PathFillConvex(col);
PathLineTo(ImVec2(a.x, b.y));
PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6);
PathFillConvex(col);
}
}
// line 5174 in imgui_widgets.cpp
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
draw_list->AddInvertedRectFilled(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_PopupBg)), 5.f); |
I have encountered this problem too, ended up doing it myself. Here is the code, without need of adding extra background color argument. Side note, this isn't very very cpu friendly. void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left, float rounding, ImDrawFlags flags)
{
if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
return;
flags = FixRectCornerFlags(flags);
rounding = ImMin(rounding, ImFabs(p_max.x - p_min.x) * (((flags & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((flags & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f) - 1.0f);
rounding = ImMin(rounding, ImFabs(p_max.y - p_min.y) * (((flags & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((flags & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f) - 1.0f);
// https://github.com/ocornut/imgui/issues/3710#issuecomment-758555966
if (rounding > 0.0f)
{
const int size_before = VtxBuffer.Size;
AddRectFilled(p_min, p_max, IM_COL32_WHITE, rounding, flags);
const int size_after = VtxBuffer.Size;
for (int i = size_before; i < size_after; i++)
{
ImDrawVert* vert = VtxBuffer.Data + i;
ImVec4 upr_left = ImGui::ColorConvertU32ToFloat4(col_upr_left);
ImVec4 bot_left = ImGui::ColorConvertU32ToFloat4(col_bot_left);
ImVec4 up_right = ImGui::ColorConvertU32ToFloat4(col_upr_right);
ImVec4 bot_right = ImGui::ColorConvertU32ToFloat4(col_bot_right);
float X = ImClamp((vert->pos.x - p_min.x) / (p_max.x - p_min.x), 0.0f, 1.0f);
// 4 colors - 8 deltas
float r1 = upr_left.x + (up_right.x - upr_left.x) * X;
float r2 = bot_left.x + (bot_right.x - bot_left.x) * X;
float g1 = upr_left.y + (up_right.y - upr_left.y) * X;
float g2 = bot_left.y + (bot_right.y - bot_left.y) * X;
float b1 = upr_left.z + (up_right.z - upr_left.z) * X;
float b2 = bot_left.z + (bot_right.z - bot_left.z) * X;
float a1 = upr_left.w + (up_right.w - upr_left.w) * X;
float a2 = bot_left.w + (bot_right.w - bot_left.w) * X;
float Y = ImClamp((vert->pos.y - p_min.y) / (p_max.y - p_min.y), 0.0f, 1.0f);
float r = r1 + (r2 - r1) * Y;
float g = g1 + (g2 - g1) * Y;
float b = b1 + (b2 - b1) * Y;
float a = a1 + (a2 - a1) * Y;
ImVec4 RGBA(r, g, b, a);
RGBA = RGBA * ImGui::ColorConvertU32ToFloat4(vert->col);
vert->col = ImColor(RGBA);
}
return;
}
const ImVec2 uv = _Data->TexUvWhitePixel;
PrimReserve(6, 4);
PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2));
PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3));
PrimWriteVtx(p_min, uv, col_upr_left);
PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right);
PrimWriteVtx(p_max, uv, col_bot_right);
PrimWriteVtx(ImVec2(p_min.x, p_max.y), uv, col_bot_left);
} |
I got an other idea i hope it's possible and i will work on it: |
1.79 shadows branch:
Version: 1.79 WIP
Branch: shadows
DX11 Win32 Windows 10 1903 Application
Back-ends: imgui_impl_win32.cpp + imgui_impl_dx11.cpp
Compiler: Win64 x64 Visual Studio 2019
Operating System: Windows 10 x64 1903
Are Rounded ClipRect's being considered and why does AddRectFilledMultiColor not have rounded options:
Hi, I am trying to create a rounded Color Picker. I located the location where ImGui's widget file (imgui_widgets.cpp) renders the actual color picker where you can select the color with the widget's cursor (you can navigate to this via visual interface by going to the demo menu's Tools tab and then selecting Style Editor, locate the section named Colors which is next to Sizes, click on the mini view of the color for Text or any other option and the view with the white to black to red picker is what I am referring to)
The lines to find this is 5149 and looks like:
I want to make this render a rounded version of this since my menu is based around being very round, I had a solution to this in other engine but since this is ImGui and it looks like functionality that should be inherited from AddRect I'm stumped to why this doesn't have the ability to round like other methods.
To be clear I am working with internal methods and know the dangers or responsibilities I must take with this, I was just reversing how ImGui::ColorPicker4 and ColorEditor4 worked so I could find what method they used for this specific display.
I believe another solution to my problem could be something like an inverted clip or inverted filled rect where instead of filling the interior of the rectangle it would fill the spots where it wouldn't be visible, which would be the rounded edges. Personally, I do not know much about the internals of ImGui's vertex shading but I can see with some extra effort I might be able to solve this. This is being posted as I am curious if anyone has already worked on something like this and I am not the first one to find a solution to this problem.
The text was updated successfully, but these errors were encountered: