Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dalai@blender.org>2022-10-20 17:37:07 +0300
committerDalai Felinto <dalai@blender.org>2022-10-20 17:46:54 +0300
commit84825e4ed2e098954f0c46adee4d65c8c0ba0e99 (patch)
tree9295baeea460f25602f89f678491bd0d6549494d
parent58e25f11ae9eb805dd857fae56be1d1a43710091 (diff)
UI: Icon number indicator for data-blocks
Adds the possibility of having a little number on top of icons. At the moment this is used for: * Outliner * Node Editor bread-crumb * Node Group node header For the outliner there is almost no functional change. It is mostly a refactor to handle the indicators as part of the icon shader instead of the outliner draw code. (note that this was already recently changed in a5d3b648e3e2). The difference is that now we use rounded border rectangle instead of circles, and we can go up to 999 elements. So for the outliner this shows the number of collapsed elements of a certain type (e.g., mesh objects inside a collapsed collection). For the node editors is being used to show the use count for the data-block. This is important for the node editor, so users know whether the node-group they are editing (or are about to edit) is used elsewhere. This is particularly important when the Node Options are hidden, which is the default for node groups appended from the asset libraries. --- Note: This can be easily enabled for ID templates which can then be part of T84669. It just need to call UI_but_icon_indicator_number_set in the function template_add_button_search_menu. --- Special thanks Clément Foucault for the help figuring out the shader, Julian Eisel for the help navigating the UI code, and Pablo Vazquez for the collaboration in this design solution. For images showing the result check the Differential Revision. Differential Revision: https://developer.blender.org/D16284
-rw-r--r--source/blender/blenlib/BLI_string.h22
-rw-r--r--source/blender/blenlib/intern/string.c30
-rw-r--r--source/blender/blenlib/tests/BLI_string_test.cc97
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/include/UI_interface.hh1
-rw-r--r--source/blender/editors/include/UI_interface_icons.h12
-rw-r--r--source/blender/editors/interface/interface.cc5
-rw-r--r--source/blender/editors/interface/interface_context_path.cc14
-rw-r--r--source/blender/editors/interface/interface_icons.c117
-rw-r--r--source/blender/editors/interface/interface_intern.h4
-rw-r--r--source/blender/editors/interface/interface_layout.c4
-rw-r--r--source/blender/editors/interface/interface_panel.cc6
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/screen/area.c3
-rw-r--r--source/blender/editors/space_file/file_draw.c65
-rw-r--r--source/blender/editors/space_info/textview.c3
-rw-r--r--source/blender/editors/space_node/node_draw.cc3
-rw-r--r--source/blender/editors/space_node/node_relationships.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc134
-rw-r--r--source/blender/gpu/CMakeLists.txt3
-rw-r--r--source/blender/gpu/GPU_shader.h4
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c5
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_frag.glsl42
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_vert.glsl37
-rw-r--r--source/blender/gpu/shaders/infos/gpu_interface_info.hh3
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh22
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.cc3
27 files changed, 499 insertions, 162 deletions
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 15926e8f2d2..17abcf52ecc 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -309,6 +309,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A
*/
void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL();
/**
+ * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long
+ * number names abbreviations. Used to produce a compact representation of large numbers as
+ * integers.
+ *
+ * It shows a lower bound instead of rounding the number.
+ *
+ * 1 -> 1
+ * 15 -> 15
+ * 155 -> 155
+ * 1555 -> 1K
+ * 15555 -> 15K
+ * 155555 -> .1M
+ * 1555555 -> 1M
+ * 15555555 -> 15M
+ * 155555555 -> .1B
+ * 1000000000 -> 1B
+ * ...
+ *
+ * Length of 5 is the maximum of the resulting string, for example, `-15K\0`.
+ */
+void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL();
+/**
* Compare two strings without regard to case.
*
* \retval True if the strings are equal, false otherwise.
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 89d31c5e93f..755d2dbd55d 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format)
BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]);
}
+void BLI_str_format_integer_unit(char dst[5], const int number_to_format)
+{
+ float number_to_format_converted = number_to_format;
+ int order = 0;
+ const float base = 1000;
+ const char *units[] = {"", "K", "M", "B"};
+ const int units_num = ARRAY_SIZE(units);
+
+ while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) {
+ number_to_format_converted /= base;
+ order++;
+ }
+
+ const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99;
+
+ if (add_dot) {
+ number_to_format_converted /= 100;
+ order++;
+ }
+
+ const size_t dst_len = 5;
+ BLI_snprintf(dst,
+ dst_len,
+ "%s%s%d%s",
+ number_to_format < 0 ? "-" : "",
+ add_dot ? "." : "",
+ (int)floorf(fabsf(number_to_format_converted)),
+ units[order]);
+}
+
/** \} */
diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc
index 9bdf6075c70..d726fbccf20 100644
--- a/source/blender/blenlib/tests/BLI_string_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_test.cc
@@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits)
EXPECT_STREQ("-2.1B", size_str);
}
+/* BLI_str_format_integer_unit */
+TEST(string, StrFormatIntegerUnits)
+{
+ char size_str[7];
+ int size;
+
+ BLI_str_format_integer_unit(size_str, size = 0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1);
+ EXPECT_STREQ("1", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10);
+ EXPECT_STREQ("10", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15);
+ EXPECT_STREQ("15", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100);
+ EXPECT_STREQ("100", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155);
+ EXPECT_STREQ("155", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000);
+ EXPECT_STREQ("10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555);
+ EXPECT_STREQ("15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555555);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 2555555);
+ EXPECT_STREQ("2M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000000);
+ EXPECT_STREQ("10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555555);
+ EXPECT_STREQ("15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000000);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555555);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 255555555);
+ EXPECT_STREQ(".2B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000000);
+ EXPECT_STREQ("1B", size_str);
+
+ /* Largest possible value. */
+ BLI_str_format_integer_unit(size_str, size = INT32_MAX);
+ EXPECT_STREQ("2B", size_str);
+
+ BLI_str_format_integer_unit(size_str, size = -0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1);
+ EXPECT_STREQ("-1", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10);
+ EXPECT_STREQ("-10", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15);
+ EXPECT_STREQ("-15", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100);
+ EXPECT_STREQ("-100", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155);
+ EXPECT_STREQ("-155", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000);
+ EXPECT_STREQ("-10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555);
+ EXPECT_STREQ("-15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555555);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000000);
+ EXPECT_STREQ("-10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555555);
+ EXPECT_STREQ("-15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000000);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555555);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000000);
+ EXPECT_STREQ("-1B", size_str);
+
+ /* Smallest possible value. */
+ BLI_str_format_integer_unit(size_str, size = -INT32_MAX);
+ EXPECT_STREQ("-2B", size_str);
+}
+
struct WordInfo {
WordInfo() = default;
WordInfo(int start, int end) : start(start), end(end)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 2a1941f0d9e..7e9422ff867 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1683,6 +1683,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name);
* Adds a hint to the button which draws right aligned, grayed out and never clipped.
*/
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number);
void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
@@ -2788,7 +2789,8 @@ typedef struct uiPropertySplitWrapper {
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout);
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
-void uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
+struct uiBut *uiItemL_ex(
+ uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
/**
* Helper to add a label and creates a property split layout if needed.
*/
diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh
index 6c756984203..fc03b0218c0 100644
--- a/source/blender/editors/include/UI_interface.hh
+++ b/source/blender/editors/include/UI_interface.hh
@@ -35,6 +35,7 @@ struct ContextPathItem {
std::string name;
/* #BIFIconID */
int icon;
+ int icon_indicator_number;
};
void context_path_add_generic(Vector<ContextPathItem> &path,
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index a1a98a4b08c..9669e242dac 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -27,6 +27,12 @@ typedef struct IconFile {
int index;
} IconFile;
+typedef struct IconTextOverlay {
+ char text[5];
+} IconTextOverlay;
+
+#define UI_NO_ICON_OVERLAY_TEXT NULL
+
#define ICON_DEFAULT_HEIGHT 16
#define ICON_DEFAULT_WIDTH 16
@@ -105,7 +111,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- bool mono_border);
+ bool mono_border,
+ const struct IconTextOverlay *text_overlay);
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
@@ -124,6 +131,9 @@ int UI_icon_from_library(const struct ID *id);
int UI_icon_from_object_mode(int mode);
int UI_icon_color_from_collection(const struct Collection *collection);
+void UI_icon_text_overlay_init_from_count(struct IconTextOverlay *text_overlay,
+ const int icon_indicator_number);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 422fc34aa50..1f88d25af2b 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -6452,6 +6452,11 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string)
ui_but_add_shortcut(but, string, false);
}
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number)
+{
+ UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number);
+}
+
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
{
but->flag |= UI_BUT_NODE_LINK;
diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc
index e8f552e26a3..91b2f9613de 100644
--- a/source/blender/editors/interface/interface_context_path.cc
+++ b/source/blender/editors/interface/interface_context_path.cc
@@ -17,6 +17,8 @@
#include "UI_interface.hh"
#include "UI_resources.h"
+#include "RNA_prototypes.h"
+
#include "WM_api.h"
namespace blender::ui {
@@ -41,7 +43,13 @@ void context_path_add_generic(Vector<ContextPathItem> &path,
static_cast<BIFIconID>(RNA_struct_ui_icon(rna_ptr.type)) :
icon_override;
- path.append({name, int(icon)});
+ if (&rna_type == &RNA_NodeTree) {
+ ID *id = (ID *)ptr;
+ path.append({name, int(icon), id->us});
+ }
+ else {
+ path.append({name, int(icon), 1});
+ }
}
/* -------------------------------------------------------------------- */
@@ -60,7 +68,9 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path)
if (i > 0) {
uiItemL(sub_row, "", ICON_RIGHTARROW_THIN);
}
- uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon);
+ uiBut *but = uiItemL_ex(
+ sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false);
+ UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number);
}
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index deb3d84ae66..9a4f98ebcd6 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -415,8 +415,15 @@ static void vicon_collection_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_OUTLINER_COLLECTION,
+ aspect,
+ 1.0f,
+ 0.0f,
+ collection_color->color,
+ true,
+ UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \
@@ -444,7 +451,8 @@ static void vicon_strip_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true);
+ UI_icon_draw_ex(
+ x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_STRIP_COLOR_DRAW(index, color) \
@@ -472,8 +480,15 @@ static void vicon_strip_color_draw_library_data_indirect(
{
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_LIBRARY_DATA_DIRECT,
+ aspect,
+ ICON_INDIRECT_DATA_ALPHA * alpha,
+ 0.0f,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
static void vicon_strip_color_draw_library_data_override_noneditable(
@@ -488,7 +503,8 @@ static void vicon_strip_color_draw_library_data_override_noneditable(
ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f,
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
@@ -1716,9 +1732,47 @@ static void icon_draw_texture(float x,
int ih,
float alpha,
const float rgb[3],
- bool with_border)
-{
- if (g_icon_draw_cache.enabled) {
+ bool with_border,
+ const IconTextOverlay *text_overlay)
+{
+ const float zoom_factor = w / UI_DPI_ICON_SIZE;
+ float text_width = 0.0f;
+
+ /* No need to show if too zoomed out, otherwise it just adds noise. */
+ const bool show_indicator = (text_overlay && text_overlay->text[0] != '\0') &&
+ (zoom_factor > 0.7f);
+
+ if (show_indicator) {
+ /* Handle the little numbers on top of the icon. */
+ uchar text_color[4];
+ UI_GetThemeColor3ubv(TH_TEXT, text_color);
+ text_color[3] = 255;
+
+ uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET;
+ fstyle_small.points *= zoom_factor;
+ fstyle_small.points *= 0.8f;
+
+ rcti text_rect = {
+ .xmax = x + UI_UNIT_X * zoom_factor,
+ .xmin = x,
+ .ymax = y,
+ .ymin = y,
+ };
+
+ UI_fontstyle_draw(&fstyle_small,
+ &text_rect,
+ text_overlay->text,
+ sizeof(text_overlay->text),
+ text_color,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ text_width = (float)UI_fontstyle_string_width(&fstyle_small, text_overlay->text) / UI_UNIT_X /
+ zoom_factor;
+ }
+
+ /* Draw the actual icon. */
+ if (!show_indicator && g_icon_draw_cache.enabled) {
icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1735,7 +1789,7 @@ static void icon_draw_texture(float x,
GPUTexture *texture = with_border ? icongltex.tex[1] : icongltex.tex[0];
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON);
GPU_shader_bind(shader);
const int img_binding = GPU_shader_get_texture_binding(shader, "image");
@@ -1752,6 +1806,7 @@ static void icon_draw_texture(float x,
GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2});
GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h});
+ GPU_shader_uniform_1f(shader, "text_width", text_width);
GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false);
@@ -1786,7 +1841,8 @@ static void icon_draw_size(float x,
int draw_size,
const float desaturate,
const uchar mono_rgba[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
bTheme *btheme = UI_GetTheme();
const float fdraw_size = (float)draw_size;
@@ -1874,7 +1930,8 @@ static void icon_draw_size(float x,
di->data.texture.h,
alpha,
NULL,
- false);
+ false,
+ text_overlay);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
/* Monochrome icon that uses text or theme color. */
@@ -1908,7 +1965,8 @@ static void icon_draw_size(float x,
di->data.texture.h + 2 * border_texel,
color[3],
color,
- with_border);
+ with_border,
+ text_overlay);
}
else if (di->type == ICON_TYPE_BUFFER) {
@@ -2425,17 +2483,27 @@ int UI_icon_color_from_collection(const Collection *collection)
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
+ icon_draw_size(x,
+ y,
+ icon_id,
+ aspect,
+ alpha,
+ ICON_SIZE_PREVIEW,
+ size,
+ false,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_ex(float x,
@@ -2445,7 +2513,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
const int draw_size = get_draw_size(ICON_SIZE_ICON);
icon_draw_size(x,
@@ -2457,7 +2526,19 @@ void UI_icon_draw_ex(float x,
draw_size,
desaturate,
mono_color,
- mono_border);
+ mono_border,
+ text_overlay);
+}
+
+void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay,
+ const int icon_indicator_number)
+{
+ /* The icon indicator is used as an aggregator, no need to show if it is 1. */
+ if (icon_indicator_number < 2) {
+ text_overlay->text[0] = '\0';
+ return;
+ }
+ BLI_str_format_integer_unit(text_overlay->text, icon_indicator_number);
}
/* ********** Alert Icons ********** */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6ef7d346418..6ef81ad897e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -23,6 +23,7 @@ struct ARegion;
struct AnimationEvalContext;
struct CurveMapping;
struct CurveProfile;
+struct IconTextOverlay;
struct ID;
struct ImBuf;
struct Main;
@@ -275,6 +276,9 @@ struct uiBut {
uiButPushedStateFunc pushed_state_func;
const void *pushed_state_arg;
+ /** Little indicator (e.g., counter) displayed on top of some icons. */
+ struct IconTextOverlay icon_overlay_text;
+
/* pointer back */
uiBlock *block;
};
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index c906a5b36f1..496f72c089a 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -3235,7 +3235,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
return but;
}
-void uiItemL_ex(
+uiBut *uiItemL_ex(
uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
{
uiBut *but = uiItemL_(layout, name, icon);
@@ -3248,6 +3248,8 @@ void uiItemL_ex(
if (redalert) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
+
+ return but;
}
void uiItemL(uiLayout *layout, const char *name, int icon)
diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc
index 7a69e2f9b2f..24d8281aad8 100644
--- a/source/blender/editors/interface/interface_panel.cc
+++ b/source/blender/editors/interface/interface_panel.cc
@@ -1112,7 +1112,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
0.7f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
@@ -1140,7 +1141,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
1.0f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6ba80e2e0d9..1bad9b34a72 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1420,21 +1420,25 @@ static void widget_draw_icon(
/* to indicate draggable */
if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) {
if (has_theme) {
alpha *= 0.8f;
}
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else {
const bTheme *btheme = UI_GetTheme();
const float desaturate = 1.0 - btheme->tui.icon_saturation;
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, desaturate, color, has_theme, &but->icon_overlay_text);
}
}
@@ -5426,7 +5430,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
GPU_blend(GPU_BLEND_ALPHA);
/* XXX scale weak get from fstyle? */
- UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
+ UI_icon_draw_ex(
+ xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false, UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 39e3c7a2f0a..8db968cbb8a 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -187,7 +187,8 @@ static void area_draw_azone_fullscreen(
min_ff(alpha, 0.75f),
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/**
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index e4085bbe9cc..240901318b5 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -410,8 +410,15 @@ static void file_draw_preview(const SpaceFile *sfile,
}
icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f));
- UI_icon_draw_ex(
- icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ icon,
+ icon_aspect / U.dpi_fac,
+ icon_opacity,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
if (is_link || is_offline) {
@@ -424,8 +431,24 @@ static void file_draw_preview(const SpaceFile *sfile,
/* At very bottom-left if preview style. */
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
else {
/* Link to folder or non-previewed file. */
@@ -433,8 +456,15 @@ static void file_draw_preview(const SpaceFile *sfile,
UI_GetThemeColor4ubv(TH_BACK, icon_color);
icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
- UI_icon_draw_ex(
- icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ icon_aspect / U.dpi_fac * 1.8,
+ 0.3f,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
}
else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) {
@@ -444,8 +474,17 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + (2.0f * UI_DPI_FAC);
icon_y = yco + (2.0f * UI_DPI_FAC);
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ icon,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT);
}
const bool is_current_main_data = filelist_file_get_id(file) != NULL;
@@ -456,7 +495,15 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + ex - UI_UNIT_X;
icon_y = yco + ey - UI_UNIT_Y;
- UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ ICON_CURRENT_FILE,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Contrasting outline around some preview types. */
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index aee72860a0a..12ee6f45991 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -235,7 +235,8 @@ static bool textview_draw_string(TextViewDrawState *tds,
1.0f,
0.0f,
icon_fg,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index ee9ebd541a0..98b2cacd162 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C,
0,
"");
UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit");
+ if (node.id) {
+ UI_but_icon_indicator_number_set(but, node.id->us);
+ }
UI_block_emboss_set(&block, UI_EMBOSS);
}
if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) {
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index b12afcb1faa..637c795d4d7 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/,
nldrag->cursor[0];
const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC;
- UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
static void draw_draglink_tooltip_activate(const ARegion &region, bNodeLinkDrag &nldrag)
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index e366c58349f..f76c0980c4f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -2877,7 +2877,8 @@ static bool tselem_draw_icon(uiBlock *block,
TreeStoreElem *tselem,
TreeElement *te,
float alpha,
- const bool is_clickable)
+ const bool is_clickable,
+ const int num_elements)
{
TreeElementIcon data = tree_element_get_icon(tselem, te);
if (data.icon == 0) {
@@ -2885,6 +2886,8 @@ static bool tselem_draw_icon(uiBlock *block,
}
const bool is_collection = outliner_is_collection_tree_element(te);
+ IconTextOverlay text_overlay;
+ UI_icon_text_overlay_init_from_count(&text_overlay, num_elements);
/* Collection colors and icons covered by restrict buttons. */
if (!is_clickable || x >= xmax || is_collection) {
@@ -2904,7 +2907,8 @@ static bool tselem_draw_icon(uiBlock *block,
alpha,
0.0f,
btheme->collection_color[collection->color_tag].color,
- true);
+ true,
+ &text_overlay);
return true;
}
}
@@ -2915,10 +2919,10 @@ static bool tselem_draw_icon(uiBlock *block,
/* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */
uchar color[4];
if (UI_icon_get_theme_color(data.icon, color)) {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay);
}
else {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay);
}
}
else {
@@ -2941,104 +2945,6 @@ static bool tselem_draw_icon(uiBlock *block,
return true;
}
-static bool outliner_is_main_row(const ARegion *region, const int ys)
-{
- int ystart;
-
- ystart = int(region->v2d.tot.ymax);
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- return ((ys - ystart) / UI_UNIT_Y) % 2;
-}
-
-/**
- * Get the expected row background color to use for the data-block counter
- *
- * This reproduces some of the logic of outliner_draw_highlights.
- * At the moment it doesn't implement the search match color since
- * we don't draw the data-block counter in those cases.
- */
-static void outliner_get_row_color(const ARegion *region,
- const TreeElement *te,
- int ys,
- float r_color[4])
-{
- const TreeStoreElem *tselem = TREESTORE(te);
-
- if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
- UI_GetThemeColor3fv(TH_ACTIVE, r_color);
- }
- else if (tselem->flag & TSE_SELECTED) {
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, r_color);
- }
- else if (outliner_is_main_row(region, ys)) {
- UI_GetThemeColor3fv(TH_BACK, r_color);
- }
- else {
- float color_alternating[4];
- UI_GetThemeColor4fv(TH_ROW_ALTERNATE, color_alternating);
- UI_GetThemeColorBlend3f(TH_BACK, TH_ROW_ALTERNATE, color_alternating[3], r_color);
- }
-
- if (tselem->flag & TSE_HIGHLIGHTED) {
- const float color_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
- interp_v3_v3v3(r_color, r_color, color_highlight, color_highlight[3]);
- }
- r_color[3] = 1.0f;
-}
-
-/**
- * For icon-only children of a collapsed tree,
- * Draw small number over the icon to show how many items of this type are displayed.
- */
-static void outliner_draw_iconrow_number(const ARegion *region,
- const uiFontStyle *fstyle,
- int offsx,
- int ys,
- const TreeElement *te_visible,
- const int num_elements)
-{
- float color[4];
- outliner_get_row_color(region, te_visible, ys, color);
-
- float ufac = 0.25f * UI_UNIT_X;
- float offset_x = float(offsx) + UI_UNIT_X * 0.35f;
- rctf rect{};
- BLI_rctf_init(&rect,
- offset_x + ufac,
- offset_x + UI_UNIT_X - ufac,
- float(ys) - UI_UNIT_Y * 0.2f + ufac,
- float(ys) - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv_ex(
- &rect, color, NULL, 1.0f, color, U.pixelsize, float(UI_UNIT_Y) / 2.0f - ufac);
-
- /* Now the numbers. */
- uchar text_col[4];
-
- UI_GetThemeColor3ubv(TH_TEXT, text_col);
- text_col[3] = 255;
-
- uiFontStyle fstyle_small = *fstyle;
- fstyle_small.points *= 0.8f;
-
- /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
- int num_digits = 4;
- char number_text[4] = "+99";
- if (num_elements < 100) {
- BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
- num_digits = num_elements < 10 ? 1 : 2;
- }
- UI_fontstyle_draw_simple(&fstyle_small,
- (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
- float(ys) - UI_UNIT_Y * 0.095f + ufac,
- number_text,
- text_col);
- UI_fontstyle_set(fstyle);
- GPU_blend(GPU_BLEND_ALPHA); /* Round-box and text drawing disables. */
-}
-
static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
{
float text[4];
@@ -3069,11 +2975,8 @@ static void outliner_draw_active_indicator(const float minx,
GPU_blend(GPU_BLEND_ALPHA); /* Round-box disables. */
}
-static void outliner_draw_iconrow_doit(const ARegion *region,
- uiBlock *block,
- TreeElement *te_visible,
+static void outliner_draw_iconrow_doit(uiBlock *block,
TreeElement *te,
- const uiFontStyle *fstyle,
int xmax,
int *offsx,
int ys,
@@ -3102,13 +3005,13 @@ static void outliner_draw_iconrow_doit(const ARegion *region,
if (tselem->flag & TSE_HIGHLIGHTED_ICON) {
alpha_fac += 0.5;
}
- tselem_draw_icon(block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false);
+ tselem_draw_icon(
+ block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false, num_elements);
te->xs = *offsx;
te->ys = ys;
te->xend = short(*offsx) + UI_UNIT_X;
if (num_elements > 1) {
- outliner_draw_iconrow_number(region, fstyle, *offsx, ys, te_visible, num_elements);
te->flag |= TE_ICONROW_MERGED;
}
else {
@@ -3145,7 +3048,6 @@ static void outliner_draw_iconrow(bContext *C,
const uiFontStyle *fstyle,
const TreeViewContext *tvc,
SpaceOutliner *space_outliner,
- TreeElement *te_visible,
ListBase *lb,
int level,
int xmax,
@@ -3154,7 +3056,6 @@ static void outliner_draw_iconrow(bContext *C,
float alpha_fac,
MergedIconRow *merged)
{
- const ARegion *region = CTX_wm_region(C);
eOLDrawState active = OL_DRAWSEL_NONE;
LISTBASE_FOREACH (TreeElement *, te, lb) {
@@ -3194,8 +3095,7 @@ static void outliner_draw_iconrow(bContext *C,
TSE_POSE_CHANNEL,
TSE_POSEGRP,
TSE_DEFGROUP)) {
- outliner_draw_iconrow_doit(
- region, block, te_visible, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
+ outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1);
}
else {
const int index = tree_element_id_type_to_index(te);
@@ -3214,7 +3114,6 @@ static void outliner_draw_iconrow(bContext *C,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
level + 1,
xmax,
@@ -3236,11 +3135,8 @@ static void outliner_draw_iconrow(bContext *C,
for (int j = 0; j < num_subtypes; j++) {
const int index = index_base + j;
if (merged->num_elements[index] != 0) {
- outliner_draw_iconrow_doit(region,
- block,
- te_visible,
+ outliner_draw_iconrow_doit(block,
merged->tree_element[index],
- fstyle,
xmax,
offsx,
ys,
@@ -3429,7 +3325,8 @@ static void outliner_draw_tree_element(bContext *C,
tselem,
te,
(tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac,
- true)) {
+ true,
+ 1)) {
offsx += UI_UNIT_X + 4 * ufac;
}
else {
@@ -3478,7 +3375,6 @@ static void outliner_draw_tree_element(bContext *C,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
0,
xmax,
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 1ede48a3265..58b1cd0a50b 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -282,6 +282,8 @@ set(GLSL_SRC
shaders/gpu_shader_2D_image_vert.glsl
shaders/gpu_shader_2D_image_rect_vert.glsl
shaders/gpu_shader_2D_image_multi_rect_vert.glsl
+ shaders/gpu_shader_icon_frag.glsl
+ shaders/gpu_shader_icon_vert.glsl
shaders/gpu_shader_image_frag.glsl
shaders/gpu_shader_image_desaturate_frag.glsl
shaders/gpu_shader_image_overlays_merge_frag.glsl
@@ -609,6 +611,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/gpu_shader_3D_smooth_color_info.hh
shaders/infos/gpu_shader_3D_uniform_color_info.hh
shaders/infos/gpu_shader_gpencil_stroke_info.hh
+ shaders/infos/gpu_shader_icon_info.hh
shaders/infos/gpu_shader_instance_varying_color_varying_size_info.hh
shaders/infos/gpu_shader_keyframe_shape_info.hh
shaders/infos/gpu_shader_line_dashed_uniform_color_info.hh
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 3f35db42eb9..1148207fc57 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -209,6 +209,10 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_KEYFRAME_SHAPE,
GPU_SHADER_SIMPLE_LIGHTING,
/**
+ * Draw an icon, leaving a semi-transparent rectangle on top of the icon.
+ */
+ GPU_SHADER_ICON,
+ /**
* Take a 2D position and color for each vertex with linear interpolation in window space.
*
* \param color: in vec4
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index 8a6586e06f6..470643ba863 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.create_info = "gpu_shader_2D_diag_stripes",
},
+ [GPU_SHADER_ICON] =
+ {
+ .name = "GPU_SHADER_ICON",
+ .create_info = "gpu_shader_icon",
+ },
[GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
{
.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
new file mode 100644
index 00000000000..ff56d772317
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
@@ -0,0 +1,42 @@
+/**
+ * Draw the icons, leaving a semi-transparent rectangle on top of the icon.
+ *
+ * The top-left corner of the rectangle is rounded and drawned with anti-alias.
+ * The anti-alias is done by transitioning from the outer to the inner radius of
+ * the rounded corner, and the rectangle sides.
+ */
+
+void main()
+{
+ /* Top-left rounded corner parameters. */
+ const float circle_radius_outer = 0.1;
+ const float circle_radius_inner = 0.075;
+
+ /**
+ * Add a bit transparency to see a bit of the icon, without
+ * getting on the way of readability. */
+ const float mask_transparency = 0.25;
+
+ vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5);
+ fragColor = texture(image, texCoord_interp) * color;
+
+ /* radius in icon space (1 is the icon width). */
+ float radius = length(mask_coord_interp - circle_center);
+ float mask = smoothstep(circle_radius_inner, circle_radius_outer, radius);
+
+ bool lower_half = mask_coord_interp.y < circle_center.y;
+ bool right_half = mask_coord_interp.x > circle_center.x;
+
+ if (right_half && mask_coord_interp.t < circle_center.y + circle_radius_outer) {
+ mask = smoothstep(circle_center.y + circle_radius_inner,
+ circle_center.y + circle_radius_outer,
+ mask_coord_interp.t);
+ }
+ if (lower_half && mask_coord_interp.s > circle_center.x - circle_radius_outer) {
+ mask = smoothstep(circle_center.x - circle_radius_inner,
+ circle_center.x - circle_radius_outer,
+ mask_coord_interp.s);
+ }
+
+ fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
new file mode 100644
index 00000000000..25f64bfe0b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
@@ -0,0 +1,37 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ */
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ mask_coord_interp = vec2(0, 1);
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ mask_coord_interp = vec2(0, 0);
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ mask_coord_interp = vec2(1, 1);
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ mask_coord_interp = vec2(1, 0);
+ }
+
+ /* Put origin in lower right corner. */
+ mask_coord_interp.x -= 1;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/infos/gpu_interface_info.hh b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
index d77c65e48a7..060def16f81 100644
--- a/source/blender/gpu/shaders/infos/gpu_interface_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
@@ -18,3 +18,6 @@ GPU_SHADER_INTERFACE_INFO(smooth_radii_outline_iface, "").smooth(Type::VEC4, "ra
GPU_SHADER_INTERFACE_INFO(flat_color_smooth_tex_coord_interp_iface, "")
.flat(Type::VEC4, "finalColor")
.smooth(Type::VEC2, "texCoord_interp");
+GPU_SHADER_INTERFACE_INFO(smooth_icon_interp_iface, "")
+ .smooth(Type::VEC2, "texCoord_interp")
+ .smooth(Type::VEC2, "mask_coord_interp");
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
new file mode 100644
index 00000000000..3d4077bdb09
--- /dev/null
+++ b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "gpu_interface_info.hh"
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(gpu_shader_icon)
+ .vertex_out(smooth_icon_interp_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .push_constant(Type::MAT4, "ModelViewProjectionMatrix")
+ .push_constant(Type::VEC4, "color")
+ .push_constant(Type::VEC4, "rect_icon")
+ .push_constant(Type::VEC4, "rect_geom")
+ .push_constant(Type::FLOAT, "text_width")
+ .sampler(0, ImageType::FLOAT_2D, "image")
+ .vertex_source("gpu_shader_icon_vert.glsl")
+ .fragment_source("gpu_shader_icon_frag.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc
index 0896daec561..fb63abed9e9 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.cc
+++ b/source/blender/windowmanager/intern/wm_dragdrop.cc
@@ -853,7 +853,8 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag
y = xy[1] - 2 * UI_DPI_FAC;
const uchar text_col[] = {255, 255, 255, 255};
- UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
}