Skip to content
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

A colored icon glyph loses its color in light mode but keeps intact in dark/classic mode. #8133

Closed
IniKiwi opened this issue Nov 6, 2024 · 5 comments

Comments

@IniKiwi
Copy link

IniKiwi commented Nov 6, 2024

Version/Branch of Dear ImGui:

Version latest, Branch: docking

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux Debian 12

Full config/build information:

Dear ImGui 1.91.5 WIP (19141)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201703
define: __linux__
define: __GNUC__=13
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000081
 NavEnableKeyboard
 DockingEnable
io.ConfigViewportsNoDecoration
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigWindowsMoveFromTitleBarOnly
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.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: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

I'm trying to add icons to a treenode. But the icons are made black.
image
image

Screenshots/Video:

Capture.video.du.2024-11-06.13-01-54.mp4

Minimal, Complete and Verifiable Example code:

#define ICON_WORLD "w"
void LoadImGuiFontIcon(std::string filename, int id){
    ImGuiIO& io = ImGui::GetIO();
    uint8_t* glyphPixels = nullptr;
    int glyphX, glyphY;
    io.Fonts->GetTexDataAsRGBA32(&glyphPixels, &glyphX, &glyphY);
    if (const ImFontAtlasCustomRect* rect = io.Fonts->GetCustomRectByIndex(id)){
        int imgX, imgY, channels;
        FILE* file = OpenContentFile(std::string("icons/")+filename, "r");
        if(file == NULL){return;}
        uint8_t* texturePixels = stbi_load_from_file(file, &imgX, &imgY, &channels, 4);

        int pixCounter = 0;
        // Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
        fmt::println("texture {} {} {}", imgX, imgY, channels);
        for (int y = 0; y < rect->Height; y++){
            ImU32* p = (ImU32*)glyphPixels + (rect->Y + y) * glyphX + (rect->X);
            for (int x = rect->Width; x > 0; x--){
                *p++ = IM_COL32(texturePixels[pixCounter], texturePixels[pixCounter+1], texturePixels[pixCounter+2], texturePixels[pixCounter+3]);
                pixCounter += 4;
            }
        }
        stbi_image_free(texturePixels);
    }
}

void Render::LoadImGuiFontIcons(){
    ImGuiIO& io = ImGui::GetIO();
    static ImFontConfig cfg;
    cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor;
    ImFont* font = io.Fonts->AddFontDefault();
    int rect_ids[10];
    rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_WORLD, 16, 16, 16+1);
    rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_BRICK, 16, 16, 16+1);

    // Build atlas
    io.Fonts->Build();

    LoadImGuiFontIcon("world.png", rect_ids[0]);
}
@ocornut
Copy link
Owner

ocornut commented Nov 6, 2024

The glyph needs to be marked as Colored to undo the vertex coloring applied by text color. It should happens to work because in the darker style the text color is white (1,1,1,1) and in the other it is black (0,0,0,1) which multiplies down the color.

There is 1 bit in ImFontGlyph for that:

 unsigned int    Colored : 1;  // Flag to indicate glyph is colored and should generally ignore tinting

Unfortunately this wasn't planned ahead in the AddCustomRectFontGlyph() function, there is no way to pass that parameter.

You would currently need to use this workaround:

    int rect_ids[10];
    rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_WORLD, 16, 16, 16+1);
    rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_BRICK, 16, 16, 16+1);

    // Build atlas
    io.Fonts->Build();

    for (int n = 0; n < 2; n++)
    {
         ImFontGlyph* glyph = (ImFontGlyph*)font->FindGlyph(rect_ids[n].GlyphID);
         glyph->Colored = 1;
    }

Normally I would fix it by expanding the AddCustomRectFontGlyph() API but as with #8107 I am currently working on a large refactor of the font system.

@IniKiwi
Copy link
Author

IniKiwi commented Nov 6, 2024

Thanks you very much!
image
Do you have any idea how fit this icon in the treenode by changing the vertical alignment of the glyph and the size of the tree nodes?

@IniKiwi IniKiwi closed this as completed Nov 6, 2024
@ocornut ocornut reopened this Nov 6, 2024
@ocornut
Copy link
Owner

ocornut commented Nov 6, 2024

If you manually add glyphs to a font it should be added with same vertical size. Horizontal size you specify.

Consider using emoji svg fonts using freetype as an alternative.

@IniKiwi
Copy link
Author

IniKiwi commented Nov 6, 2024

I'm using same icons as gmod and old roblox, these icons are just 16x16 bitmaps. I will leave it like this. Thanks you very much!

image
These icons are so cute!

@ocornut
Copy link
Owner

ocornut commented Nov 7, 2024

As an undocumented small change I have pushed 17bd417

You can now do this:

rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_WORLD, 16, 16, 16+1);
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, *(const ImWchar*)ICON_BRICK, 16, 16, 16+1);
for (int n = 0; n < 2; n++)
    io.Fonts->GetCustomRectByIndex(rects_id[n])->GlyphColored = 1;

It's not great and doesn't constitute a neat public API, but you can do this in the same call size without waiting for Build() to occur.

I'll keep this in mind when we introduce a new API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants