Themes: add setting to draw border around icons, use for Blender Light

Monochrome colored icons don't work well on a dark background, so now we can
add a border around them. Note that most icons in the interface will remain
without a border, just the outliner and properties editor navigation have
colored icons and those will get a border. Other icons continue to be drawn
in the text colored without a border.

Differential Revision: https://developer.blender.org/D4787
This commit is contained in:
2019-05-09 15:53:44 +02:00
committed by Brecht Van Lommel
parent 9b924d73da
commit 5f7eebda23
6 changed files with 335 additions and 152 deletions

View File

@@ -16,12 +16,13 @@
gizmo_secondary="#63ffff"
gizmo_a="#4da84d"
gizmo_b="#a33535"
icon_scene="#000000ff"
icon_collection="#000000ff"
icon_object="#000000ff"
icon_object_data="#000000ff"
icon_modifier="#000000ff"
icon_shading="#000000ff"
icon_scene="#e6e6e6ff"
icon_collection="#e6e6e6ff"
icon_object="#e49759ff"
icon_object_data="#89e689ff"
icon_modifier="#84b8ffff"
icon_shading="#ff6060ff"
icon_border_intensity="0.75"
>
<wcol_regular>
<ThemeWidgetColors

View File

@@ -895,6 +895,7 @@ class USERPREF_PT_theme_interface_icons(PreferencePanel, Panel):
flow.prop(ui, "icon_object_data")
flow.prop(ui, "icon_modifier")
flow.prop(ui, "icon_shading")
flow.prop(ui, "icon_border_intensity")
class USERPREF_PT_theme_text_style(PreferencePanel, Panel):

View File

@@ -52,6 +52,7 @@ typedef struct IconFile {
* Resizable Icons for Blender
*/
void UI_icons_init(void);
void UI_icons_reload_internal_textures(void);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);

View File

