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

Is Buttons with Icons / Pictures possible? #1096

Closed
Questionark opened this issue Apr 11, 2017 · 59 comments
Closed

Is Buttons with Icons / Pictures possible? #1096

Questionark opened this issue Apr 11, 2017 · 59 comments

Comments

@Questionark
Copy link

Questionark commented Apr 11, 2017

So I'd like to know if it's possible to add pictures on the buttons.

I can't really find any examples in the demo.

@colesnicov
Copy link

colesnicov commented Apr 12, 2017

Hi,
ImGui::ImageButton(...)?

Or You can create custom control and share..., like this: #282

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2017 via email

@Flix01
Copy link

Flix01 commented Apr 12, 2017

@Questionark: This is what I got in my branch:

// Declaration (.h file)
namespace ImGui {
// label is used as id
// <0 frame_padding uses default frame padding settings. 0 for no padding
IMGUI_API bool ImageButtonWithText(ImTextureID texId,const char* label,const ImVec2& imageSize=ImVec2(0,0), const ImVec2& uv0 = ImVec2(0,0),  const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1));
} // namespace ImGui

// Definition (.cpp file. Not sure if it needs "imgui_internal.h" or not)
namespace ImGui {
bool ImageButtonWithText(ImTextureID texId,const char* label,const ImVec2& imageSize, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col) {
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
    return false;

    ImVec2 size = imageSize;
    if (size.x<=0 && size.y<=0) {size.x=size.y=ImGui::GetTextLineHeightWithSpacing();}
    else {
        if (size.x<=0)          size.x=size.y;
        else if (size.y<=0)     size.y=size.x;
        size*=window->FontWindowScale*ImGui::GetIO().FontGlobalScale;
    }

    ImGuiContext& g = *GImGui;
    const ImGuiStyle& style = g.Style;

    const ImGuiID id = window->GetID(label);
    const ImVec2 textSize = ImGui::CalcTextSize(label,NULL,true);
    const bool hasText = textSize.x>0;

    const float innerSpacing = hasText ? ((frame_padding >= 0) ? (float)frame_padding : (style.ItemInnerSpacing.x)) : 0.f;
    const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
    const ImVec2 totalSizeWithoutPadding(size.x+innerSpacing+textSize.x,size.y>textSize.y ? size.y : textSize.y);
    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + totalSizeWithoutPadding + padding*2);
    ImVec2 start(0,0);
    start = window->DC.CursorPos + padding;if (size.y<textSize.y) start.y+=(textSize.y-size.y)*.5f;
    const ImRect image_bb(start, start + size);
    start = window->DC.CursorPos + padding;start.x+=size.x+innerSpacing;if (size.y>textSize.y) start.y+=(size.y-textSize.y)*.5f;
    ItemSize(bb);
    if (!ItemAdd(bb, &id))
    return false;

    bool hovered=false, held=false;
    bool pressed = ButtonBehavior(bb, id, &hovered, &held);

    // Render
    const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
    RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
    if (bg_col.w > 0.0f)
    window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));

    window->DrawList->AddImage(texId, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));

    if (textSize.x>0) ImGui::RenderText(start,label);
    return pressed;
}
} // namespace ImGui

selection_051

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2017

First look at ImageButton() and understand how ImTextureId works. Creating your own widget using the internal header should be a last recourse especially if you are confused by the earlier steps.

@Questionark
Copy link
Author

I might have confused you all, what I meant was ICONS on buttons, not just a side picture with text on the button, I wanna completely change the button from TEXT to ICON, is that possible? I looked here and there and I saw another thread about this with .tt(something) fonts on buttons, does this still work?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

@Questionark: Sorry. Then @colesnicov and @ocornut are right.

ImageButton() is what you're looking for.

@Questionark
Copy link
Author

Alrighty then, thanks 4 your help :D

@Questionark
Copy link
Author

Questionark commented Apr 12, 2017

I really can't get this to work, could someone give me a quick pseudo code to look at? I really don't understand the demo.cpp

This is my current code, which was a disaster:

`static float tex_w = 32.0f;
static int tex_h = 32;
ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;

            static int pressed_count = 0;
            ImGui::PushID(i);
            int frame_padding = -1 + i; 
		if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255)), ImVec2(ImGui::GetWindowSize().x / IM_ARRAYSIZE(tabs) - 9, 0))
			page = i;
            pressed_count += 1;
            ImGui::PopID(); 
        //ImGui::Button(tabs[i]`

@Flix01
Copy link

Flix01 commented Apr 12, 2017

I looked here and there and I saw another thread about this with .ttf fonts on buttons, does this still work?

You can add an "icon font" so that you can use normal ImGui::Button() to display the icons (because they are actually text characters). The drawback is that they aren't multicolor.
For these see: https://github.com/juliettef/IconFontCppHeaders and #1030

ImGui::ImageButton() instead allows you to use a generic image (e.g. png, jpg,etc.) as a button.

ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;

ImTextureID is something your ImGui backend must implement (that's why it is not present in imgui_demo.cpp). Basically you need to write code that can load an image and turn it into a texture.
The code depends on your graphic library (OpenGL, Direct3D, etc.) AND your image library (for example stb_image.h or SDL_image or FreeImage).

@Questionark
Copy link
Author

Hey thanks for replying @Flix01 I don't really care about colors, white/black is completely fine for me.
The link with the icon fonts, do I have to download that into my current imgui folder? and include it all inside the imgui.h or how does this work, because honestly I've never really added stuff to imgui.

@Questionark
Copy link
Author

and would it be possible to provide a simple pseudo code with these "Icon fonts" in use?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

Well, you just need the icon font .ttf and the header file.

In the link there are 3 icon fonts: I suggest you use FontAwesome, since it's the most popular.
Then you need its header IconsFontAwesome_c.h or IconsFontAwesome.h if you use C++11.

However in that repository the .ttf are not present, because they are generated on the fly by a python script.

Alternatively you can use these links for FontAwesome:
Font: https://github.com/Flix01/imgui/blob/imgui_with_addons/examples/addons_examples/fonts/Icons/FontAwesome4/font.ttf?raw=true
C Header: https://github.com/Flix01/imgui/blob/imgui_with_addons/examples/addons_examples/fonts/Icons/FontAwesome4/definitions.h?raw=true
License: https://github.com/Flix01/imgui/blob/imgui_with_addons/examples/addons_examples/fonts/Icons/FontAwesome4/LICENSE.txt?raw=true

@Questionark
Copy link
Author

I already have a .ttf font, so I was wondering, if I already have one, would I need to even add the IconsFontAwesome?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

The pseudo code is the same as Juliette's repository. Something like:

#include "IconsFontAwesome.h"

ImGuiIO& io = ImGui::GetIO();
 io.Fonts->AddFontDefault();
 
 // merge in icons from Font Awesome
static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
io.Fonts->AddFontFromFileTTF( fontFile.c_str(), 16.0f, &icons_config, icons_ranges);

// in an imgui window somewhere...
ImGui::Text( ICON_FA_FILE "  File" ); // use string literal concatenation, ouputs a file icon and File as a string.

[Of course you must change the .ttf name and the header file name...]

@Flix01
Copy link

Flix01 commented Apr 12, 2017

I already have a .ttf font, so I was wondering, if I already have one, would I need to even add the IconsFontAwesome?

You need to add the .ttf ICON font to yours.

@Flix01
Copy link

Flix01 commented Apr 12, 2017

If your .ttf font already includes the icons you want to use, you don't need nothing else...

@Questionark
Copy link
Author

I'm not sure I'm following, I have a .ttf file ONLY, and when I open it I see bunch of icons in my interest.
But I still don't understand how I can include this single file to my project and use it.

@Flix01
Copy link

Flix01 commented Apr 12, 2017

OK. Now there's one more question: Are the icons standard UTF8 characters ?
I ask because there's a difference between a standard .ttf font and an icon .ttf font (basically the latter remaps some characters to some icons, and thus it needs a header file to allow displaying them).

@Flix01
Copy link

Flix01 commented Apr 12, 2017

I takes less time if you tell me the name of your .ttf file...

@Questionark
Copy link
Author

And how can I check that exactly?

@Questionark
Copy link
Author

Well it's a custom one a friend made for me,

TuxgodsIcons.zip

@Flix01
Copy link

Flix01 commented Apr 12, 2017

Well, it's an icon font! You should know which glyphs are mapped with the icons and add them to the "icons_ranges[]". Maybe asking your friend or using some kind of font viewer might help.
Maybe you can try and see how the header files of Juliette's are made.

@Questionark
Copy link
Author

He just logged off :(

Well can we go back to the FontAwesome, I just installed it and pasted it all into my imgui folder, and I've included the IconFontAwesome inside the imgui.h, but how do I exactly use this code now? And how can I customize/download other icons and use them with FontAwesome?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

See the code I pasted above: you must use MergeMode:
ImFontConfig icons_config; icons_config.MergeMode = true;
and then just append the definition you need from the header file:
ImGui::Text( ICON_FA_FILE " File" ); // use string literal concatenation, ouputs a file icon and File as a string.

Of course you can use ImGui::Button() instead

@Flix01
Copy link

Flix01 commented Apr 12, 2017

P.S. Your "TuxGodsIcons.ttf" is almost unusable, because it maps its icons in the interval:
0x0041, 0x004d, // uppercase A-M

That probably means that you can't use the uppercase range from "A" to "M" if you want to use those icons (unless you shift the interval somewhere with a .ttf font editor).

@Questionark
Copy link
Author

Thanks for your help, I really appreciate it @Flix01 I kinda gave up on the TuxGodsIcons.ttf, so I'm trying to figure out how to add icons and use them. To be honest, I don't really understand most of the pseudo code you provided me.

Currently this is my code:

`//Example starts here
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();

		// merge in icons from Font Awesome
		static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
		ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
		io.Fonts->AddFontFromFileTTF( fontFile.c_str(), 16.0f, &icons_config, icons_ranges);

		if (ImGui::Button(ICON_FA_FILE tabs[i], ImVec2(ImGui::GetWindowSize().x / IM_ARRAYSIZE(tabs) - 9, 0)))
		page = i;`

@Questionark
Copy link
Author

Although, the issue is that it says fontFile.c_str() was not declared in this scope, and I have no idea what it actually is.

@Questionark
Copy link
Author

Questionark commented Apr 12, 2017

Okay so, I fixed some stuff, and I'm trying out this fontawesome-webfont.ttf

Although, how do I apply the font to the button?

Like I'm currently doing this:

                ImGuiIO& io = ImGui::GetIO();
   		io.Fonts->AddFontDefault();
   		ImFontConfig config;
   		config.MergeMode = true;
   		const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
   		io.Fonts->AddFontFromFileTTF("../../ImGUI/fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);

			if (ImGui::Button(TPYEHER, ImVec2(ImGui::GetWindowSize().x / IM_ARRAYSIZE(tabs) - 9, 0)))
			page = i;

@Flix01
Copy link

Flix01 commented Apr 12, 2017

                ImGuiIO& io = ImGui::GetIO();
   		io.Fonts->AddFontDefault();

  // merge in icons from Font Awesome
static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
io.Fonts->AddFontFromFileTTF( "../../ImGUI/fonts/fontawesome-webfont.ttf", 13.0f, &icons_config, icons_ranges);

			if (ImGui::Button(ICON_FA_FILE "  File")) {}

@Questionark
Copy link
Author

It just shows a question mark on the button, does it not load the correct path?

@Questionark
Copy link
Author

I definitely copy pasted the exact same code

@Questionark
Copy link
Author

Questionark commented Apr 12, 2017

And it still seems to give me the question mark as an ICON, then beside the ICON (which is a questionmark) it gives me text like FILE as you wrote.

@Questionark
Copy link
Author

@Flix01
Copy link

Flix01 commented Apr 12, 2017

OK. Things you can check:

  1. Does the program really find "../../ImGUI/fonts/fontawesome-webfont.ttf" ? If you comment out io.Fonts->AddFontFromFileTTF( ...) you should see the same question mark.
  2. The .ttf file and the .h definition file must match (you might have a different version of the .ttf file, not in sync with the header file, so that some glyph definition is actually empty).
  3. You .cpp file must be encoded in UTF8 (not sure how you can test it).
  4. I'm not using a Windows OS, but I guess your project must use UTF8, or maybe you can play with the UNICODE and _UNICODE definitions and see if something changes... I can't help much on this, 'cause I'm on Linux.

I think point (1) might be the most probable.

@Questionark
Copy link
Author

Questionark commented Apr 12, 2017

I'm on linux myself. So I guess some things would change?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

Point 3 and 4 should be OK.
1 and 2 are still to check.

And remember that on Linux file system names are case sensitive.

@Questionark
Copy link
Author

Yes of course, I just checked point 1, and removed the path, rechecked and it still gave me the question mark, which means I input the wrong path. Now I'm kinda confused.

Do I have to place the path based on where the code is, or based on where the included .h files are?

Let's say I'm coding in this path: MainFolder/Codenz/File.cpp
And my fonts are in this folder: MainFolder/Fonts/Font.ttf
And the included .h files are in this folder: MainFolder/ImGui/IconFontAmazing/IconsFontAmazing.h

How would I go by declaring the path?
In my understanding it would be like this: "../Fonts/Font.ttf"

@Questionark
Copy link
Author

And to be sure, are we talking about the imgui.h as ".h definitions file" in point 2?
or the "IconsFontAwesome.h"

@Flix01
Copy link

Flix01 commented Apr 12, 2017

And to be sure, are we talking about the imgui.h as ".h definitions file" in point 2?
or the "IconsFontAwesome.h"

"IconsFontAwesome.h" of course.

Do I have to place the path based on where the code is, or based on where the included .h files are?

Relative to the (exe) program you run, not the source files.

@Questionark
Copy link
Author

Questionark commented Apr 12, 2017

This makes no sense, it still gives me the damn question-mark.
Are there any .ttf files that are guaranteed to work with IconsFontAwesome I can test with?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

The two in the links I posted above (you can rename definitions.h -> IconsFontAwesome.h and font.ttf -> FontAwesome.ttf). I've tested them myself.

However I still think it's a path problem. Try the following: just copy/paste/rename FontAwesome.ttf next to your exe, then change the line this way:
io.Fonts->AddFontFromFileTTF( "FontAwesome.ttf", 13.0f, &icons_config, icons_ranges);
Recompile and rerun the program (outside of any IDE is better) and see if it works.

@Questionark
Copy link
Author

Okay so, I did as you said and it still wouldn't work, so what I tried was adding a random .h file inside the folder of the .ttf, and #include .h file, to see if it actually could include such a file, to check if the path was valid, and guess what it was a valid path, so apparently it's not anything to do with the path, cuz the compiler validates the path. So I'm lost again.

@Flix01
Copy link

Flix01 commented Apr 12, 2017

One thing is including a source file inside another, another thing is loading a file from the current path in the exe.

What you could try is just to use another (non-icon) .ttf font loaded from file in an imgui demo (without using the merge mode), to be sure it can find it.

@Questionark
Copy link
Author

I honestly can't see why it shouldn't work, there's nothing wrong with the code, this is exactly what the code is 1:1, copy pasted.

ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();

// merge in icons from Font Awesome
static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
io.Fonts->AddFontFromFileTTF("../../ImGUI/extra_fonts/FontXD", 13.0f, &icons_config, icons_ranges);
ImGui::Button( ICON_FA_FILE " File");

@Questionark
Copy link
Author

I will try that

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2017 via email

@Flix01
Copy link

Flix01 commented Apr 12, 2017

"../../ImGUI/extra_fonts/FontXD" has no .ttf extension...

@Questionark
Copy link
Author

Yea I forgot that.
But same result, @ocornut that's noted, I will definitely have to spend some time on this alone, but this is an issue that really frustrates me and a guy is nice enough to spend his time helping. Could we please continue without you closing the issue?

@Flix01
Copy link

Flix01 commented Apr 12, 2017

Actually I thought the issue was already closed...

@Questionark
Copy link
Author

Okay, well I'm gonna have to give up at this point and try something else @Flix01 I appreciate your help and the time you spent. Have a good day.

@ocornut
Copy link
Owner

ocornut commented Apr 12, 2017 via email

@ocornut ocornut closed this as completed Apr 12, 2017
@Flix01
Copy link

Flix01 commented Apr 12, 2017

@Questionark @ocornut good day to you too.

I am going to close this issue but you can still post messages to a closed issue.

That's the main reason why I kept answering: I thought the issue was already closed (no need to pollute Imgui with details too much OT like relative path resolution).

@Questionark
Copy link
Author

Wait wut, I didn't even know you could continue in a closed thread.

@Questionark
Copy link
Author

@Flix01 Would you wanna continue the help?
Cuz I have all day to work on this and I really can't figure this shieeet out

@Flix01
Copy link

Flix01 commented Apr 13, 2017

Honestly, I'm running out of advices...
So if you have some question it's OK for me, but otherwise...

@rlalance
Copy link

rlalance commented Jan 2, 2019

Ah, exact problem I faced.

When using chrome save as..., the file saved is HTML instead of the .ttf, but filename mislead you to think you saved the font file!

image

Cloning the font repo, and copying the files gave better results :)

@sphaero
Copy link

sphaero commented Jan 27, 2021

I just had a similar issue (question mark instead of icon) which was caused by not using a fresh ImFontConfig.

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

6 participants