Description
Version/Branch of Dear ImGui:
1.90
Back-ends:
all
Compiler, OS:
Windows
Full config/build information:
No response
Details:
I would like to have a Menu in one font and items within it in another.
If you push a font in order to have a BeginMenu
in a different font, but then want some MenuItem
in the normal (default) font and call PopFont
it will assert fail because the font stack is wrong - unless you manually fix the font stack with a hack.
asserts here in AddText
IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
Code example with hackaround:
struct PushIconFont
{
// class to push and pop the icon font
bool _pushed = false;
void push()
{
ImGui::PushFont(iconFont);
_pushed = true;
}
void pop()
{
if (_pushed)
{
ImGui::PopFont();
_pushed = false;
}
}
static void fixme()
{
// XXX big hairy steaming great hack !!
auto w = ImGui::GetCurrentWindow();
int z = w->DrawList->_TextureIdStack.Size;
if (!z)
{
auto font = ImGui::GetDefaultFont();
w->DrawList->PushTextureID(font->ContainerAtlas->TexID);
}
}
PushIconFont() { push(); }
~PushIconFont() { pop(); }
};
if (ImGui::BeginMenuBar())
{
// push the icon font.
PushIconFont pf;
// make a menu using the icon font
if (ImGui::BeginMenu(ICON_MD_MORE_HORIZ)) // three dots "..."
{
// we now want some menu items in the default font
pf.pop(); // pop off the icon font
// this fixes the stack imbalance so we can use the base font
// XXX THIS IS A STEAMING HACK !!
pf.fixme();
// !! BANG the following line will asset fail unless
// `fixme` is done above.
// make some normal menu items
if (ImGui::MenuItem("Something")) doSomething();
if (ImGui::MenuItem("Something else")) doSomethingElse();
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
The above code has a Steaming Great Hack in fixme
to do this.
I can explain what is happening:
-
PushFont
is called which pushes onto g.FontStack andPushTextureID
pushes onto the drawlistTextureIdStack
. So we're on both stacks. -
BeginMenu
is cool until you click on it. It creates a popup which callsBegin
.Begin
ascertains we'refirst_begin_of_the_frame
and callswindow->DrawList->_ResetForNewFrame()
which clears theTextureIdStack
.
But hey, the g.FontStack
is still pushed!
The workaround is to pop as normal (which has the side-effect of popping the TextureIdStack to NULL) then manually pushing it back in fixme
. Bluh!
Is this an ImGui bug, perhaps a limitation or have i gone mad (again) ?
Thanks.
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
// Here's some code anyone can copy and paste to reproduce your issue
ImGui::Begin("Example Bug");
MoreCodeToExplainMyIssue();
ImGui::End();