Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_templates.c
| Show All 39 Lines | |||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_string.h" | #include "BLI_string.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_rect.h" | #include "BLI_rect.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_fnmatch.h" | #include "BLI_fnmatch.h" | ||||
| #include "BLI_timecode.h" | |||||
| #include "BLF_api.h" | #include "BLF_api.h" | ||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_colortools.h" | #include "BKE_colortools.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_depsgraph.h" | #include "BKE_depsgraph.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| Show All 20 Lines | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_interface_icons.h" | #include "UI_interface_icons.h" | ||||
| #include "interface_intern.h" | #include "interface_intern.h" | ||||
| #include "PIL_time.h" | |||||
| void UI_template_fix_linking(void) | void UI_template_fix_linking(void) | ||||
| { | { | ||||
| } | } | ||||
| /********************** Header Template *************************/ | /********************** Header Template *************************/ | ||||
| void uiTemplateHeader(uiLayout *layout, bContext *C) | void uiTemplateHeader(uiLayout *layout, bContext *C) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 3,249 Lines • ▼ Show 20 Lines | |||||
| #define B_STOPCAST 2 | #define B_STOPCAST 2 | ||||
| #define B_STOPANIM 3 | #define B_STOPANIM 3 | ||||
| #define B_STOPCOMPO 4 | #define B_STOPCOMPO 4 | ||||
| #define B_STOPSEQ 5 | #define B_STOPSEQ 5 | ||||
| #define B_STOPCLIP 6 | #define B_STOPCLIP 6 | ||||
| #define B_STOPFILE 7 | #define B_STOPFILE 7 | ||||
| #define B_STOPOTHER 8 | #define B_STOPOTHER 8 | ||||
| static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) | static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) | ||||
| { | { | ||||
| switch (event) { | switch (event) { | ||||
| case B_STOPRENDER: | case B_STOPRENDER: | ||||
| G.is_break = true; | G.is_break = true; | ||||
| break; | break; | ||||
| case B_STOPCAST: | case B_STOPCAST: | ||||
| WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL); | WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL); | ||||
| break; | break; | ||||
| case B_STOPANIM: | case B_STOPANIM: | ||||
| WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL); | WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL); | ||||
| break; | break; | ||||
| case B_STOPCOMPO: | case B_STOPCOMPO: | ||||
| WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL); | WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL); | ||||
| break; | break; | ||||
| case B_STOPSEQ: | case B_STOPSEQ: | ||||
| WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | ||||
| break; | break; | ||||
| case B_STOPCLIP: | case B_STOPCLIP: | ||||
| WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | ||||
| break; | break; | ||||
| case B_STOPFILE: | case B_STOPFILE: | ||||
| WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); | ||||
| break; | break; | ||||
| case B_STOPOTHER: | case B_STOPOTHER: | ||||
| G.is_break = true; | G.is_break = true; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void uiTemplateRunningJobs(uiLayout *layout, bContext *C) | void uiTemplateRunningJobs(uiLayout *layout, bContext *C) | ||||
brecht: For render progress timing we already have `BLI_timecode_string_from_time_simple()`. This new… | |||||
| { | { | ||||
| bScreen *screen = CTX_wm_screen(C); | bScreen *screen = CTX_wm_screen(C); | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| ScrArea *sa = CTX_wm_area(C); | ScrArea *sa = CTX_wm_area(C); | ||||
| uiBlock *block; | uiBlock *block; | ||||
| void *owner = NULL; | void *owner = NULL; | ||||
| int handle_event; | int handle_event, icon = 0; | ||||
| block = uiLayoutGetBlock(layout); | block = uiLayoutGetBlock(layout); | ||||
| UI_block_layout_set_current(block, layout); | UI_block_layout_set_current(block, layout); | ||||
| UI_block_func_handle_set(block, do_running_jobs, NULL); | UI_block_func_handle_set(block, do_running_jobs, NULL); | ||||
| if (sa->spacetype == SPACE_SEQ) { | if (sa->spacetype == SPACE_SEQ) { | ||||
| if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) | if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) | ||||
| owner = sa; | owner = sa; | ||||
| handle_event = B_STOPSEQ; | handle_event = B_STOPSEQ; | ||||
| icon = ICON_SEQUENCE; | |||||
| } | } | ||||
| else if (sa->spacetype == SPACE_CLIP) { | else if (sa->spacetype == SPACE_CLIP) { | ||||
| if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) | if (WM_jobs_test(wm, sa, WM_JOB_TYPE_ANY)) | ||||
| owner = sa; | owner = sa; | ||||
| handle_event = B_STOPCLIP; | handle_event = B_STOPCLIP; | ||||
| icon = ICON_CLIP; | |||||
| } | } | ||||
| else if (sa->spacetype == SPACE_FILE) { | else if (sa->spacetype == SPACE_FILE) { | ||||
| if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) { | if (WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR)) { | ||||
| owner = sa; | owner = sa; | ||||
| } | } | ||||
| handle_event = B_STOPFILE; | handle_event = B_STOPFILE; | ||||
| icon = ICON_FILESEL; | |||||
| } | } | ||||
| else { | else { | ||||
| Scene *scene; | Scene *scene; | ||||
| /* another scene can be rendering too, for example via compositor */ | /* another scene can be rendering too, for example via compositor */ | ||||
| for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) { | for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) { | ||||
| if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) { | if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) { | ||||
| handle_event = B_STOPRENDER; | handle_event = B_STOPRENDER; | ||||
| icon = ICON_SCENE; | |||||
| break; | break; | ||||
| } | } | ||||
| else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_COMPOSITE)) { | else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_COMPOSITE)) { | ||||
| handle_event = B_STOPCOMPO; | handle_event = B_STOPCOMPO; | ||||
| icon = ICON_RENDERLAYERS; | |||||
| break; | break; | ||||
| } | } | ||||
| else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE) || | else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE) || | ||||
| WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE)) | WM_jobs_test(wm, scene, WM_JOB_TYPE_OBJECT_BAKE)) | ||||
| { | { | ||||
| /* Skip bake jobs in compositor to avoid compo header displaying | /* Skip bake jobs in compositor to avoid compo header displaying | ||||
| * progress bar which is not being updated (bake jobs only need | * progress bar which is not being updated (bake jobs only need | ||||
| * to update NC_IMAGE context. | * to update NC_IMAGE context. | ||||
| */ | */ | ||||
| if (sa->spacetype != SPACE_NODE) { | if (sa->spacetype != SPACE_NODE) { | ||||
| handle_event = B_STOPOTHER; | 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; | 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)) { | else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) { | ||||
| handle_event = B_STOPOTHER; | handle_event = B_STOPOTHER; | ||||
| icon = ICON_NONE; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| owner = scene; | owner = scene; | ||||
| } | } | ||||
| if (owner) { | 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); | uiLayout *row = uiLayoutRow(layout, false); | ||||
| (void)ui_abs; /* UNUSED */ | block = uiLayoutGetBlock(row); | ||||
| 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, | /* get percentage done and set it as the UI text */ | ||||
| NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); | const float progress = WM_jobs_progress(wm, owner); | ||||
| uiDefBut(block, UI_BTYPE_PROGRESS_BAR, 0, WM_jobs_name(wm, owner), | char text[8]; | ||||
| 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")); | BLI_snprintf(text, 8, "%d%%", (int)(progress * 100)); | ||||
| 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)) | 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, | 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")); | NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast")); | ||||
| if (screen->animtimer) | if (screen->animtimer) | ||||
| uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y, | uiDefIconTextBut(block, UI_BTYPE_BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, UI_UNIT_X * 5.0f, UI_UNIT_Y, | ||||
| NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); | NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 260 Lines • Show Last 20 Lines | |||||
For render progress timing we already have BLI_timecode_string_from_time_simple(). This new format is easier to understand, but I think we should try to be consistent.
If we want to make an easier to understand time format that can be done as a separate task for Blender as a whole. For backwards compatibility that might have to wait for 2.8 though, some scripts might be parsing the time format from logs.