ocornut / imgui

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

Vertical text #705

Open guillaumechereau opened 8 years ago

guillaumechereau commented 8 years ago

I would like to use vertical tabs, similar to how blender ui does:

blender

Is there a way to render vertical text with imgui?

ocornut commented 8 years ago

Not at the moment, though you can use code based on ImFont::RenderChar() and render it yourself. If you are going to create vertical tabs you'll need custom code anyway.

There was a request for rotated text which I always assumed was arbitrary-rotated text, but 90-degrees text is a little easier to handle. https://github.com/ocornut/imgui/issues/422

MrSmith33 commented 8 years ago

This is exactly what I needed this feature for. (vertical tabs and maybe table headers)

Flix01 commented 8 years ago

@MrSmith33: I've just made a quick gist modifying the related ImDrawList methods to display vertical text. If you want you can use it as a starting point to build ImGui widgets on it (I'm not sure if I'll keep on developing it or not: I still have to understand if vertical text is useful for me or not...).

https://gist.github.com/Flix01/3e176c64540f51b99a4ec82cfaf759a5 imgui_vertical_text

guillaumechereau commented 8 years ago

I finally made a small custom tab widget for my program. It's actually quite easy to manage vertical tabs with the groupBegin and groupEnd functions: tabs

The implementation code is here (GoxTab function): https://github.com/guillaumechereau/goxel/blob/master/src/imgui_user.inl

Flix01 commented 8 years ago

@guillaumechereau: good job :smiley: !

P.S. Your code is so compact that can be posted here:

#include <imgui_internal.h>
namespace ImGui {
    bool GoxTab(const char *text, bool *v)
    {
        ImFont *font = GImGui->Font;
        const ImFont::Glyph *glyph;
        char c;
        bool ret;
        ImGuiContext& g = *GImGui;
        const ImGuiStyle& style = g.Style;
        float pad = style.FramePadding.x;
        ImVec4 color;
        ImVec2 text_size = CalcTextSize(text);
        ImGuiWindow* window = GetCurrentWindow();
        ImVec2 pos = window->DC.CursorPos + ImVec2(pad, text_size.x + pad);

        const  ImU32 text_color = ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]);
        color = style.Colors[ImGuiCol_Button];
        if (*v) color = style.Colors[ImGuiCol_ButtonActive];
        ImGui::PushStyleColor(ImGuiCol_Button, color);
        ImGui::PushID(text);
        ret = ImGui::Button("", ImVec2(text_size.y + pad * 2,
                                       text_size.x + pad * 2));
        ImGui::PopStyleColor();
        while ((c = *text++)) {
            glyph = font->FindGlyph(c);
            if (!glyph) continue;

            window->DrawList->PrimReserve(6, 4);
            window->DrawList->PrimQuadUV(
                    pos + ImVec2(glyph->Y0, -glyph->X0),
                    pos + ImVec2(glyph->Y0, -glyph->X1),
                    pos + ImVec2(glyph->Y1, -glyph->X1),
                    pos + ImVec2(glyph->Y1, -glyph->X0),

                    ImVec2(glyph->U0, glyph->V0),
                    ImVec2(glyph->U1, glyph->V0),
                    ImVec2(glyph->U1, glyph->V1),
                    ImVec2(glyph->U0, glyph->V1),
                     text_color);
            pos.y -= glyph->XAdvance;
        }
        ImGui::PopID();
        return ret;
}
} // namespace ImGui

I haven't tested it so far, but it seems very compact and useful. Maybe it's good enough to be included in the original Dear ImGui ...

[Edit:] Added text_color from current style.

guillaumechereau commented 8 years ago

Note that in my code the colour is fixed to white and the text scale is assumed to be equal to 1, a more generic version should get those values from the imgui context.

Flix01 commented 8 years ago

Note that in my code the colour is fixed to white.

I've just changed it in the snippet above.

ocornut commented 4 years ago

The code in #3067 has another function to draw 90 rotated text: https://github.com/mahilab/mahi-gui/blob/master/src/Mahi/Gui/imgui_plot.cpp

