-
-
Notifications
You must be signed in to change notification settings - Fork 10.5k
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
Using Icon Fonts in current Font #232
Comments
Hacking a copy&paste of ImGui::Button to create ImGui::ButtonIcon yields pleasing results #pragma once
enum ImGuiIconEnum
{
ImGui_fa_camera_retro = 0xF083
};
namespace ImGui
{
extern ImFont* GIconFont;
bool ButtonIcon(const char* label, ImGuiIconEnum iconChar, const ImVec2& size = ImVec2(0, 0), bool repeat_when_held = false);
} #pragma once
#include "imgui.h"
// This is just to help Intellisense for private imgui.cpp symbols on visual studio...
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#include "imgui.cpp"
#endif
ImFont* ImGui::GIconFont = nullptr;
bool ImGui::ButtonIcon(const char* label, ImGuiIconEnum iconChar, const ImVec2& size_arg, bool repeat_when_held)
{
IM_ASSERT(GIconFont);
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
char labelIcon[8] = { 0 };
ImTextCharToUtf8(labelIcon, 8, (unsigned int)iconChar);
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
ImGui::PushFont(GIconFont);
const ImVec2 label_icon_size = CalcTextSize(labelIcon, NULL, true);
ImGui::PopFont();
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : (label_size.x + label_icon_size.x + style.ItemInnerSpacing.x + style.FramePadding.x * 2),
size_arg.y != 0.0f ? size_arg.y : ImMax(label_size.y + style.FramePadding.y * 2, label_icon_size.y + style.FramePadding.y * 2));
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
ItemSize(bb, style.FramePadding.y);
if (!ItemAdd(bb, &id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, true, repeat_when_held ? ImGuiButtonFlags_Repeat : 0);
// Render
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
ImGui::PushFont(GIconFont);
const ImVec2 offIcon = ImVec2(ImMax(0.0f, size.x - label_size.x - label_icon_size.x - style.ItemInnerSpacing.x) * 0.5f, ImMax(0.0f, size.y - label_icon_size.y) * 0.5f); // Center (only applies if we explicitly gave a size bigger than the text size, which isn't the common path)
RenderTextClipped(bb.Min + offIcon, labelIcon, NULL, NULL, bb.Max, NULL);
ImGui::PopFont();
const ImVec2 off = ImVec2(ImMax(0.0f, size.x - label_size.x + label_icon_size.x + style.ItemInnerSpacing.x) * 0.5f, ImMax(0.0f, size.y - label_size.y) * 0.5f); // Center (only applies if we explicitly gave a size bigger than the text size, which isn't the common path)
RenderTextClipped(bb.Min + off, label, NULL, &label_size, bb.Max, NULL); // Render clip (only applies if we explicitly gave a size smaller than the text size, which isn't the commmon path)
return pressed;
} You use it like this ImGui::ButtonIcon("Button Line 1\nButton Line 2", ImGui_fa_camera_retro); |
Hi, There's several things here.
Everything is possible really..
|
My code is just a simple test with a fixed layout that doesn't cover everyone's cases of course. I was wondering if I could quickly get some button icons using .ttf fonts, and I'm sharing in case someone else wants to play or elaborate some more. Your considerations on the line layout control are making me think that the real world use case for "inline" icon font mixed with regular character are maybe fewer than I was thinking, unless, like you're suggesting, one thinks of a mini markup language, that doesn't absolutely fit the simplicity and style of the ImGui api. Personally it has been taking me 3 minutes to get the layout I was looking for by copying/pasting/modifying the ImGui::Button code, so I really don't feel the need for a mini markup language. |
Will probably do a) loading range from multiple fonts into one + b) font scaling.
I will keep working on this with the intent of opening more of imgui.cpp down the line (which means supporting its API) but I have no doubt it will take a long time until we get there. static bool ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : (label_size.x + style.FramePadding.x*2), size_arg.y != 0.0f ? size_arg.y : (label_size.y + style.FramePadding.y*2));
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
ItemSize(bb, style.FramePadding.y);
if (!ItemAdd(bb, &id))
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, true, flags);
// Render
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, NULL, ImGuiAlign_Center | ImGuiAlign_VCenter);
// Automatically close popups
if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
ImGui::CloseCurrentPopup();
return pressed;
}
bool ImGui::Button(const char* label, const ImVec2& size_arg, bool repeat_when_held)
{
return ButtonEx(label, size_arg, repeat_when_held ? ImGuiButtonFlags_Repeat : 0);
} And I intend to remove the "repeat" flag (which is rarely used) and move it to a helper function or stateful thing. Especially before repeat needs timing parameters anyway. |
I was expecting to be walking on thin ice when using internal api, so breaking changes are not a big deal ;) |
The AA branch now support this with the new ImFontConfig* settings. Merge two fonts: io.Fonts->AddFontDefault();
// Add character ranges and merge into main font
static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); There's a few catch here. You can specify a different size to some degree but the font ine height will always be based on the first font of a merged list. So here the default font is 13 and 16 for the icon is alright, but if you use 30 icons it won't fit. By default characters of different sizes are aligned on their baseline. You can see config.MergeGlyphCenterV = true to center the merged character vertically which may make more sense with icons. It works but it's probably a little limited in the sense that you'll need your icon to be roughly the same size as your text. You can adjust the config.OversampleH, config.OversampleV parameters, even without using subpixel positioning this will also give you leeway you scale the font display with less noticeable artefacts. |
This is now merged in master along with the entire new AA-branch. Note that it is a rather big update and you'll need to update your render function to use indexed vertex rendering. |
will demo be showcasing this anytime soon? |
BTW, I have try the following code, but the "PushFont" crash ! It seems the font is not loaded, why ?
|
Where does it crash? |
No it is one code block ! It crash at "SetCurrentFont": IM_ASSERT(font && font->IsLoaded()); |
I have not called "GetTexDataAsRGBA32", but what it is used for ? and how to use it ? Thx |
You cannot use the font before it has been built into a font atlas. |
Thanks Omar, I have just put the following code before the GetTexData* :
But when I try to use the font I got the wrong symbok, I got an ASCII one ?
|
Well you aren't passing the desired ranges to AddFont. And when you do make sure ranges[] is global/static. |
Yes, it is what I have do :
|
ImGui::Button("\uF04B"); isn't correct it is 16-bit unicode whereas ImGui takes UTF-8. According to this it looks like you can utf-8 encode using an u8 (unsigned char) prefix: |
Actually I am being confused with those fancy modern literals |
#include |
adjust your path to the .ttf file, or move the executable to a proper folder |
Redownload.ttf file ,Compile it sucessfully now,Thanks! |
I've tried loading some icon fonts and it works great for button icons etc.
Anyway if you want to make a button (or other control) with an Icon followed by some text, you cannot do it easily.
The current ImGui::Button() call that assumes a single font for the label, unless you bake your ttf characters into the icon font (or the opposite).
My opinion is that for practical use it should be possible to map those icon fonts into some glyph range of current font (not a new one).
I've not gone in the details of the source code generating the glyphs so I'm not sure of the implications and/or difficulty.
Just as an idea, icon fonts could be used to create the vector graphics for new ui/graphics theme like described in #184 without the need of bitmaps (that will not scale easily on higher DPI displays) or fancy SVG drawings (that requires an SVG parser/renderer etc).
Comments?
The text was updated successfully, but these errors were encountered: