UI: redesign of the progress bar.
A picture is worth a thousand words: http://wiki.blender.org/index.php/ File:UI_progress_bar.png Reviewers: #user_interface, brecht, dingto Reviewed by: brecht, dingto Differential Revision: https://developer.blender.org/D1727
This commit is contained in:
parent
c4c2bd1350
commit
c6bc2363e5
Notes:
blender-bot
2023-02-14 10:04:50 +01:00
Referenced by issue #47204, Region selection tools (box, circle, lasso) select extra vertices
|
@ -42,7 +42,7 @@ extern "C" {
|
|||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 276
|
||||
#define BLENDER_SUBVERSION 7
|
||||
#define BLENDER_SUBVERSION 8
|
||||
/* Several breakages with 270, e.g. constraint deg vs rad */
|
||||
#define BLENDER_MINVERSION 270
|
||||
#define BLENDER_MINSUBVERSION 6
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_fnmatch.h"
|
||||
#include "BLI_timecode.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
#include "BLT_translation.h"
|
||||
|
@ -81,6 +82,8 @@
|
|||
#include "UI_interface_icons.h"
|
||||
#include "interface_intern.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
void UI_template_fix_linking(void)
|
||||
{
|
||||
}
|
||||
|
@ -3383,7 +3386,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
|||
ScrArea *sa = CTX_wm_area(C);
|
||||
uiBlock *block;
|
||||
void *owner = NULL;
|
||||
int handle_event;
|
||||
int handle_event, icon = 0;
|
||||
|
||||
block = uiLayoutGetBlock(layout);
|
||||
UI_block_layout_set_current(block, layout);
|
||||
|
@ -3394,17 +3397,20 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
|||
if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY))
|
||||
owner = sa;
|
||||
handle_event = B_STOPSEQ;
|
||||
icon = ICON_SEQUENCE;
|
||||
}
|
||||
else if (sa->spacetype == SPACE_CLIP) {
|
||||
if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY))
|
||||
owner = sa;
|
||||
handle_event = B_STOPCLIP;
|
||||
icon = ICON_CLIP;
|
||||
}
|
||||
else if (sa->spacetype == SPACE_FILE) {
|
||||
if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) {
|
||||
owner = sa;
|
||||
}
|
||||
handle_event = B_STOPFILE;
|
||||
icon = ICON_FILESEL;
|
||||
}
|
||||
else {
|
||||
Scene *scene;
|
||||
|
@ -3412,10 +3418,12 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
|||
for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) {
|
||||
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
|
||||
handle_event = B_STOPRENDER;
|
||||
icon = ICON_SCENE;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_COMPOSITE)) {
|
||||
handle_event = B_STOPCOMPO;
|
||||
icon = ICON_RENDERLAYERS;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE) ||
|
||||
|
@ -3427,11 +3435,33 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
|||
*/
|
||||
if (sa->spacetype != SPACE_NODE) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_IMAGE_COL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_DPAINT_BAKE)) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_MOD_DYNAMICPAINT;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_POINTCACHE)) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_PHYSICS;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_FLUID)) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_MOD_FLUIDSIM;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_SIM_OCEAN)) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_MOD_OCEAN;
|
||||
break;
|
||||
}
|
||||
else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
|
||||
handle_event = B_STOPOTHER;
|
||||
icon = ICON_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3439,18 +3469,52 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
|||
}
|
||||
|
||||
if (owner) {
|
||||
uiLayout *ui_abs;
|
||||
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
|
||||
bool active = !(WM_jobs_is_stopped(wm, owner) || G.is_break);
|
||||
|
||||
ui_abs = uiLayoutAbsolute(layout, false);
|
||||
(void)ui_abs; /* UNUSED */
|
||||
uiLayout *row = uiLayoutRow(layout, false);
|
||||
block = uiLayoutGetBlock(row);
|
||||
|
||||
/* get percentage done and set it as the UI text */
|
||||
const float progress = WM_jobs_progress(wm, owner);
|
||||
char text[8];
|
||||
BLI_snprintf(text, 8, "%d%%", (int)(progress * 100));
|
||||
|
||||
uiDefIconBut(block, UI_BTYPE_BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8,
|
||||
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
|
||||
uiDefBut(block, UI_BTYPE_PROGRESS_BAR, 0, WM_jobs_name(wm, owner),
|
||||
UI_UNIT_X, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress"));
|
||||
|
||||
uiLayoutRow(layout, false);
|
||||
/* create tooltip text and associate it with the job */
|
||||
|
||||
const double elapsed = PIL_check_seconds_timer() - WM_jobs_starttime(wm, owner);
|
||||
const double remaining = (elapsed / progress) - elapsed;
|
||||
|
||||
char remaining_str[32], elapsed_str[32];
|
||||
BLI_timecode_string_from_time_simple(remaining_str, sizeof(remaining_str), remaining);
|
||||
BLI_timecode_string_from_time_simple(elapsed_str, sizeof(remaining_str), elapsed);
|
||||
|
||||
char tooltip[128];
|
||||
BLI_snprintf(tooltip, sizeof(tooltip), "Time Remaining: %s\nTime Elapsed: %s", remaining_str, elapsed_str);
|
||||
|
||||
WM_jobs_set_tooltip(wm, owner, tooltip);
|
||||
|
||||
const char *name = active ? WM_jobs_name(wm, owner) : "Canceling...";
|
||||
|
||||
/* job name and icon */
|
||||
const int textwidth = UI_fontstyle_string_width(fstyle, name);
|
||||
uiDefIconTextBut(block, UI_BTYPE_LABEL, 0, icon, name, 0, 0,
|
||||
textwidth + UI_UNIT_X * 1.5f, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "");
|
||||
|
||||
/* stick progress bar and cancel button together */
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetActive(row, active);
|
||||
block = uiLayoutGetBlock(row);
|
||||
|
||||
uiDefIconTextBut(block, UI_BTYPE_PROGRESS_BAR, 0, 0, text,
|
||||
UI_UNIT_X, 0, UI_UNIT_X * 6.0f, UI_UNIT_Y, NULL, 0.0f, 0.0f,
|
||||
progress, 0, WM_jobs_tooltip(wm, owner));
|
||||
|
||||
uiDefIconTextBut(block, UI_BTYPE_BUT, handle_event, ICON_PANEL_CLOSE,
|
||||
"", 0, 0, UI_UNIT_X, UI_UNIT_Y,
|
||||
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
|
||||
}
|
||||
|
||||
if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
|
||||
uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, UI_UNIT_X * 4.25f, UI_UNIT_Y,
|
||||
NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast"));
|
||||
|
|
|
@ -1854,7 +1854,7 @@ static struct uiWidgetColors wcol_progress = {
|
|||
{0, 0, 0, 255},
|
||||
{190, 190, 190, 255},
|
||||
{100, 100, 100, 180},
|
||||
{68, 68, 68, 255},
|
||||
{128, 128, 128, 255},
|
||||
|
||||
{0, 0, 0, 255},
|
||||
{255, 255, 255, 255},
|
||||
|
@ -2863,30 +2863,37 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
|
|||
UI_draw_widget_scroll(wcol, rect, &rect1, state);
|
||||
}
|
||||
|
||||
static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
|
||||
{
|
||||
uiWidgetBase wtb, wtb_bar;
|
||||
rcti rect_prog = *rect, rect_bar = *rect;
|
||||
|
||||
widget_init(&wtb);
|
||||
widget_init(&wtb_bar);
|
||||
|
||||
/* round corners */
|
||||
float value = but->a1;
|
||||
float w, min;
|
||||
|
||||
/* make the progress bar a proportion of the original height */
|
||||
/* hardcoded 4px high for now */
|
||||
rect_prog.ymax = rect_prog.ymin + 4 * UI_DPI_FAC;
|
||||
rect_bar.ymax = rect_bar.ymin + 4 * UI_DPI_FAC;
|
||||
|
||||
w = value * BLI_rcti_size_x(&rect_prog);
|
||||
|
||||
float offs = 0.25f * BLI_rcti_size_y(&rect_prog);
|
||||
float w = value * BLI_rcti_size_x(&rect_prog);
|
||||
|
||||
/* ensure minimium size */
|
||||
min = BLI_rcti_size_y(&rect_prog);
|
||||
w = MAX2(w, min);
|
||||
|
||||
w = MAX2(w, offs);
|
||||
|
||||
rect_bar.xmax = rect_bar.xmin + w;
|
||||
|
||||
UI_draw_widget_scroll(wcol, &rect_prog, &rect_bar, UI_SCROLL_NO_OUTLINE);
|
||||
|
||||
|
||||
round_box_edges(&wtb, roundboxalign, &rect_prog, offs);
|
||||
round_box_edges(&wtb_bar, roundboxalign, &rect_bar, offs);
|
||||
|
||||
wtb.draw_outline = true;
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
|
||||
/* "slider" bar color */
|
||||
copy_v3_v3_char(wcol->inner, wcol->item);
|
||||
widgetbase_draw(&wtb_bar, wcol);
|
||||
|
||||
/* raise text a bit */
|
||||
rect->ymin += 6 * UI_DPI_FAC;
|
||||
rect->xmin -= 6 * UI_DPI_FAC;
|
||||
rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2);
|
||||
rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
|
||||
}
|
||||
|
||||
static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
|
|
|
@ -2024,7 +2024,7 @@ void init_userdef_do_versions(void)
|
|||
{0, 0, 0, 255},
|
||||
{190, 190, 190, 255},
|
||||
{100, 100, 100, 180},
|
||||
{68, 68, 68, 255},
|
||||
{128, 128, 128, 255},
|
||||
|
||||
{0, 0, 0, 255},
|
||||
{255, 255, 255, 255},
|
||||
|
@ -2678,6 +2678,13 @@ void init_userdef_do_versions(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(276, 8)) {
|
||||
bTheme *btheme;
|
||||
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
|
||||
rgba_char_args_set(btheme->tui.wcol_progress.item, 128, 128, 128, 255);
|
||||
}
|
||||
}
|
||||
|
||||
if (U.pixelsize == 0.0f)
|
||||
U.pixelsize = 1.0f;
|
||||
|
||||
|
|
|
@ -453,10 +453,14 @@ struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void
|
|||
bool WM_jobs_test(struct wmWindowManager *wm, void *owner, int job_type);
|
||||
float WM_jobs_progress(struct wmWindowManager *wm, void *owner);
|
||||
char *WM_jobs_name(struct wmWindowManager *wm, void *owner);
|
||||
double WM_jobs_starttime(struct wmWindowManager *wm, void *owner);
|
||||
char *WM_jobs_tooltip(struct wmWindowManager *wm, void *owner);
|
||||
void WM_jobs_set_tooltip(struct wmWindowManager *wm, void *owner, char *text);
|
||||
void *WM_jobs_customdata(struct wmWindowManager *wm, void *owner);
|
||||
void *WM_jobs_customdata_from_type(struct wmWindowManager *wm, int job_type);
|
||||
|
||||
bool WM_jobs_is_running(struct wmJob *);
|
||||
bool WM_jobs_is_stopped(wmWindowManager *wm, void *owner);
|
||||
void *WM_jobs_customdata_get(struct wmJob *);
|
||||
void WM_jobs_customdata_set(struct wmJob *, void *customdata, void (*free)(void *));
|
||||
void WM_jobs_timer(struct wmJob *, double timestep, unsigned int note, unsigned int endnote);
|
||||
|
|
|
@ -103,7 +103,7 @@ struct wmJob {
|
|||
unsigned int note, endnote;
|
||||
|
||||
|
||||
/* internal */
|
||||
/* internal */
|
||||
void *owner;
|
||||
int flag;
|
||||
short suspended, running, ready, do_update, stop, job_type;
|
||||
|
@ -112,6 +112,9 @@ struct wmJob {
|
|||
/* for display in header, identification */
|
||||
char name[128];
|
||||
|
||||
/* for other text display in progress bar */
|
||||
char text[128];
|
||||
|
||||
/* once running, we store this separately */
|
||||
void *run_customdata;
|
||||
void (*run_free)(void *);
|
||||
|
@ -245,6 +248,38 @@ float WM_jobs_progress(wmWindowManager *wm, void *owner)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
/* time that job started */
|
||||
double WM_jobs_starttime(wmWindowManager *wm, void *owner)
|
||||
{
|
||||
wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
|
||||
|
||||
if (wm_job && wm_job->flag & WM_JOB_PROGRESS)
|
||||
return wm_job->start_time;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get progress bar tooltip text */
|
||||
char *WM_jobs_tooltip(wmWindowManager *wm, void *owner)
|
||||
{
|
||||
wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
|
||||
|
||||
if (wm_job && wm_job->flag & WM_JOB_PROGRESS)
|
||||
return wm_job->text;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set progress bar text (e.g. tooltip, UI label, eta...) */
|
||||
void WM_jobs_set_tooltip(wmWindowManager *wm, void *owner, char *text)
|
||||
{
|
||||
wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
|
||||
|
||||
if (wm_job && wm_job->flag & WM_JOB_PROGRESS) {
|
||||
BLI_strncpy(wm_job->text, text, sizeof(wm_job->text));
|
||||
}
|
||||
}
|
||||
|
||||
char *WM_jobs_name(wmWindowManager *wm, void *owner)
|
||||
{
|
||||
wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
|
||||
|
@ -280,6 +315,12 @@ bool WM_jobs_is_running(wmJob *wm_job)
|
|||
return wm_job->running;
|
||||
}
|
||||
|
||||
bool WM_jobs_is_stopped(wmWindowManager *wm, void *owner)
|
||||
{
|
||||
wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
|
||||
return wm_job->stop;
|
||||
}
|
||||
|
||||
void *WM_jobs_customdata_get(wmJob *wm_job)
|
||||
{
|
||||
if (!wm_job->customdata) {
|
||||
|
@ -420,8 +461,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
|
|||
if (wm_job->wt == NULL)
|
||||
wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, wm_job->timestep);
|
||||
|
||||
if (G.debug & G_DEBUG_JOBS)
|
||||
wm_job->start_time = PIL_check_seconds_timer();
|
||||
wm_job->start_time = PIL_check_seconds_timer();
|
||||
}
|
||||
else {
|
||||
printf("job fails, not initialized\n");
|
||||
|
|
Loading…
Reference in New Issue