diff --git a/source/blender/makesrna/intern/rna_wm_api.cc b/source/blender/makesrna/intern/rna_wm_api.cc index ba12ded4350..3cc23e57478 100644 --- a/source/blender/makesrna/intern/rna_wm_api.cc +++ b/source/blender/makesrna/intern/rna_wm_api.cc @@ -201,12 +201,12 @@ static void rna_progress_begin(wmWindowManager * /*wm*/, float min, float max) static void rna_progress_update(wmWindowManager *wm, float value) { if (wm_progress_state.is_valid) { - /* Map to cursor_time range [0,9999] */ + /* Map to factor 0..1. */ wmWindow *win = wm->winactive; if (win) { - int val = int(10000 * (value - wm_progress_state.min) / - (wm_progress_state.max - wm_progress_state.min)); - WM_cursor_time(win, val); + const float progress_factor = (value - wm_progress_state.min) / + (wm_progress_state.max - wm_progress_state.min); + WM_cursor_progress(win, progress_factor); } } } diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index 5a35a5d1148..fb28874e634 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -527,6 +527,11 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2]); */ void WM_cursor_time(wmWindow *win, int nr); +/** + * Show progress in the cursor (0.0..1.0 when complete). + */ +void WM_cursor_progress(wmWindow *win, float progress_factor); + wmPaintCursor *WM_paint_cursor_activate(short space_type, short region_type, bool (*poll)(bContext *C), diff --git a/source/blender/windowmanager/intern/wm_cursors.cc b/source/blender/windowmanager/intern/wm_cursors.cc index c3414f1b2e1..68292e95034 100644 --- a/source/blender/windowmanager/intern/wm_cursors.cc +++ b/source/blender/windowmanager/intern/wm_cursors.cc @@ -52,6 +52,12 @@ */ constexpr int CURSOR_HARDWARE_SIZE_MAX = 255; +/** + * The maximum size of cursor text (in bytes). + * Can remain small as it's unlikely we can ever show much text in a cursor. + */ +#define CURSOR_TEXT_BUFFER_SIZE 24 + /** Blender custom cursor. */ struct BCursor { /** @@ -729,7 +735,7 @@ static void wm_cursor_time_small(wmWindow *win, uint32_t nr) * \return the pixel data as a `sizeof(uint8_t[4]) * r_bitmap_size[0] * r_bitmap_size[1]` array * or null on failure. */ -static uint8_t *cursor_bitmap_from_text(const std::string &text, +static uint8_t *cursor_bitmap_from_text(const char *text, const int cursor_size, const int cursor_size_max, int font_id, @@ -746,8 +752,9 @@ static uint8_t *cursor_bitmap_from_text(const std::string &text, int font_descender; /* At least 1 even on an empty string else the cursor is blank. */ - const int text_units = std::max(1, BLI_str_utf8_column_count(text.c_str(), text.size())); - const bool text_to_draw = text.size() > 0; + const size_t text_len = strlen(text); + const int text_units = std::max(1, BLI_str_utf8_column_count(text, text_len)); + const bool text_to_draw = text_len != 0; for (int pass = 0; pass < 2; pass++) { BLF_size(font_id, font_size); @@ -791,7 +798,7 @@ static uint8_t *cursor_bitmap_from_text(const std::string &text, BLF_buffer_col(font_id, color); BLF_buffer(font_id, nullptr, bitmap_rgba, dest_size[0], dest_size[1], nullptr); BLF_position(font_id, font_padding, font_padding + font_descender, 0.0f); - BLF_draw_buffer(font_id, text.c_str(), text.size()); + BLF_draw_buffer(font_id, text, text_len); BLF_buffer(font_id, nullptr, nullptr, 0, 0, nullptr); cursor_bitmap_rgba_flip_y(bitmap_rgba, dest_size); @@ -803,10 +810,10 @@ static uint8_t *cursor_bitmap_from_text(const std::string &text, return bitmap_rgba; } -static bool wm_cursor_text_generator(wmWindow *win, const std::string &text, int font_id) +static bool wm_cursor_text_generator(wmWindow *win, const char *text, int font_id) { struct WMCursorText { - std::string text; + char text[CURSOR_TEXT_BUFFER_SIZE]; int font_id; }; @@ -845,7 +852,7 @@ static bool wm_cursor_text_generator(wmWindow *win, const std::string &text, int }; WMCursorText *cursor_text = MEM_new(__func__); - cursor_text->text = text; + STRNCPY_UTF8(cursor_text->text, text); cursor_text->font_id = font_id; cursor_generator->user_data = (void *)cursor_text; @@ -861,7 +868,7 @@ static bool wm_cursor_text_generator(wmWindow *win, const std::string &text, int return (success == GHOST_kSuccess) ? true : false; } -static bool wm_cursor_text_pixmap(wmWindow *win, const std::string &text, int font_id) +static bool wm_cursor_text_pixmap(wmWindow *win, const char *text, int font_id) { const int cursor_size = wm_cursor_size(win); /* This is arbitrary. Use a larger value than the cursor size since the text is often wider than @@ -899,7 +906,7 @@ static bool wm_cursor_text_pixmap(wmWindow *win, const std::string &text, int fo return (success == GHOST_kSuccess) ? true : false; } -static bool wm_cursor_text(wmWindow *win, const std::string &text, int font_id) +static bool wm_cursor_text(wmWindow *win, const char *text, int font_id) { if (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_GENERATOR) { return wm_cursor_text_generator(win, text, font_id); @@ -907,7 +914,11 @@ static bool wm_cursor_text(wmWindow *win, const std::string &text, int font_id) return wm_cursor_text_pixmap(win, text, font_id); } -void WM_cursor_time(wmWindow *win, int nr) +/** + * \param is_percentage: When true, nr represents a percentage multiplied by 100 + * so the percentage with two decimal places can be shown. + */ +static void wm_cursor_number_impl(wmWindow *win, int nr, bool is_percentage) { if (win->lastcursor == 0) { win->lastcursor = win->cursor; @@ -919,7 +930,15 @@ void WM_cursor_time(wmWindow *win, int nr) const uint32_t nr_abs = nr >= 0 ? uint32_t(nr) : -uint32_t(nr); if (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_RGBA) { - wm_cursor_text(win, std::to_string(nr_abs), blf_mono_font); + char text[CURSOR_TEXT_BUFFER_SIZE]; + if (is_percentage) { + /* Left pad to avoid resizing text between 9% & 10%. */ + SNPRINTF_UTF8(text, "%2u.%02u", nr_abs / 100, nr_abs % 100); + } + else { + SNPRINTF_UTF8(text, "%u", nr_abs); + } + wm_cursor_text(win, text, blf_mono_font); } else if (wm_cursor_size(win) < 24 || !wm_cursor_time_large(win, nr_abs)) { wm_cursor_time_small(win, nr_abs); @@ -929,6 +948,18 @@ void WM_cursor_time(wmWindow *win, int nr) win->cursor = 0; } +void WM_cursor_time(wmWindow *win, int nr) +{ + wm_cursor_number_impl(win, nr, false); +} + +void WM_cursor_progress(wmWindow *win, float progress_factor) +{ + constexpr int nr_max = 10000; + const int nr = std::clamp(int(std::round(double(progress_factor) * nr_max)), 0, nr_max); + wm_cursor_number_impl(win, nr, true); +} + #ifndef WITH_HEADLESS static void wm_add_cursor(WMCursorType cursor, const char *svg_source,