Add number and memory size formatting throughout the UI
authorDiego Gangl <dnicolas@gmail.com>
Fri, 25 May 2018 20:17:15 +0000 (22:17 +0200)
committerJulian Eisel <eiseljulian@gmail.com>
Fri, 25 May 2018 20:41:49 +0000 (22:41 +0200)
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

release/scripts/startup/bl_ui/properties_data_modifier.py
source/blender/blenkernel/intern/pointcache.c
source/blender/blenlib/BLI_string.h
source/blender/blenlib/intern/string.c
source/blender/editors/space_info/info_stats.c
tests/gtests/blenlib/BLI_string_test.cc

index e3cc08c..5bcf188 100644 (file)
@@ -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)
index 89885bd..3d1cdba 100644 (file)
@@ -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,9 +4048,11 @@ 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++)
                                bytes += MEM_allocN_len(pm->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) {
index 48be9d1..faa8dc0 100644 (file)
@@ -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();
index 1a6fd08..da9f5a8 100644 (file)
@@ -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.
  *
index 8dc6c42..10b5ede 100644 (file)
@@ -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);
                }
        }
 
index f6f7e17..f3a12ce 100644 (file)
@@ -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] = \