Imgui: Progress widget

Created on 15 Sep 2015  路  10Comments  路  Source: ocornut/imgui

A progress widget would be nice.

I actually need to display horizontal bars of various width, which represent the percentage of some internal values. I'm currently using buttons of width from 0 to N, but a progress widget would be much more suitable for this (and possibly also displaying actual progress)

If @ocornut doesn't have time for this, I'm gonna implement it myself, but in a couple of weeks (when I'm going to have time for this) probably reusing the slider code

enhancement

Most helpful comment

Added.
IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL);

progress_bar2

All 10 comments

You can do that trivially with the DrawList api.

Something like

ImVec2 size;
..
ImVec2 pos = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ....) // fill
ImGui::GetWindowDrawList()->AddRect(pos, pos + ....) ; // border
ImGui::Dummy(size);

Great! Would you mind if I make a pull request with a function ImGui::Progress with similar behavior?

Yes in theory, but I haven't really thought about what the input would be for such functions if it was in the standard API. Color? Fill ratio? Explicit size or using standard widget size or both? Label or not? Some parameters to split the filled parts into blocks?

If you make it a default API thing it's better using coding style similar to other internal code (direct access to fields as needed instead of calling functions).

Here is my simple version:

imguiprogressbar.h

#ifndef IMGUIPROGRESSBAR_H
#define  IMGUIPROGRESSBAR_H
#include <imgui.h>
namespace ImGui {
// Please note that you can tweak the "format" argument if you want to add a prefix (or a suffix) piece of text to the text that appears at the right of the bar.
// returns the value "fraction" in 0.f-1.f.
// It does not need any ID.
float ProgressBar(const char* optionalPrefixText,float value,const float minValue=0.f,const float maxValue=1.f,const char* format="%1.0f%%",const ImVec2& sizeOfBarWithoutTextInPixels=ImVec2(-1,-1),
                 const ImVec4& colorLeft=ImVec4(0,1,0,0.8),const ImVec4& colorRight=ImVec4(0,0.4,0,0.8),const ImVec4& colorBorder=ImVec4(0.25,0.25,1.0,1));

void TestProgressBar();
}
#endif // IMGUIPROGRESSBAR_H

imguiprogressbar.cpp

#include "imguiprogressbar.h"
namespace ImGui {
float ProgressBar(const char *optionalPrefixText, float value, const float minValue, const float maxValue, const char *format, const ImVec2 &sizeOfBarWithoutTextInPixels, const ImVec4 &colorLeft, const ImVec4 &colorRight, const ImVec4 &colorBorder)    {
    if (value<minValue) value=minValue;
    else if (value>maxValue) value = maxValue;
    const float valueFraction = (maxValue==minValue) ? 1.0f : ((value-minValue)/(maxValue-minValue));
    const bool needsPercConversion = strstr(format,"%%")!=NULL;

    ImVec2 size = sizeOfBarWithoutTextInPixels;
    if (size.x<=0) size.x = ImGui::GetWindowWidth()*0.25f;
    if (size.y<=0) size.y = ImGui::GetTextLineHeightWithSpacing(); // or without

    const ImFontAtlas* fontAtlas = ImGui::GetIO().Fonts;

    if (optionalPrefixText && strlen(optionalPrefixText)>0) {
        ImGui::AlignFirstTextHeightToWidgets();
        ImGui::Text(optionalPrefixText);
        ImGui::SameLine();
    }

    if (valueFraction>0)   {
        ImGui::Image(fontAtlas->TexID,ImVec2(size.x*valueFraction,size.y), fontAtlas->TexUvWhitePixel,fontAtlas->TexUvWhitePixel,colorLeft,colorBorder);
    }
    if (valueFraction<1)   {
        if (valueFraction>0) ImGui::SameLine(0,0);
        ImGui::Image(fontAtlas->TexID,ImVec2(size.x*(1.f-valueFraction),size.y), fontAtlas->TexUvWhitePixel,fontAtlas->TexUvWhitePixel,colorRight,colorBorder);
    }
    ImGui::SameLine();

    ImGui::Text(format,needsPercConversion ? (valueFraction*100.f+0.0001f) : value);
    return valueFraction;
}

void TestProgressBar()  {
    static float progress=0; static float progressSign = 1.f;
    progress+=progressSign*.0001f;if (progress>=1.f || progress<=0.f) progressSign*=-1.f;
    // No IDs needed for ProgressBars:
    ImGui::ProgressBar("ProgressBar",progress);
    ImGui::ProgressBar("ProgressBar",1.f-progress);
    ImGui::ProgressBar("",500+progress*1000,500,1500,"%4.0f (absolute value in [500,1500] and fixed bar size)",ImVec2(150,-1));
    ImGui::ProgressBar("",500+progress*1000,500,1500,"%3.0f%% (same as above, but with percentage and new colors)",ImVec2(150,-1),ImVec4(0.7,0.7,1,1),ImVec4(0.05,0.15,0.5,0.8),ImVec4(0.8,0.8,0,1));
}

}

capture

what about using horizontal scrollbar for this?
can the scrollbar be fixed to initial position (0) and just tweak size from [0,100%]?
edit: same for vertical progress bar :)

It's 5 lines of code to do a custom progress widget why would you use a scrollbar.

Started working on an official ProgressBar() thing, not done yet.

progress_bar

Very cool 馃憤

Added.
IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL);

progress_bar2

Very nice :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KaungZawHtet picture KaungZawHtet  路  3Comments

mkanakis picture mkanakis  路  3Comments

Folling picture Folling  路  3Comments

ocornut picture ocornut  路  3Comments

GrammarLord picture GrammarLord  路  3Comments