Add number and memory size formatting throughout the UI

This commit adds number formatting (thousands separator) to the baking panel. It also adds a new function to format memory sizes (KB/GB/etc) and applies it to the baking panel and scene stats. The new function is unit tested.

Reviewers: Severin
Tags: #user_interface
Differential Revision: https://developer.blender.org/D1248
This commit is contained in:
Diego Gangl 2018-05-25 22:17:15 +02:00 committed by Julian Eisel
parent 9dca74f0e5
commit 4dee702332
6 changed files with 125 additions and 15 deletions

@ -328,7 +328,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "delimit")
layout_info = layout
layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False)
layout_info.label(text=iface_("Face Count: {:,}".format(md.face_count)),
translate=False)
def DISPLACE(self, layout, ob, md):
has_texture = (md.texture is not None)

@ -49,6 +49,7 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -4047,8 +4048,10 @@ void BKE_ptcache_update_info(PTCacheID *pid)
}
else {
PTCacheMem *pm = cache->mem_cache.first;
float bytes = 0.0f;
int i, mb;
char formatted_tot[16];
char formatted_mem[15];
long long int bytes = 0.0f;
int i;
for (; pm; pm=pm->next) {
for (i=0; i<BPHYS_TOT_DATA; i++)
@ -4064,12 +4067,10 @@ void BKE_ptcache_update_info(PTCacheID *pid)
totframes++;
}
mb = (bytes > 1024.0f * 1024.0f);
BLI_str_format_int_grouped(formatted_tot, totframes);
BLI_str_format_byte_unit(formatted_mem, bytes, true);
BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"),
totframes,
bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
mb ? IFACE_("Mb") : IFACE_("kb"));
BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%s frames in memory (%s)"), formatted_tot, formatted_mem);
}
if (cache->flag & PTCACHE_OUTDATED) {

@ -71,6 +71,7 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT A
size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL();
void BLI_str_format_byte_unit(char dst[15], long long int size, const bool base_10) ATTR_NONNULL();
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

@ -994,6 +994,41 @@ size_t BLI_str_format_int_grouped(char dst[16], int num)
return (size_t)(p_dst - dst);
}
/**
* Format a size in bytes using binary units.
* 1000 -> 1 KB
* Number of decimal places grows with the used unit (e.g. 1.5 MB, 1.55 GB, 1.545 TB).
*
* \param dst The resulting string. Dimension of 14 to support largest possible value for \a bytes (LLONG_MAX).
* \param bytes Number to format
* \param base_10 Calculate using base 10 (GB, MB, ...) or 2 (GiB, MiB, ...)
*/
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10)
{
double bytes_converted = bytes;
int order = 0;
int decimals;
const int base = base_10 ? 1000 : 1024;
const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"};
const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
const int tot_units = ARRAY_SIZE(units_base_2);
BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch");
while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) {
bytes_converted /= base;
order++;
}
decimals = MAX2(order - 1, 0);
/* Format value first, stripping away floating zeroes. */
sprintf(dst, "%.*f", decimals, bytes_converted);
BLI_str_rstrip_float_zero(dst, '\0');
/* Append unit. */
sprintf(dst, "%s %s", dst, base_10 ? units_base_10[order] : units_base_2[order]);
}
/**
* Find the ranges needed to split \a str into its individual words.
*

@ -384,6 +384,7 @@ static void stats_string(Scene *scene)
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
char gpumemstr[MAX_INFO_MEM_LEN] = "";
char formatted_mem[15];
char *s;
size_t ofs = 0;
@ -419,20 +420,25 @@ static void stats_string(Scene *scene)
/* get memory statistics */
ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
(double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
if (mmap_in_use)
BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true);
ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem);
if (mmap_in_use) {
BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true);
BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%s)"), formatted_mem);
}
if (GPU_mem_stats_supported()) {
int gpu_free_mem, gpu_tot_memory;
GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, true);
ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem);
if (gpu_tot_memory) {
BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true);
BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem);
}
}

@ -364,6 +364,72 @@ TEST(string, StrFormatIntGrouped)
EXPECT_STREQ("-999", num_str);
}
/* BLI_str_format_byte_unit */
TEST(string, StrFormatByteUnits)
{
char size_str[15];
long long int size;
/* Base 10 */
BLI_str_format_byte_unit(size_str, size = 0, true);
EXPECT_STREQ("0 B", size_str);
BLI_str_format_byte_unit(size_str, size = -0, true);
EXPECT_STREQ("0 B", size_str);
BLI_str_format_byte_unit(size_str, size = 1, true);
EXPECT_STREQ("1 B", size_str);
BLI_str_format_byte_unit(size_str, size = -1, true);
EXPECT_STREQ("-1 B", size_str);
BLI_str_format_byte_unit(size_str, size = 1000, true);
EXPECT_STREQ("1 KB", size_str);
BLI_str_format_byte_unit(size_str, size = -1000, true);
EXPECT_STREQ("-1 KB", size_str);
BLI_str_format_byte_unit(size_str, size = 1024, true);
EXPECT_STREQ("1 KB", size_str);
BLI_str_format_byte_unit(size_str, size = -1024, true);
EXPECT_STREQ("-1 KB", size_str);
BLI_str_format_byte_unit(size_str, size = 9223372036854775807, true); /* LLONG_MAX - largest possible value */
EXPECT_STREQ("9223.372 PB", size_str);
BLI_str_format_byte_unit(size_str, size = -9223372036854775807, true);
EXPECT_STREQ("-9223.372 PB", size_str);
/* Base 2 */
BLI_str_format_byte_unit(size_str, size = 0, false);
EXPECT_STREQ("0 B", size_str);
BLI_str_format_byte_unit(size_str, size = -0, false);
EXPECT_STREQ("0 B", size_str);
BLI_str_format_byte_unit(size_str, size = 1, false);
EXPECT_STREQ("1 B", size_str);
BLI_str_format_byte_unit(size_str, size = -1, false);
EXPECT_STREQ("-1 B", size_str);
BLI_str_format_byte_unit(size_str, size = 1000, false);
EXPECT_STREQ("1000 B", size_str);
BLI_str_format_byte_unit(size_str, size = -1000, false);
EXPECT_STREQ("-1000 B", size_str);
BLI_str_format_byte_unit(size_str, size = 1024, false);
EXPECT_STREQ("1 KiB", size_str);
BLI_str_format_byte_unit(size_str, size = -1024, false);
EXPECT_STREQ("-1 KiB", size_str);
BLI_str_format_byte_unit(size_str, size = 9223372036854775807, false); /* LLONG_MAX - largest possible value */
EXPECT_STREQ("8192.0 PiB", size_str);
BLI_str_format_byte_unit(size_str, size = -9223372036854775807, false);
EXPECT_STREQ("-8192.0 PiB", size_str);
/* Test maximum string length. */
BLI_str_format_byte_unit(size_str, size = -9223200000000000000, false);
EXPECT_STREQ("-8191.8472 PiB", size_str);
}
#define STRING_FIND_SPLIT_WORDS_EX(word_str_src, word_str_src_len, limit_words, ...) \
{ \
int word_info[][2] = \