@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
#include "BLI_math_vector.h"
#include "BLI_math_color_blend.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -83,6 +84,7 @@
# define ICON_GRID_COLS 26
# define ICON_GRID_ROWS 30
# define ICON_MONO_BORDER_OUTSET 2
# define ICON_GRID_MARGIN 10
# define ICON_GRID_W 32
# define ICON_GRID_H 32
@@ -138,7 +140,8 @@ typedef struct DrawInfo {
} DrawInfo;
typedef struct IconTexture {
GLuint id;
GLuint id[2];
int num_textures;
int w;
int h;
float invw;
@@ -154,7 +157,7 @@ typedef struct IconType {
/* static here to cache results of icon directory scan, so it's not
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f};
#ifndef WITH_HEADLESS
@@ -714,10 +717,214 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
static ImBuf *create_mono_icon_with_border(ImBuf *buf,
int resolution_divider,
float border_intensity)
{
ImBuf *result = IMB_dupImBuf(buf);
const float border_sharpness = 16.0 / (resolution_divider * resolution_divider);
float blurred_alpha_buffer[(ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) *
(ICON_GRID_H + 2 * ICON_MONO_BORDER_OUTSET)];
const int icon_width = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
const int icon_height = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
for (int y = 0; y < ICON_GRID_ROWS; y++) {
for (int x = 0; x < ICON_GRID_COLS; x++) {
IconType icontype = icontypes[y * ICON_GRID_COLS + x];
if (icontype.type != ICON_TYPE_MONO_TEXTURE) {
continue;
}
int sx = x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
int sy = y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
sx = sx / resolution_divider;
sy = sy / resolution_divider;
/* blur the alpha channel and store it in blurred_alpha_buffer */
int blur_size = 2 / resolution_divider;
for (int bx = 0; bx < icon_width; bx++) {
const int asx = MAX2(bx - blur_size, 0);
const int aex = MIN2(bx + blur_size + 1, icon_width);
for (int by = 0; by < icon_height; by++) {
const int asy = MAX2(by - blur_size, 0);
const int aey = MIN2(by + blur_size + 1, icon_height);
// blur alpha channel
const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
float alpha_accum = 0.0;
unsigned int alpha_samples = 0;
for (int ax = asx; ax < aex; ax++) {
for (int ay = asy; ay < aey; ay++) {
const int offset_read = (sy + ay) * buf->x + (sx + ax);
unsigned int color_read = buf->rect[offset_read];
const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0;
alpha_accum += alpha_read;
alpha_samples += 1;
}
}
blurred_alpha_buffer[write_offset] = alpha_accum / alpha_samples;
}
}
/* apply blurred alpha */
for (int bx = 0; bx < icon_width; bx++) {
for (int by = 0; by < icon_height; by++) {
const int blurred_alpha_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
const int offset_write = (sy + by) * buf->x + (sx + bx);
const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset];
float border_srgb[4] = {
0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity};
const unsigned int color_read = buf->rect[offset_write];
const unsigned char *orig_color = (unsigned char *)&color_read;
float border_rgba[4];
float orig_rgba[4];
float dest_rgba[4];
float dest_srgb[4];
srgb_to_linearrgb_v4(border_rgba, border_srgb);
srgb_to_linearrgb_uchar4(orig_rgba, orig_color);
blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]);
linearrgb_to_srgb_v4(dest_srgb, dest_rgba);
unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24;
unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
result->rect[offset_write] = cpack;
}
}
}
}
return result;
}
/* Generate the mipmap levels for the icon textures
* During creation the source16 ImBuf will be freed to reduce memory overhead
* A new ImBuf will be returned that needs is owned by the caller.
*
* FIXME: Mipmap levels are generated until the width of the image is 1, which
* are too many levels than that are needed.*/
static ImBuf *create_mono_icon_mipmaps(ImBuf *source32, ImBuf *source16, int level)
{
if (level == 0) {
glTexImage2D(GL_TEXTURE_2D,
level,
GL_RGBA8,
source32->x,
source32->y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
source32->rect);
return create_mono_icon_mipmaps(source32, source16, level + 1);
}
else {
glTexImage2D(GL_TEXTURE_2D,
level,
GL_RGBA8,
source16->x,
source16->y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
source16->rect);
if (source16->x > 1) {
ImBuf *nbuf = IMB_onehalf(source16);
IMB_freeImBuf(source16);
source16 = create_mono_icon_mipmaps(source32, nbuf, level + 1);
}
return source16;
}
}
static void free_icons_textures(void)
{
if (icongltex.num_textures > 0) {
glDeleteTextures(icongltex.num_textures, icongltex.id);
icongltex.id[0] = 0;
icongltex.id[1] = 0;
icongltex.num_textures = 0;
}
}
/* Reload the textures for internal icons.
* This function will release the previous textures. */
void UI_icons_reload_internal_textures(void)
{
bTheme *btheme = UI_GetTheme();
ImBuf *b16buf = NULL, *b32buf = NULL, *b16buf_border = NULL, *b32buf_border = NULL;
const float icon_border_intensity = btheme->tui.icon_border_intensity;
bool need_icons_with_border = icon_border_intensity > 0.0f;
if (b16buf == NULL) {
b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size,
IB_rect,
NULL,
"<blender icons>");
}
if (b16buf) {
if (need_icons_with_border) {
b16buf_border = create_mono_icon_with_border(b16buf, 2, icon_border_intensity);
IMB_premultiply_alpha(b16buf_border);
}
IMB_premultiply_alpha(b16buf);
}
if (b32buf == NULL) {
b32buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons32_png,
datatoc_blender_icons32_png_size,
IB_rect,
NULL,
"<blender icons>");
}
if (b32buf) {
if (need_icons_with_border) {
b32buf_border = create_mono_icon_with_border(b32buf, 1, icon_border_intensity);
IMB_premultiply_alpha(b32buf_border);
}
IMB_premultiply_alpha(b32buf);
}
if (b16buf && b32buf) {
/* Free existing texture if any. */
free_icons_textures();
/* Allocate OpenGL texture. */
icongltex.num_textures = need_icons_with_border ? 2 : 1;
glGenTextures(icongltex.num_textures, icongltex.id);
if (icongltex.id) {
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
glBindTexture(GL_TEXTURE_2D, icongltex.id[0]);
b16buf = create_mono_icon_mipmaps(b32buf, b16buf, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
if (need_icons_with_border && icongltex.id[1]) {
glBindTexture(GL_TEXTURE_2D, icongltex.id[1]);
b16buf_border = create_mono_icon_mipmaps(b32buf_border, b16buf_border, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
IMB_freeImBuf(b16buf);
IMB_freeImBuf(b32buf);
IMB_freeImBuf(b16buf_border);
IMB_freeImBuf(b32buf_border);
}
static void init_internal_icons(void)
{
// bTheme *btheme = UI_GetTheme();
ImBuf *b16buf = NULL, *b32buf = NULL;
int x, y;
# if 0 // temp disabled
@@ -746,106 +953,23 @@ static void init_internal_icons(void)
}
}
# endif
if (b16buf == NULL) {
b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size,
IB_rect,
NULL,
"<blender icons>");
}
if (b16buf) {
IMB_premultiply_alpha(b16buf);
}
if (b32buf == NULL) {
b32buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons32_png,
datatoc_blender_icons32_png_size,
IB_rect,
NULL,
"<blender icons>");
}
if (b32buf) {
IMB_premultiply_alpha(b32buf);
}
if (b16buf && b32buf) {
/* Free existing texture if any. */
if (icongltex.id) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
/* Allocate OpenGL texture. */
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
int level = 2;
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
glBindTexture(GL_TEXTURE_2D, icongltex.id);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA8,
b32buf->x,
b32buf->y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
b32buf->rect);
glTexImage2D(GL_TEXTURE_2D,
1,
GL_RGBA8,
b16buf->x,
b16buf->y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
b16buf->rect);
while (b16buf->x > 1) {
ImBuf *nbuf = IMB_onehalf(b16buf);
glTexImage2D(GL_TEXTURE_2D,
level,
GL_RGBA8,
nbuf->x,
nbuf->y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
nbuf->rect);
level++;
IMB_freeImBuf(b16buf);
b16buf = nbuf;
/* Define icons. */
for (y = 0; y < ICON_GRID_ROWS; y++) {
/* Row W has monochrome icons. */
for (x = 0; x < ICON_GRID_COLS; x++) {
IconType icontype = icontypes[y * ICON_GRID_COLS + x];
if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
continue;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
/* Define icons. */
for (y = 0; y < ICON_GRID_ROWS; y++) {
/* Row W has monochrome icons. */
for (x = 0; x < ICON_GRID_COLS; x++) {
IconType icontype = icontypes[y * ICON_GRID_COLS + x];
if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
continue;
}
def_internal_icon(b32buf,
BIFICONID_FIRST + y * ICON_GRID_COLS + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
ICON_GRID_W,
icontype.type,
icontype.theme_color);
}
def_internal_icon(NULL,
BIFICONID_FIRST + y * ICON_GRID_COLS + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
ICON_GRID_W,
icontype.type,
icontype.theme_color);
}
}
@@ -883,9 +1007,6 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
IMB_freeImBuf(b16buf);
IMB_freeImBuf(b32buf);
}
# endif /* WITH_HEADLESS */
@@ -991,11 +1112,7 @@ ListBase *UI_iconfile_list(void)
void UI_icons_free(void)
{
#ifndef WITH_HEADLESS
if (icongltex.id) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
free_icons_textures();
free_iconfile_list(&iconfilelist);
BKE_icons_free();
#endif
@@ -1109,6 +1226,7 @@ void UI_icons_init()
{
#ifndef WITH_HEADLESS
init_iconfile_list(&iconfilelist);
UI_icons_reload_internal_textures();
init_internal_icons();
init_brush_icons();
init_event_icons();
@@ -1440,12 +1558,17 @@ typedef struct IconDrawCall {
float color[4];
} IconDrawCall;
static struct {
typedef struct IconTextureDrawCall {
IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
int calls; /* Number of calls batched together */
} IconTextureDrawCall;
static struct {
IconTextureDrawCall normal;
IconTextureDrawCall border;
bool enabled;
float mat[4][4];
} g_icon_draw_cache = {{{{0}}}};
} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
{
@@ -1453,19 +1576,15 @@ void UI_icon_draw_cache_begin(void)
g_icon_draw_cache.enabled = true;
}
static void icon_draw_cache_flush_ex(void)
static void icon_draw_cache_texture_flush_ex(GLuint texture,
IconTextureDrawCall *texture_draw_calls)
{
if (g_icon_draw_cache.calls == 0) {
if (texture_draw_calls->calls == 0) {
return;
}
/* We need to flush widget base first to ensure correct ordering. */
UI_widgetbase_draw_cache_flush();
GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
glBindTexture(GL_TEXTURE_2D, texture);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1474,16 +1593,43 @@ static void icon_draw_cache_flush_ex(void)
int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
glUniform1i(img_loc, 0);
glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
GPU_draw_primitive(GPU_PRIM_TRIS, 6 * texture_draw_calls->calls);
glBindTexture(GL_TEXTURE_2D, 0);
g_icon_draw_cache.calls = 0;
texture_draw_calls->calls = 0;
}
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
static void icon_draw_cache_flush_ex(bool only_full_caches)
{
bool should_draw = false;
if (only_full_caches) {
should_draw = g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE ||
g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE;
}
else {
should_draw = g_icon_draw_cache.normal.calls || g_icon_draw_cache.border.calls;
}
if (should_draw) {
/* We need to flush widget base first to ensure correct ordering. */
UI_widgetbase_draw_cache_flush();
GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (!only_full_caches || g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE) {
icon_draw_cache_texture_flush_ex(icongltex.id[0], &g_icon_draw_cache.normal);
}
if (!only_full_caches || g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE) {
icon_draw_cache_texture_flush_ex(icongltex.id[1], &g_icon_draw_cache.border);
}
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
}
void UI_icon_draw_cache_end(void)
@@ -1492,12 +1638,12 @@ void UI_icon_draw_cache_end(void)
g_icon_draw_cache.enabled = false;
/* Don't change blend state if it's not needed. */
if (g_icon_draw_cache.calls == 0) {
if (g_icon_draw_cache.border.calls == 0 && g_icon_draw_cache.normal.calls == 0) {
return;
}
GPU_blend(true);
icon_draw_cache_flush_ex();
icon_draw_cache_flush_ex(false);
GPU_blend(false);
}
@@ -1510,14 +1656,18 @@ static void icon_draw_texture_cached(float x,
int UNUSED(iw),
int ih,
float alpha,
const float rgb[3])
const float rgb[3],
bool with_border)
{
float mvp[4][4];
GPU_matrix_model_view_projection_get(mvp);
IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
g_icon_draw_cache.calls++;
IconTextureDrawCall *texture_call = with_border ? &g_icon_draw_cache.border :
&g_icon_draw_cache.normal;
IconDrawCall *call = &texture_call->drawcall_cache[texture_call->calls];
texture_call->calls++;
/* Manual mat4*vec2 */
call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
@@ -1537,8 +1687,8 @@ static void icon_draw_texture_cached(float x,
copy_v4_fl(call->color, alpha);
}
if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
icon_draw_cache_flush_ex();
if (texture_call->calls == ICON_DRAW_CACHE_SIZE) {
icon_draw_cache_flush_ex(true);
}
}
@@ -1551,10 +1701,11 @@ static void icon_draw_texture(float x,
int iw,
int ih,
float alpha,
const float rgb[3])
const float rgb[3],
bool with_border)
{
if (g_icon_draw_cache.enabled) {
icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1571,7 +1722,7 @@ static void icon_draw_texture(float x,
y2 = (iy + ih) * icongltex.invh;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
glBindTexture(GL_TEXTURE_2D, with_border ? icongltex.id[1] : icongltex.id[0]);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1696,10 +1847,12 @@ static void icon_draw_size(float x,
di->data.texture.w,
di->data.texture.h,
alpha,
rgb);
rgb,
false);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
/* icon that matches text color, assumed to be white */
bool with_border = false;
float color[4];
if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
if (mono_rgba) {
@@ -1709,6 +1862,9 @@ static void icon_draw_size(float x,
UI_GetThemeColor4fv(TH_TEXT, color);
}
}
else {
with_border = (btheme->tui.icon_border_intensity > 0.0f);
}
if (rgb) {
mul_v3_v3(color, rgb);
@@ -1716,16 +1872,24 @@ static void icon_draw_size(float x,
mul_v4_fl(color, alpha);
icon_draw_texture(x,
y,
(float)w,
(float)h,
di->data.texture.x,
di->data.texture.y,
di->data.texture.w,
di->data.texture.h,
float border_outset = 0.0;
unsigned int border_texel = 0;
if (with_border) {
const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
border_texel = ICON_MONO_BORDER_OUTSET;
border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect);
}
icon_draw_texture(x - border_outset,
y - border_outset,
(float)w + 2 * border_outset,
(float)h + 2 * border_outset,
di->data.texture.x - border_texel,
di->data.texture.y - border_texel,
di->data.texture.w + 2 * border_texel,
di->data.texture.h + 2 * border_texel,
color[3],
color);
color,
with_border);
}
else if (di->type == ICON_TYPE_BUFFER) {

View File

@@ -196,8 +196,9 @@ typedef struct ThemeUI {
char icon_modifier[4];
/** Shading related items. */
char icon_shading[4];
char _pad1[4];
/** Intensity of the border icons. >0 will render an border around themed
* icons. */
float icon_border_intensity;
} ThemeUI;
/* try to put them all in one, if needed a special struct can be created as well

View File

@@ -42,6 +42,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface_icons.h"
#include "rna_internal.h"
#include "WM_api.h"
@@ -195,6 +197,12 @@ static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_userdef_update(bmain, scene, ptr);
}
static void rna_userdef_theme_update_icons(Main *bmain, Scene *scene, PointerRNA *ptr)
{
UI_icons_reload_internal_textures();
rna_userdef_theme_update(bmain, scene, ptr);
}
/* also used by buffer swap switching */
static void rna_userdef_dpi_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
@@ -1412,6 +1420,13 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Shading", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "icon_border_intensity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "icon_border_intensity");
RNA_def_property_ui_text(
prop, "Icon Border", "Control the intensity of the border around themes icons");
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
RNA_def_property_update(prop, 0, "rna_userdef_theme_update_icons");
}
static void rna_def_userdef_theme_space_common(StructRNA *srna)