/// Draws vertical text. The position is the bottom left of the text rect.
inline void AddTextVertical(ImDrawList* DrawList, const char *text, ImVec2 pos, ImU32 text_color) {
    pos.x = IM_ROUND(pos.x);
    pos.y = IM_ROUND(pos.y);
    ImFont *font = GImGui->Font;
    const ImFontGlyph *glyph;
    char c;
    ImGuiContext& g = *GImGui;
    ImVec2 text_size = CalcTextSize(text);
    while ((c = *text++)) {
        glyph = font->FindGlyph(c);
        if (!glyph) continue;

        DrawList->PrimReserve(6, 4);
        DrawList->PrimQuadUV(
                pos + ImVec2(glyph->Y0, -glyph->X0),
                pos + ImVec2(glyph->Y0, -glyph->X1),
                pos + ImVec2(glyph->Y1, -glyph->X1),
                pos + ImVec2(glyph->Y1, -glyph->X0),

                ImVec2(glyph->U0, glyph->V0),
                ImVec2(glyph->U1, glyph->V0),
                ImVec2(glyph->U1, glyph->V1),
                ImVec2(glyph->U0, glyph->V1),
                    text_color);
        pos.y -= glyph->AdvanceX;
    }
}

If you don't need clipping, wrapping etc. it's fairly easy to write it. We will aim to support full-featured rotated text in a new low-level text rendering API this year.

Also linking to #1286, #3032

h3r commented 3 years ago

I finally made a small custom tab widget for my program. It's actually quite easy to manage vertical tabs with the groupBegin and groupEnd functions: tabs

The implementation code is here (GoxTab function): https://github.com/guillaumechereau/goxel/blob/master/src/imgui_user.inl

Where I can find the whole implementation? Looks awesome, I tried the one posted above and its only working partially

guillaumechereau commented 3 years ago

Where I can find the whole implementation? Looks awesome, I tried the one posted above and its only working partially

At the moment the code in Goxel is not using vertical tabs anymore. The original code is still there in git history though. This should be what you are looking for:

https://github.com/guillaumechereau/goxel/commit/7f19813ef4ab3b66bd346fbae88c7f887c4e2a14#diff-cfe21764ff8318e2f277e1d653bf7edf160502b6af27d31a6fecc8c25c7ff66f

aabilityuk commented 1 year ago

The code in #3067 has another function to draw 90 rotated text: https://github.com/mahilab/mahi-gui/blob/master/src/Mahi/Gui/imgui_plot.cpp

/// Draws vertical text. The position is the bottom left of the text rect.
inline void AddTextVertical(ImDrawList* DrawList, const char *text, ImVec2 pos, ImU32 text_color) {
    pos.x = IM_ROUND(pos.x);
    pos.y = IM_ROUND(pos.y);
    ImFont *font = GImGui->Font;
    const ImFontGlyph *glyph;
    char c;
    ImGuiContext& g = *GImGui;
    ImVec2 text_size = CalcTextSize(text);
    while ((c = *text++)) {
        glyph = font->FindGlyph(c);
        if (!glyph) continue;

        DrawList->PrimReserve(6, 4);
        DrawList->PrimQuadUV(
                pos + ImVec2(glyph->Y0, -glyph->X0),
                pos + ImVec2(glyph->Y0, -glyph->X1),
                pos + ImVec2(glyph->Y1, -glyph->X1),
                pos + ImVec2(glyph->Y1, -glyph->X0),

                ImVec2(glyph->U0, glyph->V0),
                ImVec2(glyph->U1, glyph->V0),
                ImVec2(glyph->U1, glyph->V1),
                ImVec2(glyph->U0, glyph->V1),
                    text_color);
        pos.y -= glyph->AdvanceX;
    }
}

If you don't need clipping, wrapping etc. it's fairly easy to write it. We will aim to support full-featured rotated text in a new low-level text rendering API this year.

Also linking to #1286, #3032

Hello, could you post a small example of how to use this code please? What should i pass to ImDrawList parametr? Thank you

sakiodre commented 1 year ago

@aabilityuk Use GetWindowDrawList() for your windows, alternatively use GetBackgroundDrawList() or GetForegroundDrawList(). You also might want to use GetCursorScreenPos() for the pos.

AddTextVertical(ImGui::GetWindowDrawList(), "text", ImGui::GetCursorScreenPos(), 0xff00ff00);
aabilityuk commented 1 year ago

@aabilityuk Use GetWindowDrawList() for your windows, alternatively use GetBackgroundDrawList() or GetForegroundDrawList(). You also might want to use GetCursorScreenPos() for the pos.

AddTextVertical(ImGui::GetWindowDrawList(), "text", ImGui::GetCursorScreenPos(), 0xff00ff00);

Thank you