-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
Pushing colors after creating a widget / 1 frame delay blinking #2144
Comments
How do you suggest to fix this issue? :)
Implement your own button widget calling ButtonBehavior(), it should be a dozen of lines.
|
Thanks for pointing me to the right direction, but it looks like with Thanks! |
Reimplementing a custom version of ButtonEx() - where you can trim some of the fat from - seems like the more reasonable way, far more reasonable than poking into vertex colors after submitting the vertices.
|
Yes, so one option I came up with is using a callback instead of a return value. The callback is called before the actual rendering, so I can easily push my color changes in a lambda function and they will be applied in the current frame. Posting a C++ snippet for others in case they would like to get inspired. I used Thank you, I am closing the issue now! template <typename Func>
void ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags, Func onPressed)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
ImVec2 pos = window->DC.CursorPos;
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
ImVec2 size = ImGui::CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
const ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
ImGui::ItemSize(bb, style.FramePadding.y);
if (!ImGui::ItemAdd(bb, id))
return;
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat;
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, flags);
if(pressed) {
onPressed();
}
// Render
const ImU32 col = ImGui::GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImGui::RenderNavHighlight(bb, id);
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
ImGui::RenderTextClipped(ImVec2(bb.Min.x + style.FramePadding.x, bb.Min.y + style.FramePadding.y), ImVec2(bb.Max.x - style.FramePadding.x, bb.Max.y - style.FramePadding.y), label, NULL, &label_size, style.ButtonTextAlign, &bb);
// Automatically close popups
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
// CloseCurrentPopup();
} |
That’s an odd choice, why don’t you push the colors directly inside the function you created, and give it a proper name? Eg: ToggleButton() and pass its toggle state as a parameter?
|
I might end up doing it that way, but imo both options have their pros and cons, e.g.,
I think the only robust solution here is to actually combine both of them, the callback to actually set if the button should really become toggled, but setting the colors inside the actual button function. |
You seem to be ignoring the whole point of copying the function which to use whatever color you want without any push/pop action and without any restriction. There’s no lag because you’ll doing the drawing after processing the logic like ButtonEx is doing.
|
Ah ok, I see, I was just trying to find a kinda generic solution to this problem. Thanks for help! |
Those internals rarely change, but I would like down the line to redesign them in a way that is more friendly/obvious for creating new widgets, and toward making the internal api guaranteed forward compatible. It’ll probably be a good portion of imgui 2.0 to aim for that, once the feature set is better known. |
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(ImColor(23, 30, 57, 255)));
|
Hello, I am trying to make a button which behaves more or less like a classic Windows GUI toggle button. The problem here is that classic toggle buttons are more complicated than this simple example. Let me explain how a usual toggle button should actually work:
This should not be that hard to do in ImGui, right? Here is a simple concept:
But watch how it actually looks like:
Do you notice the 1 frame delay? The quick blink of gray color before it turns black? Obviously the lower the framerate, the more noticeable this issue is.
It happens because in the code, the
isToggled
variable is only updated after the button widget is actually created, so the colors that are pushed are 1 frame delayed. However, ImGui is so clever that it actually notices that the button is not clicked anymore at this moment, so it gives it theButtonHovered
light color in the current frame causing the whole button to blink.One way to fix this would be to somehow push the colors after already creating the button, something like
PushStyleColorToPreviousWidget
but obviously this is too weird.How do you suggest to fix this issue? :)
Edit: Here is how it actually should look like (gif from Microsoft Paint 3D user interface):
The text was updated successfully, but these errors were encountered: