ocornut / imgui

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

Simplified styling #438

Open ocornut opened 8 years ago

ocornut commented 8 years ago

Following tweet https://twitter.com/relativetoyou/status/675856390070644737 Trying to find a way to setup styles neatly with minimal amount of parameters

Original code is https://github.com/ofnode/ofxImgui/blob/2a3c2a7/src/ofxImgui.cpp#L79-L138

I adjusted it, made some fix but missing stuff, trying to make it more readable. Also added more parameters for testing. which pretty much going against the point but it is trying to figure how what minimal set of parameters could be exposed. Perhaps only "Hue" and some sort of single "Variance"? Some really sure what's right, need some fiddling if anybody wants to play with that and make a definitive "simplified" version with very few parameters that gives decent results.

It doesn't actually look too great now - at some hue it's ok but not all.

Ideally we could add those controls as part of the regular Style Editor so you can use the simplified mode or go advanced to overwrite individual stuff. Then again I somehow expect styling settings to change noticeably when heading toward #184

hue styling

void SetupStyleFromHue()
{
#if 1
    // FIXME: those should become parameters to the function
    static int hue = 140;
    static float col_main_sat = 180.f/255.f;
    static float col_main_val = 161.f/255.f;
    static float col_area_sat = 124.f/255.f;
    static float col_area_val = 100.f/255.f;
    static float col_back_sat = 59.f/255.f;
    static float col_back_val = 40.f/255.f;

    ImGui::Begin("Hue Style");
    ImGui::SliderInt("master hue", &hue, 0, 255);

    float dummy;
    ImVec4 rgb; 
    ImGui::ColorEditMode(ImGuiColorEditMode_HSV);

    ImGui::ColorConvertHSVtoRGB(hue/255.f, col_main_sat, col_main_val, rgb.x, rgb.y, rgb.z);
    ImGui::ColorEdit3("main", &rgb.x);
    ImGui::ColorConvertRGBtoHSV(rgb.x, rgb.y, rgb.z, dummy, col_main_sat, col_main_val);

    ImGui::ColorConvertHSVtoRGB(hue/255.f, col_area_sat, col_area_val, rgb.x, rgb.y, rgb.z);
    ImGui::ColorEdit3("area", &rgb.x);
    ImGui::ColorConvertRGBtoHSV(rgb.x, rgb.y, rgb.z, dummy, col_area_sat, col_area_val);

    ImGui::ColorConvertHSVtoRGB(hue/255.f, col_back_sat, col_back_val, rgb.x, rgb.y, rgb.z);
    ImGui::ColorEdit3("back", &rgb.x);
    ImGui::ColorConvertRGBtoHSV(rgb.x, rgb.y, rgb.z, dummy, col_back_sat, col_back_val);

    ImGui::End();
#endif

    ImGuiStyle& style = ImGui::GetStyle();

    ImVec4 col_text = ImColor::HSV(hue/255.f,  20.f/255.f, 235.f/255.f);
    ImVec4 col_main = ImColor::HSV(hue/255.f, col_main_sat, col_main_val);
    ImVec4 col_back = ImColor::HSV(hue/255.f, col_back_sat, col_back_val);
    ImVec4 col_area = ImColor::HSV(hue/255.f, col_area_sat, col_area_val);

    style.Colors[ImGuiCol_Text]                  = ImVec4(col_text.x, col_text.y, col_text.z, 1.00f);
    style.Colors[ImGuiCol_TextDisabled]          = ImVec4(col_text.x, col_text.y, col_text.z, 0.58f);
    style.Colors[ImGuiCol_WindowBg]              = ImVec4(col_back.x, col_back.y, col_back.z, 1.00f);
    style.Colors[ImGuiCol_ChildWindowBg]         = ImVec4(col_area.x, col_area.y, col_area.z, 0.00f);
    style.Colors[ImGuiCol_Border]                = ImVec4(col_text.x, col_text.y, col_text.z, 0.30f);
    style.Colors[ImGuiCol_BorderShadow]          = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
    style.Colors[ImGuiCol_FrameBg]               = ImVec4(col_area.x, col_area.y, col_area.z, 1.00f);
    style.Colors[ImGuiCol_FrameBgHovered]        = ImVec4(col_main.x, col_main.y, col_main.z, 0.68f);
    style.Colors[ImGuiCol_FrameBgActive]         = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_TitleBg]               = ImVec4(col_main.x, col_main.y, col_main.z, 0.45f);
    style.Colors[ImGuiCol_TitleBgCollapsed]      = ImVec4(col_main.x, col_main.y, col_main.z, 0.35f);
    style.Colors[ImGuiCol_TitleBgActive]         = ImVec4(col_main.x, col_main.y, col_main.z, 0.78f);
    style.Colors[ImGuiCol_MenuBarBg]             = ImVec4(col_area.x, col_area.y, col_area.z, 0.57f);
    style.Colors[ImGuiCol_ScrollbarBg]           = ImVec4(col_area.x, col_area.y, col_area.z, 1.00f);
    style.Colors[ImGuiCol_ScrollbarGrab]         = ImVec4(col_main.x, col_main.y, col_main.z, 0.31f);
    style.Colors[ImGuiCol_ScrollbarGrabHovered]  = ImVec4(col_main.x, col_main.y, col_main.z, 0.78f);
    style.Colors[ImGuiCol_ScrollbarGrabActive]   = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_ComboBg]               = ImVec4(col_area.x, col_area.y, col_area.z, 1.00f);
    style.Colors[ImGuiCol_CheckMark]             = ImVec4(col_main.x, col_main.y, col_main.z, 0.80f);
    style.Colors[ImGuiCol_SliderGrab]            = ImVec4(col_main.x, col_main.y, col_main.z, 0.24f);
    style.Colors[ImGuiCol_SliderGrabActive]      = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_Button]                = ImVec4(col_main.x, col_main.y, col_main.z, 0.44f);
    style.Colors[ImGuiCol_ButtonHovered]         = ImVec4(col_main.x, col_main.y, col_main.z, 0.86f);
    style.Colors[ImGuiCol_ButtonActive]          = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_Header]                = ImVec4(col_main.x, col_main.y, col_main.z, 0.76f);
    style.Colors[ImGuiCol_HeaderHovered]         = ImVec4(col_main.x, col_main.y, col_main.z, 0.86f);
    style.Colors[ImGuiCol_HeaderActive]          = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_Column]                = ImVec4(col_text.x, col_text.y, col_text.z, 0.32f);
    style.Colors[ImGuiCol_ColumnHovered]         = ImVec4(col_text.x, col_text.y, col_text.z, 0.78f);
    style.Colors[ImGuiCol_ColumnActive]          = ImVec4(col_text.x, col_text.y, col_text.z, 1.00f);
    style.Colors[ImGuiCol_ResizeGrip]            = ImVec4(col_main.x, col_main.y, col_main.z, 0.20f);
    style.Colors[ImGuiCol_ResizeGripHovered]     = ImVec4(col_main.x, col_main.y, col_main.z, 0.78f);
    style.Colors[ImGuiCol_ResizeGripActive]      = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_CloseButton]           = ImVec4(col_text.x, col_text.y, col_text.z, 0.16f);
    style.Colors[ImGuiCol_CloseButtonHovered]    = ImVec4(col_text.x, col_text.y, col_text.z, 0.39f);
    style.Colors[ImGuiCol_CloseButtonActive]     = ImVec4(col_text.x, col_text.y, col_text.z, 1.00f);
    style.Colors[ImGuiCol_PlotLines]             = ImVec4(col_text.x, col_text.y, col_text.z, 0.63f);
    style.Colors[ImGuiCol_PlotLinesHovered]      = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_PlotHistogram]         = ImVec4(col_text.x, col_text.y, col_text.z, 0.63f);
    style.Colors[ImGuiCol_PlotHistogramHovered]  = ImVec4(col_main.x, col_main.y, col_main.z, 1.00f);
    style.Colors[ImGuiCol_TextSelectedBg]        = ImVec4(col_main.x, col_main.y, col_main.z, 0.43f);
    style.Colors[ImGuiCol_TooltipBg]             = ImVec4(col_main.x, col_main.y, col_main.z, 0.92f);
    style.Colors[ImGuiCol_ModalWindowDarkening]  = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}
thennequin commented 8 years ago

Very cool, thanks

ghost commented 8 years ago

I use such method, it allow to start from a "base" color and derivate Active color / Hover colors etc...

ImVec4 ColorFade(ImVec4 rgb, float percents)
{
    ImVec4 r;

    percents /= 100.f;

    r.x = min(1.f, rgb.x * (1.f + percents));
    r.y = min(1.f, rgb.y * (1.f + percents));
    r.z = min(1.f, rgb.z * (1.f + percents));
    r.w = rgb.w;

    return r;
}
r-lyeh-archived commented 8 years ago

@dougbinks has stated in twitter that you can inverse V if S < 0.1f too to get an alternative (negative) theme for both default and Itamago's themes.

For future reference, this is how I am achieving that (by shadowing ImVec4 locally):

void ApplyItamagosTheme( bool alt = false ) {

    auto ImVec4 = [&alt]( float r, float g, float b, float a ) {
        float h, s, v;
        ImGui::ColorConvertRGBtoHSV( r, g, b, h, s, v );
        if( alt && (s < 0.1f) ) v = 1 - v;
        ImGui::ColorConvertHSVtoRGB( h, s, v, r, g, b );
        return ImColor(r,g,b,a);
    };

    ImGuiStyle& style = ImGui::GetStyle();
    style.Colors[ImGuiCol_Text]                  = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
    style.Colors[ImGuiCol_TextDisabled]          = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
    style.Colors[ImGuiCol_WindowBg]              = ImVec4(0.94f, 0.94f, 0.94f, 1.00f);
    style.Colors[ImGuiCol_ChildWindowBg]         = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
    style.Colors[ImGuiCol_Border]                = ImVec4(0.00f, 0.00f, 0.00f, 0.39f);
    // [ ... ] omitted
}
dougbinks commented 8 years ago

I just do this:

void StyleInvert()
{
    ImGuiStyle& style = ImGui::GetStyle();
    for (int i = 0; i < ImGuiCol_COUNT; i++)
    {
        ImVec4& col = style.Colors[i];
        float H, S, V;
        ImGui::ColorConvertRGBtoHSV( col.x, col.y, col.z, H, S, V );
        if( S < 0.1f )  { V = 1.0 - V; }
        ImGui::ColorConvertHSVtoRGB( H, S, V, col.x, col.y, col.z );
    }
}
r-lyeh-archived commented 8 years ago

:+1:

r-lyeh-archived commented 6 years ago

Random thoughts.

Some more tips for styling:

And since you are using HSL/HSV in the color editor menus, why dont...?:

ocornut commented 6 years ago

Allow drag'n'drop themes like hundredrabbits/Themes#2

You are free to do so. To me it seems superfluous compared to actually getting the Style system reworked. (Whenever I even see a Style Editor open in an imgui screenshot/video, which is too many times, I know that I haven't done my job of making people able to use the library as-is!)

Does imgui really need to use that variable list so long?

Probably not. But it also support more features than the HundredRabbits stuff which are carefully crafted design. Some people want simple styling, some people will want to make pro tools with hundred of daily users and will want to tweak every shape, borders and colors for readability.

And since you are using HSL/HSV in the color editor menus, why dont...?:

May use delta in HSL/HSV space but it has to be done in a way that don't cost back-and-forth dozens of HSV conversion every time someone does a couple of Push/Pop for items in a loop.

Essentially I agree with your sentiment, style will be reworked to go toward this direction. I just have so much on my plate already. Also see #1223.

r-lyeh-archived commented 6 years ago

Just throwing a few easy ideas to complement the new reworking direction. Not meant in any way to use it as primary direction :)

Btw, the HSV buttons, and the shift/mutate/conversion are meant to be used in the style editor to simplify customizing a bit. Not meant to be used in the end-user API at all! :)

r-lyeh-archived commented 6 years ago

Also, another idea:

ocornut commented 6 years ago

Btw, the HSV buttons, and the shift/mutate/conversion are meant to be used in the style editor to simplify customizing a bit. Not meant to be used in the end-user API at all! :)

Would be good, though it would create an extra gap between the data you see in style editor and the programmatic side, so the UI would need to show data in multiple forms (luckily writing UI is easy for us).

I'm not particularly interested about optimize for "sharing themes", and fluff like "drag and drop a theme", I think it detract us from using dear imgui. Ideally I'd rather have 5-6 themes that are great enough that no one feels the need to spend time thinking about styling. The way toward that is long enough we could focus on this... if someone wants to encode theme in whatever z85 they feel is a fun thing to do, why not.

ImguiPower commented 6 years ago

Hi, i need something like this but in lua, can someone help me please?

haldean commented 5 years ago

I wrote something similar to this as well, but with a slightly different set of parameters; I found you could get better results if you had separate hues for the accent color and the frame/window color. I posted the code in the gallery thread: https://github.com/ocornut/imgui/issues/2265#issuecomment-465432091

maximvl commented 5 years ago

Hi, is it possible to set a theme for a specific window? Thanks!

LuanDevecchi commented 5 years ago

Hi, is it possible to set a theme for a specific window? Thanks!

you can simply set new style before rendering it then restore the old style