Compare commits
42 Commits
main
...
temp-ui-wi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8d09ca96a7 | ||
![]() |
d693aa3590 | ||
![]() |
8dbe598192 | ||
![]() |
76a74e2c58 | ||
![]() |
ae50da6ea6 | ||
![]() |
73310f25fe | ||
![]() |
4db51cf00e | ||
![]() |
e28f359007 | ||
![]() |
e022e44af0 | ||
![]() |
6cad17291c | ||
![]() |
b284667681 | ||
![]() |
f2c6b7cdda | ||
![]() |
d2fc12d73e | ||
![]() |
50bd598a17 | ||
![]() |
bd46a92deb | ||
![]() |
b2e18d25b0 | ||
![]() |
08b3e9a49c | ||
![]() |
74eb56fe7e | ||
![]() |
2b73dff7cf | ||
![]() |
eba5bd3340 | ||
![]() |
b22061e989 | ||
![]() |
5d021e3331 | ||
![]() |
b947998a51 | ||
![]() |
2a325a0eb9 | ||
![]() |
94adf2cc5f | ||
![]() |
80af1f10fc | ||
![]() |
56c6bd646a | ||
![]() |
85eb2ea3bb | ||
![]() |
f45c2a9cb5 | ||
![]() |
a3a56d9aaf | ||
![]() |
03bfc42f74 | ||
![]() |
e50904f9c9 | ||
![]() |
0e06f4c491 | ||
![]() |
52ce543f4d | ||
![]() |
0a202fdfce | ||
![]() |
d032de3bae | ||
![]() |
29166b3ae3 | ||
![]() |
d6c93298b5 | ||
![]() |
9ebe875dcc | ||
![]() |
58c50e786a | ||
![]() |
0d3a3347f0 | ||
![]() |
db5e89ad5c |
@@ -19,6 +19,8 @@
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
widgets
|
||||
widgets/widgets_draw
|
||||
../include
|
||||
../../blenfont
|
||||
../../blenkernel
|
||||
@@ -55,8 +57,14 @@ set(SRC
|
||||
resources.c
|
||||
view2d.c
|
||||
view2d_ops.c
|
||||
widgets/widgets.c
|
||||
widgets/widgets_draw/drawstyle_classic.c
|
||||
widgets/widgets_draw/widgets_draw.c
|
||||
widgets/widgets_draw/widgets_draw_text.c
|
||||
|
||||
interface_intern.h
|
||||
widgets/widgets.h
|
||||
widgets/widgets_draw/widgets_draw_intern.h
|
||||
)
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
|
@@ -1384,7 +1384,7 @@ void UI_block_draw(const bContext *C, uiBlock *block)
|
||||
/* XXX: figure out why invalid coordinates happen when closing render window */
|
||||
/* and material preview is redrawn in main window (temp fix for bug #23848) */
|
||||
if (rect.xmin < rect.xmax && rect.ymin < rect.ymax)
|
||||
ui_draw_but(C, ar, &style, but, &rect);
|
||||
ui_draw_but(ar, &style, but, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -953,266 +953,6 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
copy_v2_fl2(v, x1 + halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y1 + height);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1 - halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
if (fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
}
|
||||
else {
|
||||
glPolygonMode(GL_FRONT, GL_LINE);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
copy_v2_fl2(v, x1 + halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y1 + height);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1 - halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
if (fill) {
|
||||
glDisable(GL_POLYGON_SMOOTH);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
if (fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
else {
|
||||
glPolygonMode(GL_FRONT, GL_LINE);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
copy_v2_fl2(v, x1, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y2);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x2, y2);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x2, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
if (!fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle(
|
||||
const rcti *rect, float x,
|
||||
const float rgb[3], struct ColorManagedDisplay *display,
|
||||
bool active)
|
||||
{
|
||||
const float sizey = BLI_rcti_size_y(rect);
|
||||
const float min_width = 3.0f;
|
||||
float half_width, height, y1, y2;
|
||||
float colf[3] = {UNPACK3(rgb)};
|
||||
|
||||
half_width = floorf(sizey / 3.5f);
|
||||
height = half_width * 1.4f;
|
||||
|
||||
y1 = rect->ymin + (sizey * 0.16f);
|
||||
y2 = rect->ymax;
|
||||
|
||||
/* align to pixels */
|
||||
x = floorf(x + 0.5f);
|
||||
y1 = floorf(y1 + 0.5f);
|
||||
|
||||
if (active || half_width < min_width) {
|
||||
glBegin(GL_LINES);
|
||||
glColor3ub(0, 0, 0);
|
||||
glVertex2f(x, y1);
|
||||
glVertex2f(x, y2);
|
||||
glEnd();
|
||||
setlinestyle(active ? 2 : 1);
|
||||
glBegin(GL_LINES);
|
||||
glColor3ub(200, 200, 200);
|
||||
glVertex2f(x, y1);
|
||||
glVertex2f(x, y2);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
|
||||
/* hide handles when zoomed out too far */
|
||||
if (half_width < min_width) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* shift handle down */
|
||||
y1 = y1 - half_width;
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false);
|
||||
|
||||
/* draw all triangles blended */
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
|
||||
|
||||
if (active)
|
||||
glColor3ub(196, 196, 196);
|
||||
else
|
||||
glColor3ub(96, 96, 96);
|
||||
ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
|
||||
|
||||
if (active)
|
||||
glColor3ub(255, 255, 255);
|
||||
else
|
||||
glColor3ub(128, 128, 128);
|
||||
ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1));
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glColor3ub(128, 128, 128);
|
||||
ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
|
||||
|
||||
if (display) {
|
||||
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
|
||||
}
|
||||
|
||||
glColor3fv(colf);
|
||||
ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
|
||||
}
|
||||
|
||||
void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
|
||||
{
|
||||
ColorBand *coba;
|
||||
CBData *cbd;
|
||||
float x1, y1, sizex, sizey, sizey_solid;
|
||||
float v1[2], v2[2];
|
||||
int a;
|
||||
float pos, colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
|
||||
struct ColorManagedDisplay *display = NULL;
|
||||
|
||||
coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
|
||||
if (coba == NULL) return;
|
||||
|
||||
if (but->block->color_profile)
|
||||
display = ui_block_cm_display_get(but->block);
|
||||
|
||||
x1 = rect->xmin;
|
||||
sizex = rect->xmax - x1;
|
||||
sizey = BLI_rcti_size_y(rect);
|
||||
sizey_solid = sizey / 4;
|
||||
y1 = rect->ymin;
|
||||
|
||||
/* layer: background, to show tranparency */
|
||||
glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
|
||||
glRectf(x1, y1, x1 + sizex, rect->ymax);
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
|
||||
glPolygonStipple(stipple_checker_8px);
|
||||
glRectf(x1, y1, x1 + sizex, rect->ymax);
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
|
||||
/* layer: color ramp */
|
||||
glShadeModel(GL_FLAT);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
cbd = coba->data;
|
||||
|
||||
v1[1] = y1 + sizey_solid;
|
||||
v2[1] = rect->ymax;
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (a = 0; a <= sizex; a++) {
|
||||
pos = ((float)a) / sizex;
|
||||
do_colorband(coba, pos, colf);
|
||||
if (display)
|
||||
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
|
||||
|
||||
v1[0] = v2[0] = x1 + a;
|
||||
|
||||
glColor4fv(colf);
|
||||
glVertex2fv(v1);
|
||||
glVertex2fv(v2);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* layer: color ramp without alpha for reference when manipulating ramp properties */
|
||||
v1[1] = y1;
|
||||
v2[1] = y1 + sizey_solid;
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (a = 0; a <= sizex; a++) {
|
||||
pos = ((float)a) / sizex;
|
||||
do_colorband(coba, pos, colf);
|
||||
if (display)
|
||||
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
|
||||
|
||||
v1[0] = v2[0] = x1 + a;
|
||||
|
||||
glColor4f(colf[0], colf[1], colf[2], 1.0f);
|
||||
glVertex2fv(v1);
|
||||
glVertex2fv(v2);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
/* layer: box outline */
|
||||
glColor4f(0.0, 0.0, 0.0, 1.0);
|
||||
fdrawbox(x1, y1, x1 + sizex, rect->ymax);
|
||||
|
||||
/* layer: box outline */
|
||||
glEnable(GL_BLEND);
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
fdrawline(x1, y1, x1 + sizex, y1);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
|
||||
fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* layer: draw handles */
|
||||
for (a = 0; a < coba->tot; a++, cbd++) {
|
||||
if (a != coba->cur) {
|
||||
pos = x1 + cbd->pos * (sizex - 1) + 1;
|
||||
ui_draw_colorband_handle(rect, pos, &cbd->r, display, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* layer: active handle */
|
||||
if (coba->tot != 0) {
|
||||
cbd = &coba->data[coba->cur];
|
||||
pos = x1 + cbd->pos * (sizex - 1) + 1;
|
||||
ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
|
||||
{
|
||||
static GLuint displist = 0;
|
||||
|
@@ -57,50 +57,6 @@ struct ImBuf;
|
||||
#define RNA_NO_INDEX -1
|
||||
#define RNA_ENUM_VALUE -2
|
||||
|
||||
/* visual types for drawing */
|
||||
/* for time being separated from functional types */
|
||||
typedef enum {
|
||||
/* default */
|
||||
UI_WTYPE_REGULAR,
|
||||
|
||||
/* standard set */
|
||||
UI_WTYPE_LABEL,
|
||||
UI_WTYPE_TOGGLE,
|
||||
UI_WTYPE_CHECKBOX,
|
||||
UI_WTYPE_RADIO,
|
||||
UI_WTYPE_NUMBER,
|
||||
UI_WTYPE_SLIDER,
|
||||
UI_WTYPE_EXEC,
|
||||
UI_WTYPE_TOOLTIP,
|
||||
|
||||
/* strings */
|
||||
UI_WTYPE_NAME,
|
||||
UI_WTYPE_NAME_LINK,
|
||||
UI_WTYPE_POINTER_LINK,
|
||||
UI_WTYPE_FILENAME,
|
||||
|
||||
/* menus */
|
||||
UI_WTYPE_MENU_RADIO,
|
||||
UI_WTYPE_MENU_ICON_RADIO,
|
||||
UI_WTYPE_MENU_POINTER_LINK,
|
||||
UI_WTYPE_MENU_NODE_LINK,
|
||||
|
||||
UI_WTYPE_PULLDOWN,
|
||||
UI_WTYPE_MENU_ITEM,
|
||||
UI_WTYPE_MENU_ITEM_RADIAL,
|
||||
UI_WTYPE_MENU_BACK,
|
||||
|
||||
/* specials */
|
||||
UI_WTYPE_ICON,
|
||||
UI_WTYPE_SWATCH,
|
||||
UI_WTYPE_RGB_PICKER,
|
||||
UI_WTYPE_UNITVEC,
|
||||
UI_WTYPE_BOX,
|
||||
UI_WTYPE_SCROLL,
|
||||
UI_WTYPE_LISTITEM,
|
||||
UI_WTYPE_PROGRESSBAR,
|
||||
} uiWidgetTypeEnum;
|
||||
|
||||
/* menu scrolling */
|
||||
#define UI_MENU_SCROLL_ARROW 12
|
||||
#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2)
|
||||
@@ -619,7 +575,6 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
|
||||
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_COLORBAND(uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_UNITVEC(uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
|
||||
@@ -666,7 +621,7 @@ void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
|
||||
bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol);
|
||||
void ui_draw_link_bezier(const rcti *rect);
|
||||
|
||||
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
|
||||
extern void ui_draw_but(ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
|
||||
/* theme color init */
|
||||
struct ThemeUI;
|
||||
void ui_widget_color_init(struct ThemeUI *tui);
|
||||
|
File diff suppressed because it is too large
Load Diff
295
source/blender/editors/interface/widgets/widgets.c
Normal file
295
source/blender/editors/interface/widgets/widgets.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/interface/widgets/widgets.c
|
||||
* \ingroup edinterface
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
|
||||
#include "widgets.h" /* own include */
|
||||
|
||||
|
||||
|
||||
uiWidgetDrawStyle *widget_drawstyle_get(const short drawstyle_type) /* TODO widget draw styles are for later */
|
||||
{
|
||||
#if 0
|
||||
switch (widget_style_type) {
|
||||
case WIDGETSTYLE_TYPE_CLASSIC:
|
||||
return &WidgetStyle_Classic;
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
return &WidgetStyle_Classic;
|
||||
|
||||
(void)drawstyle_type;
|
||||
#endif
|
||||
}
|
||||
|
||||
uiWidgetType *WidgetTypeInit(const uiWidgetTypeEnum type)
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
const uiWidgetDrawStyle *draw_style = widget_drawstyle_get(0); /* TODO drawstyles aren't in use yet */
|
||||
static uiWidgetType wt;
|
||||
|
||||
/* defaults */
|
||||
wt.wcol_theme = &btheme->tui.wcol_regular;
|
||||
wt.wcol_state = &btheme->tui.wcol_state;
|
||||
wt.draw_type = NULL;
|
||||
|
||||
switch (type) {
|
||||
/* let's keep this in a nice alphabetical order! */
|
||||
|
||||
case UI_WTYPE_BOX:
|
||||
wt.wcol_theme = &btheme->tui.wcol_box;
|
||||
wt.draw_type = draw_style->box;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_CHECKBOX:
|
||||
wt.wcol_theme = &btheme->tui.wcol_option;
|
||||
wt.draw_type = draw_style->checkbox;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_COLORBAND:
|
||||
wt.draw_type = draw_style->colorband;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_EXEC:
|
||||
wt.wcol_theme = &btheme->tui.wcol_tool;
|
||||
wt.draw_type = draw_style->exec;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_EXTRA:
|
||||
wt.draw_type = draw_style->extra_mask;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_FILENAME:
|
||||
break;
|
||||
|
||||
case UI_WTYPE_HSV_CIRCLE:
|
||||
wt.draw_type = draw_style->hsv_circle;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_HSV_CUBE:
|
||||
wt.draw_type = draw_style->hsv_cube;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_HSV_VERT:
|
||||
wt.draw_type = draw_style->hsv_vert;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_ICON:
|
||||
wt.draw_type = draw_style->icon;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_LABEL:
|
||||
wt.draw_type = draw_style->label;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_LINK:
|
||||
wt.draw_type = draw_style->link;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_LISTITEM:
|
||||
wt.wcol_theme = &btheme->tui.wcol_list_item;
|
||||
wt.draw_type = draw_style->listitem;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_LISTSCROLL:
|
||||
wt.wcol_theme = &btheme->tui.wcol_scroll;
|
||||
wt.draw_type = draw_style->listscroll;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_BACK:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu_back;
|
||||
wt.draw_type = draw_style->menu_back;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_ICON_RADIO:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu;
|
||||
wt.draw_type = draw_style->menu_icon_radio;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_ITEM:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu_item;
|
||||
wt.draw_type = draw_style->menu_item;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_ITEM_PREVIEW:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu_item;
|
||||
wt.draw_type = draw_style->menu_item_preview;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_ITEM_RADIAL:
|
||||
wt.wcol_theme = &btheme->tui.wcol_pie_menu;
|
||||
wt.draw_type = draw_style->menu_item_radial;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_LABEL:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu_back;
|
||||
wt.draw_type = draw_style->menu_label;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_NODE_LINK:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu;
|
||||
wt.draw_type = draw_style->menu_node_link;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_POINTER_LINK:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu;
|
||||
wt.draw_type = draw_style->pointer_link;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_RADIO:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu;
|
||||
wt.draw_type = draw_style->menu_radio;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_NAME:
|
||||
wt.wcol_theme = &btheme->tui.wcol_text;
|
||||
wt.draw_type = draw_style->name;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_NAME_LINK:
|
||||
break;
|
||||
|
||||
case UI_WTYPE_NUMBER:
|
||||
wt.wcol_theme = &btheme->tui.wcol_num;
|
||||
wt.draw_type = draw_style->number;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_POINTER_LINK:
|
||||
break;
|
||||
|
||||
case UI_WTYPE_PROGRESSBAR:
|
||||
wt.wcol_theme = &btheme->tui.wcol_progress;
|
||||
wt.draw_type = draw_style->progressbar;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_PULLDOWN:
|
||||
wt.wcol_theme = &btheme->tui.wcol_pulldown;
|
||||
wt.draw_type = draw_style->pulldown;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_RADIO:
|
||||
wt.wcol_theme = &btheme->tui.wcol_radio;
|
||||
wt.draw_type = draw_style->radio;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_REGULAR:
|
||||
wt.draw_type = draw_style->regular;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_RGB_PICKER:
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SCROLL_BACK:
|
||||
wt.draw_type = draw_style->scroll_back;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SCROLL_INNER:
|
||||
wt.draw_type = draw_style->scroll_inner;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SEARCH_BACK:
|
||||
wt.wcol_theme = &btheme->tui.wcol_box;
|
||||
wt.draw_type = draw_style->search_back;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SEPARATOR:
|
||||
wt.wcol_theme = &btheme->tui.wcol_menu_item;
|
||||
wt.draw_type = draw_style->separator;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SLIDER:
|
||||
wt.wcol_theme = &btheme->tui.wcol_numslider;
|
||||
wt.draw_type = draw_style->slider;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SWATCH:
|
||||
wt.draw_type = draw_style->swatch;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_TOGGLE:
|
||||
wt.wcol_theme = &btheme->tui.wcol_toggle;
|
||||
wt.draw_type = draw_style->toggle;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_TOOLTIP:
|
||||
wt.wcol_theme = &btheme->tui.wcol_tooltip;
|
||||
wt.draw_type = draw_style->tooltip;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_UNITVEC:
|
||||
wt.draw_type = draw_style->unitvec;
|
||||
break;
|
||||
}
|
||||
|
||||
return &wt;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Widget main draw routine
|
||||
*
|
||||
* passing NULL for \a but disables draw_type->custom and draw_type->text,
|
||||
* passing NULl for \a fstyle or \a str disables draw_type->text
|
||||
*/
|
||||
void WidgetDraw(
|
||||
uiWidgetType *wt,
|
||||
uiFontStyle *fstyle, uiBut *but, rcti *rect,
|
||||
int state, int roundboxalign, const int iconid, const char *str,
|
||||
const bool use_text_blend)
|
||||
{
|
||||
uiWidgetDrawType *dtype = wt->draw_type;
|
||||
|
||||
if (dtype->state) {
|
||||
dtype->state(wt, state);
|
||||
}
|
||||
|
||||
if (dtype->custom && but) {
|
||||
dtype->custom(but, &wt->wcol, rect, state, roundboxalign);
|
||||
}
|
||||
else if (dtype->draw) {
|
||||
dtype->draw(&wt->wcol, rect, state, roundboxalign);
|
||||
}
|
||||
|
||||
if (dtype->text && but && fstyle && str) {
|
||||
if (use_text_blend) {
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
dtype->text(fstyle, &wt->wcol, but, rect, str, iconid);
|
||||
if (use_text_blend) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
}
|
181
source/blender/editors/interface/widgets/widgets.h
Normal file
181
source/blender/editors/interface/widgets/widgets.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __WIDGETS_H__
|
||||
#define __WIDGETS_H__
|
||||
|
||||
/** \file blender/editors/interface/widgets/widgets.h
|
||||
* \ingroup edinterface
|
||||
*
|
||||
* \brief Blender widget API and internal functions
|
||||
*
|
||||
* Seems a bit overkill do have such an isolated module just for widget drawing but plan is to
|
||||
* use this for widget handling as well and basically make it a standalone blenwidget module
|
||||
*/
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
struct uiBut;
|
||||
struct uiWidgetType;
|
||||
|
||||
typedef enum {
|
||||
/* default */
|
||||
UI_WTYPE_REGULAR,
|
||||
|
||||
/* standard set */
|
||||
UI_WTYPE_LABEL,
|
||||
UI_WTYPE_TOGGLE,
|
||||
UI_WTYPE_CHECKBOX,
|
||||
UI_WTYPE_RADIO,
|
||||
UI_WTYPE_NUMBER,
|
||||
UI_WTYPE_SLIDER,
|
||||
UI_WTYPE_EXEC,
|
||||
UI_WTYPE_TOOLTIP,
|
||||
|
||||
/* strings */
|
||||
UI_WTYPE_NAME,
|
||||
UI_WTYPE_NAME_LINK,
|
||||
UI_WTYPE_POINTER_LINK,
|
||||
UI_WTYPE_FILENAME,
|
||||
|
||||
/* menus */
|
||||
UI_WTYPE_MENU_RADIO,
|
||||
UI_WTYPE_MENU_ICON_RADIO,
|
||||
UI_WTYPE_MENU_POINTER_LINK,
|
||||
UI_WTYPE_MENU_NODE_LINK,
|
||||
|
||||
UI_WTYPE_PULLDOWN,
|
||||
UI_WTYPE_MENU_LABEL,
|
||||
UI_WTYPE_MENU_ITEM,
|
||||
UI_WTYPE_MENU_ITEM_PREVIEW,
|
||||
UI_WTYPE_MENU_ITEM_RADIAL,
|
||||
UI_WTYPE_MENU_BACK,
|
||||
UI_WTYPE_SEARCH_BACK,
|
||||
|
||||
/* specials */
|
||||
UI_WTYPE_ICON,
|
||||
UI_WTYPE_EXTRA,
|
||||
UI_WTYPE_SWATCH,
|
||||
UI_WTYPE_RGB_PICKER,
|
||||
UI_WTYPE_UNITVEC,
|
||||
UI_WTYPE_COLORBAND,
|
||||
UI_WTYPE_HSV_CIRCLE,
|
||||
UI_WTYPE_HSV_CUBE,
|
||||
UI_WTYPE_HSV_VERT,
|
||||
UI_WTYPE_BOX,
|
||||
UI_WTYPE_SCROLL_BACK,
|
||||
UI_WTYPE_SCROLL_INNER,
|
||||
UI_WTYPE_LISTSCROLL, /* scroll widget within lists */
|
||||
UI_WTYPE_LISTITEM,
|
||||
UI_WTYPE_PROGRESSBAR,
|
||||
UI_WTYPE_LINK,
|
||||
UI_WTYPE_SEPARATOR,
|
||||
} uiWidgetTypeEnum;
|
||||
|
||||
/** uiWidgetType: for time being only for visual appearance,
|
||||
* later, a handling callback can be added too
|
||||
*/
|
||||
typedef struct uiWidgetType {
|
||||
/* pointer to theme color definition */
|
||||
uiWidgetColors *wcol_theme;
|
||||
uiWidgetStateColors *wcol_state;
|
||||
|
||||
/* converted colors for state */
|
||||
uiWidgetColors wcol;
|
||||
|
||||
struct uiWidgetDrawType *draw_type;
|
||||
} uiWidgetType;
|
||||
|
||||
typedef struct uiWidgetDrawType {
|
||||
void (*state)(struct uiWidgetType *, int state);
|
||||
void (*draw)(struct uiWidgetColors *, rcti *, int state, int roundboxalign);
|
||||
/* XXX uiBut and uiFontStyle shouldn't be needed/used at this level,
|
||||
* the needed data should be transferred using uiWidget API instead */
|
||||
void (*custom)(struct uiBut *, struct uiWidgetColors *, rcti *, int state, int roundboxalign);
|
||||
void (*text)(struct uiFontStyle *, struct uiWidgetColors *, struct uiBut *, rcti *, const char *str, const int iconid);
|
||||
} uiWidgetDrawType;
|
||||
|
||||
typedef struct uiWidgetDrawStyle {
|
||||
/* let's keep this in a nice alphabetical order! */
|
||||
uiWidgetDrawType *box,
|
||||
*checkbox,
|
||||
*colorband,
|
||||
*exec,
|
||||
*extra_mask,
|
||||
*filename,
|
||||
*hsv_circle,
|
||||
*hsv_cube,
|
||||
*hsv_vert,
|
||||
*icon,
|
||||
*label,
|
||||
*link,
|
||||
*listitem,
|
||||
*listscroll,
|
||||
*menu_back,
|
||||
*menu_icon_radio,
|
||||
*menu_item,
|
||||
*menu_item_preview,
|
||||
*menu_item_radial,
|
||||
*menu_label,
|
||||
*menu_node_link,
|
||||
*menu_pointer_link,
|
||||
*menu_radio,
|
||||
*name,
|
||||
*name_link,
|
||||
*number,
|
||||
*pointer_link,
|
||||
*progressbar,
|
||||
*pulldown,
|
||||
*radio,
|
||||
*regular,
|
||||
*rgb_picker,
|
||||
*scroll_back,
|
||||
*scroll_inner,
|
||||
*search_back,
|
||||
*separator,
|
||||
*slider,
|
||||
*swatch,
|
||||
*toggle,
|
||||
*tooltip,
|
||||
*unitvec;
|
||||
} uiWidgetDrawStyle;
|
||||
|
||||
|
||||
/* *** external API *** */
|
||||
|
||||
uiWidgetType *WidgetTypeInit(const uiWidgetTypeEnum type);
|
||||
void WidgetDraw(
|
||||
uiWidgetType *wt,
|
||||
uiFontStyle *fstyle, uiBut *but, rcti *rect,
|
||||
int state, int roundboxalign, const int iconid, const char *str,
|
||||
const bool use_text_blend);
|
||||
|
||||
|
||||
/* *** internal *** */
|
||||
|
||||
uiWidgetDrawStyle *widget_drawstyle_get(const short drawstyle_type);
|
||||
|
||||
/* draw-styles */
|
||||
extern struct uiWidgetDrawStyle WidgetStyle_Classic;
|
||||
|
||||
#endif /* __WIDGETS_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,879 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/interface/widgets/widgets_draw/widgets_draw.c
|
||||
* \ingroup edinterface
|
||||
*
|
||||
* \brief Shared low-level widget drawing functions
|
||||
*/
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
|
||||
#include "widgets_draw_intern.h" /* own include */
|
||||
|
||||
|
||||
|
||||
/* draw defines ************************************ */
|
||||
|
||||
static const float cornervec[WIDGET_CURVE_RESOLU][2] = {
|
||||
{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067},
|
||||
{0.55, 0.169}, {0.707, 0.293}, {0.831, 0.45},
|
||||
{0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}
|
||||
};
|
||||
|
||||
#define WIDGET_AA_JITTER 8
|
||||
static const float jit[WIDGET_AA_JITTER][2] = {
|
||||
{ 0.468813, -0.481430}, {-0.155755, -0.352820},
|
||||
{ 0.219306, -0.238501}, {-0.393286, -0.110949},
|
||||
{-0.024699, 0.013908}, { 0.343805, 0.147431},
|
||||
{-0.272855, 0.269918}, { 0.095909, 0.388710}
|
||||
};
|
||||
|
||||
static const float num_tria_vert[3][2] = {
|
||||
{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}
|
||||
};
|
||||
|
||||
static const unsigned int num_tria_face[1][3] = {
|
||||
{0, 1, 2}
|
||||
};
|
||||
|
||||
static const float check_tria_vert[6][2] = {
|
||||
{-0.578579, 0.253369}, {-0.392773, 0.412794}, {-0.004241, -0.328551},
|
||||
{-0.003001, 0.034320}, {1.055313, 0.864744}, {0.866408, 1.026895}
|
||||
};
|
||||
|
||||
static const unsigned int check_tria_face[4][3] = {
|
||||
{3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}
|
||||
};
|
||||
|
||||
static const float menu_tria_vert[6][2] = {
|
||||
{-0.33, 0.16}, {0.33, 0.16}, {0, 0.82},
|
||||
{0, -0.82}, {-0.33, -0.16}, {0.33, -0.16}
|
||||
};
|
||||
|
||||
static const float scroll_circle_vert[16][2] = {
|
||||
{0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
|
||||
{-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
|
||||
{-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
|
||||
{0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}
|
||||
};
|
||||
|
||||
static const unsigned int scroll_circle_face[14][3] = {
|
||||
{0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6},
|
||||
{6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}
|
||||
};
|
||||
|
||||
static const unsigned int menu_tria_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
|
||||
|
||||
|
||||
/* prepare drawing ********************************* */
|
||||
|
||||
/* roundbox stuff ************* */
|
||||
|
||||
/* this call has 1 extra arg to allow mask outline */
|
||||
void round_box__edges(uiWidgetDrawBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
|
||||
{
|
||||
float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
|
||||
float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
|
||||
float minxi = minx + U.pixelsize; /* boundbox inner */
|
||||
float maxxi = maxx - U.pixelsize;
|
||||
float minyi = miny + U.pixelsize;
|
||||
float maxyi = maxy - U.pixelsize;
|
||||
float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f; /* for uv, can divide by zero */
|
||||
float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
|
||||
int a, tot = 0, minsize;
|
||||
const int hnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT)) == (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT) ||
|
||||
(roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)) ? 1 : 2;
|
||||
const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) ||
|
||||
(roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
|
||||
|
||||
minsize = min_ii(BLI_rcti_size_x(rect) * hnum,
|
||||
BLI_rcti_size_y(rect) * vnum);
|
||||
|
||||
if (2.0f * rad > minsize)
|
||||
rad = 0.5f * minsize;
|
||||
|
||||
if (2.0f * (radi + 1.0f) > minsize)
|
||||
radi = 0.5f * minsize - U.pixelsize;
|
||||
|
||||
/* mult */
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
|
||||
veci[a][0] = radi * cornervec[a][0];
|
||||
veci[a][1] = radi * cornervec[a][1];
|
||||
vec[a][0] = rad * cornervec[a][0];
|
||||
vec[a][1] = rad * cornervec[a][1];
|
||||
}
|
||||
|
||||
/* corner left-bottom */
|
||||
if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0] = minxi + veci[a][1];
|
||||
wt->inner_v[tot][1] = minyi + radi - veci[a][0];
|
||||
|
||||
wt->outer_v[tot][0] = minx + vec[a][1];
|
||||
wt->outer_v[tot][1] = miny + rad - vec[a][0];
|
||||
|
||||
wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
|
||||
wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wt->inner_v[tot][0] = minxi;
|
||||
wt->inner_v[tot][1] = minyi;
|
||||
|
||||
wt->outer_v[tot][0] = minx;
|
||||
wt->outer_v[tot][1] = miny;
|
||||
|
||||
wt->inner_uv[tot][0] = 0.0f;
|
||||
wt->inner_uv[tot][1] = 0.0f;
|
||||
|
||||
tot++;
|
||||
}
|
||||
|
||||
/* corner right-bottom */
|
||||
if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0] = maxxi - radi + veci[a][0];
|
||||
wt->inner_v[tot][1] = minyi + veci[a][1];
|
||||
|
||||
wt->outer_v[tot][0] = maxx - rad + vec[a][0];
|
||||
wt->outer_v[tot][1] = miny + vec[a][1];
|
||||
|
||||
wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
|
||||
wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wt->inner_v[tot][0] = maxxi;
|
||||
wt->inner_v[tot][1] = minyi;
|
||||
|
||||
wt->outer_v[tot][0] = maxx;
|
||||
wt->outer_v[tot][1] = miny;
|
||||
|
||||
wt->inner_uv[tot][0] = 1.0f;
|
||||
wt->inner_uv[tot][1] = 0.0f;
|
||||
|
||||
tot++;
|
||||
}
|
||||
|
||||
wt->halfwayvert = tot;
|
||||
|
||||
/* corner right-top */
|
||||
if (roundboxalign & UI_CNR_TOP_RIGHT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0] = maxxi - veci[a][1];
|
||||
wt->inner_v[tot][1] = maxyi - radi + veci[a][0];
|
||||
|
||||
wt->outer_v[tot][0] = maxx - vec[a][1];
|
||||
wt->outer_v[tot][1] = maxy - rad + vec[a][0];
|
||||
|
||||
wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
|
||||
wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wt->inner_v[tot][0] = maxxi;
|
||||
wt->inner_v[tot][1] = maxyi;
|
||||
|
||||
wt->outer_v[tot][0] = maxx;
|
||||
wt->outer_v[tot][1] = maxy;
|
||||
|
||||
wt->inner_uv[tot][0] = 1.0f;
|
||||
wt->inner_uv[tot][1] = 1.0f;
|
||||
|
||||
tot++;
|
||||
}
|
||||
|
||||
/* corner left-top */
|
||||
if (roundboxalign & UI_CNR_TOP_LEFT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0] = minxi + radi - veci[a][0];
|
||||
wt->inner_v[tot][1] = maxyi - veci[a][1];
|
||||
|
||||
wt->outer_v[tot][0] = minx + rad - vec[a][0];
|
||||
wt->outer_v[tot][1] = maxy - vec[a][1];
|
||||
|
||||
wt->inner_uv[tot][0] = facxi * (wt->inner_v[tot][0] - minxi);
|
||||
wt->inner_uv[tot][1] = facyi * (wt->inner_v[tot][1] - minyi);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wt->inner_v[tot][0] = minxi;
|
||||
wt->inner_v[tot][1] = maxyi;
|
||||
|
||||
wt->outer_v[tot][0] = minx;
|
||||
wt->outer_v[tot][1] = maxy;
|
||||
|
||||
wt->inner_uv[tot][0] = 0.0f;
|
||||
wt->inner_uv[tot][1] = 1.0f;
|
||||
|
||||
tot++;
|
||||
}
|
||||
|
||||
BLI_assert(tot <= WIDGET_SIZE_MAX);
|
||||
|
||||
wt->totvert = tot;
|
||||
}
|
||||
|
||||
void widget_drawbase_roundboxedges_set(uiWidgetDrawBase *wt, int roundboxalign, const rcti *rect, float rad)
|
||||
{
|
||||
round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
|
||||
}
|
||||
|
||||
/* prepares shade colors */
|
||||
static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
|
||||
{
|
||||
coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
|
||||
coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255);
|
||||
coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255);
|
||||
coltop[3] = color[3];
|
||||
|
||||
coldown[0] = CLAMPIS(color[0] + shadedown, 0, 255);
|
||||
coldown[1] = CLAMPIS(color[1] + shadedown, 0, 255);
|
||||
coldown[2] = CLAMPIS(color[2] + shadedown, 0, 255);
|
||||
coldown[3] = color[3];
|
||||
}
|
||||
|
||||
static void round_box_shade_col4_r(unsigned char r_col[4], const char col1[4], const char col2[4], const float fac)
|
||||
{
|
||||
const int faci = FTOCHAR(fac);
|
||||
const int facm = 255 - faci;
|
||||
|
||||
r_col[0] = (faci * col1[0] + facm * col2[0]) / 256;
|
||||
r_col[1] = (faci * col1[1] + facm * col2[1]) / 256;
|
||||
r_col[2] = (faci * col1[2] + facm * col2[2]) / 256;
|
||||
r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
|
||||
}
|
||||
|
||||
|
||||
/* triangle stuff ************* */
|
||||
|
||||
static void widget_verts_to_triangle_strip(uiWidgetDrawBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < totvert; a++) {
|
||||
copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
|
||||
copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
|
||||
}
|
||||
copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
|
||||
copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
|
||||
}
|
||||
|
||||
static void widget_verts_to_triangle_strip_open(uiWidgetDrawBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2])
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < totvert; a++) {
|
||||
triangle_strip[a * 2][0] = wtb->outer_v[a][0];
|
||||
triangle_strip[a * 2][1] = wtb->outer_v[a][1];
|
||||
triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
|
||||
triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* based on button rect, return scaled array of triangles */
|
||||
static void widget_drawbase_tria_ex(
|
||||
uiWidgetDrawBaseTrias *tria, const rcti *rect, float triasize, char where,
|
||||
/* input data */
|
||||
const float verts[][2], const int verts_tot,
|
||||
const unsigned int tris[][3], const int tris_tot)
|
||||
{
|
||||
float centx, centy, sizex, sizey, minsize;
|
||||
int a, i1 = 0, i2 = 1;
|
||||
|
||||
minsize = min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
|
||||
|
||||
/* center position and size */
|
||||
centx = (float)rect->xmin + 0.4f * minsize;
|
||||
centy = (float)rect->ymin + 0.5f * minsize;
|
||||
sizex = sizey = -0.5f * triasize * minsize;
|
||||
|
||||
if (where == 'r') {
|
||||
centx = (float)rect->xmax - 0.4f * minsize;
|
||||
sizex = -sizex;
|
||||
}
|
||||
else if (where == 't') {
|
||||
centy = (float)rect->ymax - 0.5f * minsize;
|
||||
sizey = -sizey;
|
||||
i2 = 0; i1 = 1;
|
||||
}
|
||||
else if (where == 'b') {
|
||||
sizex = -sizex;
|
||||
i2 = 0; i1 = 1;
|
||||
}
|
||||
|
||||
for (a = 0; a < verts_tot; a++) {
|
||||
tria->vec[a][0] = sizex * verts[a][i1] + centx;
|
||||
tria->vec[a][1] = sizey * verts[a][i2] + centy;
|
||||
}
|
||||
|
||||
tria->tot = tris_tot;
|
||||
tria->index = tris;
|
||||
}
|
||||
|
||||
void widget_drawbase_num_tria(uiWidgetDrawBaseTrias *tria, const rcti *rect, float triasize, char where)
|
||||
{
|
||||
widget_drawbase_tria_ex(
|
||||
tria, rect, triasize, where,
|
||||
num_tria_vert, ARRAY_SIZE(num_tria_vert),
|
||||
num_tria_face, ARRAY_SIZE(num_tria_face));
|
||||
}
|
||||
|
||||
void widget_drawbase_menu_trias(uiWidgetDrawBaseTrias *tria, const rcti *rect)
|
||||
{
|
||||
float centx, centy, size;
|
||||
int a;
|
||||
|
||||
/* center position and size */
|
||||
centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
|
||||
centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
|
||||
size = 0.4f * BLI_rcti_size_y(rect);
|
||||
|
||||
for (a = 0; a < 6; a++) {
|
||||
tria->vec[a][0] = size * menu_tria_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * menu_tria_vert[a][1] + centy;
|
||||
}
|
||||
|
||||
tria->tot = 2;
|
||||
tria->index = menu_tria_face;
|
||||
}
|
||||
|
||||
void widget_drawbase_check_trias(uiWidgetDrawBaseTrias *tria, const rcti *rect)
|
||||
{
|
||||
float centx, centy, size;
|
||||
int a;
|
||||
|
||||
/* center position and size */
|
||||
centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
|
||||
centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
|
||||
size = 0.5f * BLI_rcti_size_y(rect);
|
||||
|
||||
for (a = 0; a < 6; a++) {
|
||||
tria->vec[a][0] = size * check_tria_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * check_tria_vert[a][1] + centy;
|
||||
}
|
||||
|
||||
tria->tot = 4;
|
||||
tria->index = check_tria_face;
|
||||
}
|
||||
|
||||
void widget_drawbase_scroll_circle(uiWidgetDrawBaseTrias *tria, const rcti *rect, float triasize, char where)
|
||||
{
|
||||
widget_drawbase_tria_ex(
|
||||
tria, rect, triasize, where,
|
||||
scroll_circle_vert, ARRAY_SIZE(scroll_circle_vert),
|
||||
scroll_circle_face, ARRAY_SIZE(scroll_circle_face));
|
||||
}
|
||||
|
||||
/* menu backdrop stuff ******** */
|
||||
|
||||
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
|
||||
/* return tot */
|
||||
static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
|
||||
{
|
||||
float vec[WIDGET_CURVE_RESOLU][2];
|
||||
float minx, miny, maxx, maxy;
|
||||
int a, tot = 0;
|
||||
|
||||
rad += step;
|
||||
|
||||
if (2.0f * rad > BLI_rcti_size_y(rect))
|
||||
rad = 0.5f * BLI_rcti_size_y(rect);
|
||||
|
||||
minx = rect->xmin - step;
|
||||
miny = rect->ymin - step;
|
||||
maxx = rect->xmax + step;
|
||||
maxy = rect->ymax + step;
|
||||
|
||||
/* mult */
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
|
||||
vec[a][0] = rad * cornervec[a][0];
|
||||
vec[a][1] = rad * cornervec[a][1];
|
||||
}
|
||||
|
||||
/* start with left-top, anti clockwise */
|
||||
if (roundboxalign & UI_CNR_TOP_LEFT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = minx + rad - vec[a][0];
|
||||
vert[tot][1] = maxy - vec[a][1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = minx;
|
||||
vert[tot][1] = maxy;
|
||||
}
|
||||
}
|
||||
|
||||
if (roundboxalign & UI_CNR_BOTTOM_LEFT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = minx + vec[a][1];
|
||||
vert[tot][1] = miny + rad - vec[a][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = minx;
|
||||
vert[tot][1] = miny;
|
||||
}
|
||||
}
|
||||
|
||||
if (roundboxalign & UI_CNR_BOTTOM_RIGHT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = maxx - rad + vec[a][0];
|
||||
vert[tot][1] = miny + vec[a][1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = maxx;
|
||||
vert[tot][1] = miny;
|
||||
}
|
||||
}
|
||||
|
||||
if (roundboxalign & UI_CNR_TOP_RIGHT) {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = maxx - vec[a][1];
|
||||
vert[tot][1] = maxy - rad + vec[a][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (a = 0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0] = maxx;
|
||||
vert[tot][1] = maxy;
|
||||
}
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
|
||||
/* actual drawing ********************************** */
|
||||
|
||||
/* outside of rect, rad to left/bottom/right */
|
||||
void widget_drawbase_softshadow(const rcti *rect, int roundboxalign, const float radin)
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
uiWidgetDrawBase wtb;
|
||||
rcti rect1 = *rect;
|
||||
float alphastep;
|
||||
int step, totvert;
|
||||
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
|
||||
const float radout = UI_ThemeMenuShadowWidth();
|
||||
|
||||
/* disabled shadow */
|
||||
if (radout == 0.0f)
|
||||
return;
|
||||
|
||||
/* prevent tooltips to not show round shadow */
|
||||
if (radout > 0.2f * BLI_rcti_size_y(&rect1))
|
||||
rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
|
||||
else
|
||||
rect1.ymax -= radout;
|
||||
|
||||
/* inner part */
|
||||
totvert = round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
|
||||
|
||||
/* we draw a number of increasing size alpha quad strips */
|
||||
alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for (step = 1; step <= (int)radout; step++) {
|
||||
float expfac = sqrtf(step / radout);
|
||||
|
||||
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
|
||||
|
||||
glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
|
||||
|
||||
widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
static void widget_trias_draw(uiWidgetDrawBaseTrias *tria)
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, tria->vec);
|
||||
glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void widget_drawbase_outline(uiWidgetDrawBase *wtb)
|
||||
{
|
||||
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
|
||||
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void widget_drawbase_draw(uiWidgetDrawBase *wtb, uiWidgetColors *wcol)
|
||||
{
|
||||
int j, a;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
/* backdrop non AA */
|
||||
if (wtb->draw_inner) {
|
||||
if (wcol->shaded == 0) {
|
||||
if (wcol->alpha_check) {
|
||||
float inner_v_half[WIDGET_SIZE_MAX][2];
|
||||
float x_mid = 0.0f; /* used for dumb clamping of values */
|
||||
|
||||
/* dark checkers */
|
||||
glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
|
||||
/* light checkers */
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
|
||||
glPolygonStipple(stipple_checker_8px);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
|
||||
/* alpha fill */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glColor4ubv((unsigned char *)wcol->inner);
|
||||
|
||||
for (a = 0; a < wtb->totvert; a++) {
|
||||
x_mid += wtb->inner_v[a][0];
|
||||
}
|
||||
x_mid /= wtb->totvert;
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
|
||||
/* 1/2 solid color */
|
||||
glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
|
||||
|
||||
for (a = 0; a < wtb->totvert; a++) {
|
||||
inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid);
|
||||
inner_v_half[a][1] = wtb->inner_v[a][1];
|
||||
}
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
else {
|
||||
/* simple fill */
|
||||
glColor4ubv((unsigned char *)wcol->inner);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char col1[4], col2[4];
|
||||
unsigned char col_array[WIDGET_SIZE_MAX * 4];
|
||||
unsigned char *col_pt = col_array;
|
||||
|
||||
shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
|
||||
round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
}
|
||||
|
||||
/* for each AA step */
|
||||
if (wtb->draw_outline) {
|
||||
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
|
||||
float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
|
||||
|
||||
const unsigned char tcol[4] = {wcol->outline[0],
|
||||
wcol->outline[1],
|
||||
wcol->outline[2],
|
||||
wcol->outline[3] / WIDGET_AA_JITTER};
|
||||
|
||||
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
|
||||
|
||||
if (wtb->draw_emboss) {
|
||||
widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for (j = 0; j < WIDGET_AA_JITTER; j++) {
|
||||
unsigned char emboss[4];
|
||||
|
||||
glTranslatef(jit[j][0], jit[j][1], 0.0f);
|
||||
|
||||
/* outline */
|
||||
glColor4ubv(tcol);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
|
||||
|
||||
/* emboss bottom shadow */
|
||||
if (wtb->draw_emboss) {
|
||||
UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
|
||||
|
||||
if (emboss[3]) {
|
||||
glColor4ubv(emboss);
|
||||
glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
|
||||
}
|
||||
}
|
||||
|
||||
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
/* decoration */
|
||||
if (wtb->tria1.tot || wtb->tria2.tot) {
|
||||
const unsigned char tcol[4] = {wcol->item[0],
|
||||
wcol->item[1],
|
||||
wcol->item[2],
|
||||
(unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)};
|
||||
|
||||
/* for each AA step */
|
||||
for (j = 0; j < WIDGET_AA_JITTER; j++) {
|
||||
glTranslatef(jit[j][0], jit[j][1], 0.0f);
|
||||
|
||||
if (wtb->tria1.tot) {
|
||||
glColor4ubv(tcol);
|
||||
widget_trias_draw(&wtb->tria1);
|
||||
}
|
||||
if (wtb->tria2.tot) {
|
||||
glColor4ubv(tcol);
|
||||
widget_trias_draw(&wtb->tria2);
|
||||
}
|
||||
|
||||
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void ui_hsv_cursor(float x, float y)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0.0f);
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
copy_v2_fl2(v, x1 + halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y1 + height);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1 - halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
if (fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
}
|
||||
else {
|
||||
glPolygonMode(GL_FRONT, GL_LINE);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
copy_v2_fl2(v, x1 + halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y1 + height);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1 - halfwidth, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
if (fill) {
|
||||
glDisable(GL_POLYGON_SMOOTH);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill)
|
||||
{
|
||||
float v[2];
|
||||
|
||||
if (fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
else {
|
||||
glPolygonMode(GL_FRONT, GL_LINE);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
copy_v2_fl2(v, x1, y1);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x1, y2);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x2, y2);
|
||||
glVertex2fv(v);
|
||||
copy_v2_fl2(v, x2, y1);
|
||||
glVertex2fv(v);
|
||||
glEnd();
|
||||
|
||||
if (!fill) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_draw_colorband_handle(
|
||||
const rcti *rect, float x,
|
||||
const float rgb[3], struct ColorManagedDisplay *display,
|
||||
bool active)
|
||||
{
|
||||
const float sizey = BLI_rcti_size_y(rect);
|
||||
const float min_width = 3.0f;
|
||||
float half_width, height, y1, y2;
|
||||
float colf[3] = {UNPACK3(rgb)};
|
||||
|
||||
half_width = floorf(sizey / 3.5f);
|
||||
height = half_width * 1.4f;
|
||||
|
||||
y1 = rect->ymin + (sizey * 0.16f);
|
||||
y2 = rect->ymax;
|
||||
|
||||
/* align to pixels */
|
||||
x = floorf(x + 0.5f);
|
||||
y1 = floorf(y1 + 0.5f);
|
||||
|
||||
if (active || half_width < min_width) {
|
||||
glBegin(GL_LINES);
|
||||
glColor3ub(0, 0, 0);
|
||||
glVertex2f(x, y1);
|
||||
glVertex2f(x, y2);
|
||||
glEnd();
|
||||
setlinestyle(active ? 2 : 1);
|
||||
glBegin(GL_LINES);
|
||||
glColor3ub(200, 200, 200);
|
||||
glVertex2f(x, y1);
|
||||
glVertex2f(x, y2);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
|
||||
/* hide handles when zoomed out too far */
|
||||
if (half_width < min_width) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* shift handle down */
|
||||
y1 = y1 - half_width;
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false);
|
||||
|
||||
/* draw all triangles blended */
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
|
||||
|
||||
if (active)
|
||||
glColor3ub(196, 196, 196);
|
||||
else
|
||||
glColor3ub(96, 96, 96);
|
||||
ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
|
||||
|
||||
if (active)
|
||||
glColor3ub(255, 255, 255);
|
||||
else
|
||||
glColor3ub(128, 128, 128);
|
||||
ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1));
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glColor3ub(128, 128, 128);
|
||||
ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
|
||||
|
||||
if (display) {
|
||||
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
|
||||
}
|
||||
|
||||
glColor3fv(colf);
|
||||
ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __WIDGETS_DRAW_INTERN_H__
|
||||
#define __WIDGETS_DRAW_INTERN_H__
|
||||
|
||||
/** \file blender/editors/interface/widgets/widgets_draw/widgets_draw_intern.h
|
||||
* \ingroup edinterface
|
||||
*
|
||||
* \brief Blender widget drawing module
|
||||
*/
|
||||
|
||||
/* Struct Declarations */
|
||||
|
||||
struct uiBut;
|
||||
struct uiFontStyle;
|
||||
struct uiWidgetType;
|
||||
struct rcti;
|
||||
struct ColorManagedDisplay;
|
||||
|
||||
/* ************** widget base functions ************** */
|
||||
/**
|
||||
* - in: roundbox codes for corner types and radius
|
||||
* - return: array of `[size][2][x, y]` points, the edges of the roundbox, + UV coords
|
||||
*
|
||||
* - draw black box with alpha 0 on exact button boundbox
|
||||
* - for every AA step:
|
||||
* - draw the inner part for a round filled box, with color blend codes or texture coords
|
||||
* - draw outline in outline color
|
||||
* - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow
|
||||
* - draw extra decorations
|
||||
* - draw background color box with alpha 1 on exact button boundbox
|
||||
*/
|
||||
|
||||
/* fill this struct with polygon info to draw AA'ed */
|
||||
/* it has outline, back, and two optional tria meshes */
|
||||
|
||||
/* max as used by round_box__edges */
|
||||
#define WIDGET_CURVE_RESOLU 9
|
||||
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
|
||||
|
||||
typedef struct uiWidgetDrawBaseTrias {
|
||||
unsigned int tot;
|
||||
|
||||
float vec[16][2];
|
||||
const unsigned int (*index)[3];
|
||||
} uiWidgetDrawBaseTrias;
|
||||
|
||||
typedef struct uiWidgetDrawBase {
|
||||
int totvert, halfwayvert;
|
||||
float outer_v[WIDGET_SIZE_MAX][2];
|
||||
float inner_v[WIDGET_SIZE_MAX][2];
|
||||
float inner_uv[WIDGET_SIZE_MAX][2];
|
||||
|
||||
bool draw_inner, draw_outline, draw_emboss, draw_shadedir;
|
||||
|
||||
uiWidgetDrawBaseTrias tria1;
|
||||
uiWidgetDrawBaseTrias tria2;
|
||||
} uiWidgetDrawBase;
|
||||
|
||||
|
||||
/* widgets_draw.c - shared low-level drawing functions */
|
||||
|
||||
void widget_drawbase_roundboxedges_set(uiWidgetDrawBase *wt, int roundboxalign, const rcti *rect, float rad);
|
||||
void round_box__edges(uiWidgetDrawBase *wt, int roundboxalign, const rcti *rect, float rad, float radi);
|
||||
void widget_drawbase_num_tria(uiWidgetDrawBaseTrias *tria, const rcti *rect, float triasize, char where);
|
||||
void widget_drawbase_menu_trias(uiWidgetDrawBaseTrias *tria, const rcti *rect);
|
||||
void widget_drawbase_check_trias(uiWidgetDrawBaseTrias *tria, const rcti *rect);
|
||||
void widget_drawbase_softshadow(const rcti *rect, int roundboxalign, const float radin);
|
||||
void widget_drawbase_draw(uiWidgetDrawBase *wtb, struct uiWidgetColors *wcol);
|
||||
void widget_drawbase_outline(uiWidgetDrawBase *wtb);
|
||||
void widget_drawbase_scroll_circle(uiWidgetDrawBaseTrias *tria, const rcti *rect, float triasize, char where);
|
||||
void ui_hsv_cursor(float x, float y);
|
||||
void ui_draw_colorband_handle(
|
||||
const rcti *rect, float x,
|
||||
const float rgb[3], struct ColorManagedDisplay *display,
|
||||
bool active);
|
||||
|
||||
|
||||
/* widgets_draw_text.c - shared low-level text formatting/drawing functions */
|
||||
|
||||
void widget_draw_text_icon(
|
||||
uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but,
|
||||
rcti *rect, const char *str, const int iconid);
|
||||
void widget_draw_text_preview_item(
|
||||
uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *UNUSED(but),
|
||||
rcti *rect, const char *str, const int iconid);
|
||||
|
||||
#endif /* __WIDGETS_DRAW_INTERN_H__ */
|
||||
|
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/interface/widgets/widgets_draw/widgets_draw_text.c
|
||||
* \ingroup edinterface
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
|
||||
#include "../interface_intern.h" /* XXX currently needed, but not so nice on this level */
|
||||
|
||||
|
||||
#include "widgets_draw_intern.h"
|
||||
|
||||
|
||||
|
||||
#define UI_TEXT_CLIP_MARGIN (0.25f * U.widget_unit / but->block->aspect)
|
||||
|
||||
/* icons are 80% of height of button (16 pixels inside 20 height) */
|
||||
#define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
|
||||
|
||||
|
||||
#define PREVIEW_PAD 4
|
||||
|
||||
static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
|
||||
{
|
||||
int w, h, size;
|
||||
|
||||
if (icon == ICON_NONE)
|
||||
return;
|
||||
|
||||
w = BLI_rcti_size_x(rect);
|
||||
h = BLI_rcti_size_y(rect);
|
||||
size = MIN2(w, h);
|
||||
size -= PREVIEW_PAD * 2; /* padding */
|
||||
|
||||
if (size > 0) {
|
||||
int x = rect->xmin + w / 2 - size / 2;
|
||||
int y = rect->ymin + h / 2 - size / 2;
|
||||
|
||||
UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
|
||||
}
|
||||
}
|
||||
|
||||
void widget_draw_text_preview_item(
|
||||
uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *UNUSED(but),
|
||||
rcti *rect, const char *str, const int iconid)
|
||||
{
|
||||
rcti trect = *rect;
|
||||
const float text_size = UI_UNIT_Y;
|
||||
float font_dims[2] = {0.0f, 0.0f};
|
||||
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect->ymin += text_size;
|
||||
glEnable(GL_BLEND);
|
||||
widget_draw_preview(iconid, 1.0f, rect);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
BLF_width_and_height(fstyle->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
|
||||
|
||||
/* text rect */
|
||||
trect.xmin += 0;
|
||||
trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
|
||||
trect.ymin += U.widget_unit / 2;
|
||||
trect.ymax = trect.ymin + font_dims[1];
|
||||
if (trect.xmax > rect->xmax - PREVIEW_PAD)
|
||||
trect.xmax = rect->xmax - PREVIEW_PAD;
|
||||
|
||||
{
|
||||
char drawstr[UI_MAX_DRAW_STR];
|
||||
const float okwidth = (float)BLI_rcti_size_x(&trect);
|
||||
const size_t max_len = sizeof(drawstr);
|
||||
const float minwidth = (float)(UI_DPI_ICON_SIZE);
|
||||
|
||||
BLI_strncpy(drawstr, str, sizeof(drawstr));
|
||||
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
|
||||
|
||||
glColor4ubv((unsigned char *)wcol->text);
|
||||
UI_fontstyle_draw(fstyle, &trect, drawstr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ui_but_draw_menu_icon(const uiBut *but)
|
||||
{
|
||||
return (but->flag & UI_BUT_ICON_SUBMENU) && (but->dt == UI_EMBOSS_PULLDOWN);
|
||||
}
|
||||
|
||||
/* icons have been standardized... and this call draws in untransformed coordinates */
|
||||
|
||||
static void widget_draw_icon(
|
||||
const uiBut *but, BIFIconID icon, float alpha, const rcti *rect,
|
||||
const bool show_menu_icon)
|
||||
{
|
||||
float xs = 0.0f, ys = 0.0f;
|
||||
float aspect, height;
|
||||
|
||||
if (but->flag & UI_BUT_ICON_PREVIEW) {
|
||||
glEnable(GL_BLEND);
|
||||
widget_draw_preview(icon, alpha, rect);
|
||||
glDisable(GL_BLEND);
|
||||
return;
|
||||
}
|
||||
|
||||
/* this icon doesn't need draw... */
|
||||
if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) return;
|
||||
|
||||
aspect = but->block->aspect / UI_DPI_FAC;
|
||||
height = ICON_DEFAULT_HEIGHT / aspect;
|
||||
|
||||
/* calculate blend color */
|
||||
if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_ROW, UI_BTYPE_TOGGLE_N, UI_BTYPE_LISTROW)) {
|
||||
if (but->flag & UI_SELECT) {}
|
||||
else if (but->flag & UI_ACTIVE) {}
|
||||
else alpha = 0.5f;
|
||||
}
|
||||
|
||||
/* extra feature allows more alpha blending */
|
||||
if ((but->type == UI_BTYPE_LABEL) && but->a1 == 1.0f)
|
||||
alpha *= but->a2;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
if (icon && icon != ICON_BLANK1) {
|
||||
float ofs = 1.0f / aspect;
|
||||
|
||||
if (but->drawflag & UI_BUT_ICON_LEFT) {
|
||||
if (but->block->flag & UI_BLOCK_LOOP) {
|
||||
if (but->type == UI_BTYPE_SEARCH_MENU)
|
||||
xs = rect->xmin + 4.0f * ofs;
|
||||
else
|
||||
xs = rect->xmin + ofs;
|
||||
}
|
||||
else {
|
||||
xs = rect->xmin + 4.0f * ofs;
|
||||
}
|
||||
ys = (rect->ymin + rect->ymax - height) / 2.0f;
|
||||
}
|
||||
else {
|
||||
xs = (rect->xmin + rect->xmax - height) / 2.0f;
|
||||
ys = (rect->ymin + rect->ymax - height) / 2.0f;
|
||||
}
|
||||
|
||||
/* force positions to integers, for zoom levels near 1. draws icons crisp. */
|
||||
if (aspect > 0.95f && aspect < 1.05f) {
|
||||
xs = (int)(xs + 0.1f);
|
||||
ys = (int)(ys + 0.1f);
|
||||
}
|
||||
|
||||
/* to indicate draggable */
|
||||
if (but->dragpoin && (but->flag & UI_ACTIVE)) {
|
||||
float rgb[3] = {1.25f, 1.25f, 1.25f};
|
||||
UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb);
|
||||
}
|
||||
else
|
||||
UI_icon_draw_aspect(xs, ys, icon, aspect, alpha);
|
||||
}
|
||||
|
||||
if (show_menu_icon) {
|
||||
xs = rect->xmax - UI_DPI_ICON_SIZE - aspect;
|
||||
ys = (rect->ymin + rect->ymax - height) / 2.0f;
|
||||
|
||||
UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void ui_text_clip_give_prev_off(uiBut *but, const char *str)
|
||||
{
|
||||
const char *prev_utf8 = BLI_str_find_prev_char_utf8(str, str + but->ofs);
|
||||
int bytes = str + but->ofs - prev_utf8;
|
||||
|
||||
but->ofs -= bytes;
|
||||
}
|
||||
|
||||
static void ui_text_clip_give_next_off(uiBut *but, const char *str)
|
||||
{
|
||||
const char *next_utf8 = BLI_str_find_next_char_utf8(str + but->ofs, NULL);
|
||||
int bytes = next_utf8 - (str + but->ofs);
|
||||
|
||||
but->ofs += bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper.
|
||||
* This func assumes things like kerning handling have already been handled!
|
||||
* Return the length of modified (right-clipped + ellipsis) string.
|
||||
*/
|
||||
static void ui_text_clip_right_ex(
|
||||
uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth,
|
||||
const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len)
|
||||
{
|
||||
float tmp;
|
||||
int l_end;
|
||||
|
||||
BLI_assert(str[0]);
|
||||
|
||||
/* If the trailing ellipsis takes more than 20% of all available width, just cut the string
|
||||
* (as using the ellipsis would remove even more useful chars, and we cannot show much already!).
|
||||
*/
|
||||
if (sep_strwidth / okwidth > 0.2f) {
|
||||
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
|
||||
str[l_end] = '\0';
|
||||
if (r_final_len) {
|
||||
*r_final_len = (size_t)l_end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp);
|
||||
memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */
|
||||
if (r_final_len) {
|
||||
*r_final_len = (size_t)(l_end + sep_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cut off the middle of the text to fit into the given width.
|
||||
* Note in case this middle clipping would just remove a few chars, it rather clips right, which is more readable.
|
||||
* If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful
|
||||
* for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
|
||||
*/
|
||||
float UI_text_clip_middle_ex(
|
||||
uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
|
||||
const size_t max_len, const char rpart_sep)
|
||||
{
|
||||
float strwidth;
|
||||
|
||||
/* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits!
|
||||
* Better to have a small piece of the last char cut out, than two remaining chars replaced by an allipsis... */
|
||||
okwidth += 1.0f + UI_DPI_FAC;
|
||||
|
||||
BLI_assert(str[0]);
|
||||
|
||||
/* need to set this first */
|
||||
UI_fontstyle_set(fstyle);
|
||||
|
||||
if (fstyle->kerning == 1) { /* for BLF_width */
|
||||
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
|
||||
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
|
||||
|
||||
if ((okwidth > 0.0f) && (strwidth > okwidth)) {
|
||||
/* utf8 ellipsis '...', some compilers complain */
|
||||
const char sep[] = {0xe2, 0x80, 0xa6, 0x0};
|
||||
const int sep_len = sizeof(sep) - 1;
|
||||
const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
|
||||
float parts_strwidth;
|
||||
size_t l_end;
|
||||
|
||||
char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR];
|
||||
float rpart_width = 0.0f;
|
||||
size_t rpart_len = 0;
|
||||
size_t final_lpart_len;
|
||||
|
||||
if (rpart_sep) {
|
||||
rpart = strrchr(str, rpart_sep);
|
||||
|
||||
if (rpart) {
|
||||
rpart_len = strlen(rpart);
|
||||
rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len);
|
||||
okwidth -= rpart_width;
|
||||
strwidth -= rpart_width;
|
||||
|
||||
if (okwidth < 0.0f) {
|
||||
/* Not enough place for actual label, just display protected right part.
|
||||
* Here just for safety, should never happen in real life! */
|
||||
memmove(str, rpart, rpart_len + 1);
|
||||
rpart = NULL;
|
||||
okwidth += rpart_width;
|
||||
strwidth = rpart_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parts_strwidth = (okwidth - sep_strwidth) / 2.0f;
|
||||
|
||||
if (rpart) {
|
||||
strcpy(rpart_buf, rpart);
|
||||
*rpart = '\0';
|
||||
rpart = rpart_buf;
|
||||
}
|
||||
|
||||
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
|
||||
if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) {
|
||||
/* If we really have no place, or we would clip a very small piece of string in the middle,
|
||||
* only show start of string.
|
||||
*/
|
||||
ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
|
||||
}
|
||||
else {
|
||||
size_t r_offset, r_len;
|
||||
|
||||
r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width);
|
||||
r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */
|
||||
|
||||
if (l_end + sep_len + r_len + rpart_len > max_len) {
|
||||
/* Corner case, the str already takes all available mem, and the ellipsis chars would actually
|
||||
* add more chars...
|
||||
* Better to just trim one or two letters to the right in this case...
|
||||
* Note: with a single-char ellipsis, this should never happen! But better be safe here...
|
||||
*/
|
||||
ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
|
||||
}
|
||||
else {
|
||||
memmove(str + l_end + sep_len, str + r_offset, r_len);
|
||||
memcpy(str + l_end, sep, sep_len);
|
||||
final_lpart_len = (size_t)(l_end + sep_len + r_len - 1); /* -1 to remove trailing '\0'! */
|
||||
}
|
||||
}
|
||||
|
||||
if (rpart) {
|
||||
/* Add back preserved right part to our shorten str. */
|
||||
memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */
|
||||
}
|
||||
|
||||
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
|
||||
}
|
||||
|
||||
if (fstyle->kerning == 1) {
|
||||
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
|
||||
return strwidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around UI_text_clip_middle_ex.
|
||||
*/
|
||||
static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
|
||||
{
|
||||
/* No margin for labels! */
|
||||
const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
|
||||
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
|
||||
const size_t max_len = sizeof(but->drawstr);
|
||||
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
|
||||
|
||||
but->ofs = 0;
|
||||
but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep.
|
||||
* Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
|
||||
*/
|
||||
static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
|
||||
{
|
||||
/* No margin for labels! */
|
||||
const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
|
||||
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
|
||||
const size_t max_len = sizeof(but->drawstr);
|
||||
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
|
||||
|
||||
but->ofs = 0;
|
||||
but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cut off the text, taking into account the cursor location (text display while editing).
|
||||
*/
|
||||
static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
|
||||
{
|
||||
const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
|
||||
const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
|
||||
|
||||
BLI_assert(but->editstr && but->pos >= 0);
|
||||
|
||||
/* need to set this first */
|
||||
UI_fontstyle_set(fstyle);
|
||||
|
||||
if (fstyle->kerning == 1) /* for BLF_width */
|
||||
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
|
||||
/* define ofs dynamically */
|
||||
if (but->ofs > but->pos)
|
||||
but->ofs = but->pos;
|
||||
|
||||
if (BLF_width(fstyle->uifont_id, but->editstr, INT_MAX) <= okwidth)
|
||||
but->ofs = 0;
|
||||
|
||||
but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, INT_MAX);
|
||||
|
||||
if (but->strwidth > okwidth) {
|
||||
int len = strlen(but->editstr);
|
||||
|
||||
while (but->strwidth > okwidth) {
|
||||
float width;
|
||||
|
||||
/* string position of cursor */
|
||||
width = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, (but->pos - but->ofs));
|
||||
|
||||
/* if cursor is at 20 pixels of right side button we clip left */
|
||||
if (width > okwidth - 20) {
|
||||
ui_text_clip_give_next_off(but, but->editstr);
|
||||
}
|
||||
else {
|
||||
int bytes;
|
||||
/* shift string to the left */
|
||||
if (width < 20 && but->ofs > 0)
|
||||
ui_text_clip_give_prev_off(but, but->editstr);
|
||||
bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->editstr, but->editstr + len));
|
||||
if (bytes == -1)
|
||||
bytes = 1;
|
||||
len -= bytes;
|
||||
}
|
||||
|
||||
but->strwidth = BLF_width(fstyle->uifont_id, but->editstr + but->ofs, len - but->ofs);
|
||||
|
||||
if (but->strwidth < 10) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstyle->kerning == 1) {
|
||||
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cut off the end of text to fit into the width of \a rect.
|
||||
*
|
||||
* \note deals with ': ' especially for number buttons
|
||||
*/
|
||||
static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
|
||||
{
|
||||
const int border = UI_TEXT_CLIP_MARGIN + 1;
|
||||
const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
|
||||
char *cpoin = NULL;
|
||||
int drawstr_len = strlen(but->drawstr);
|
||||
const char *cpend = but->drawstr + drawstr_len;
|
||||
|
||||
/* need to set this first */
|
||||
UI_fontstyle_set(fstyle);
|
||||
|
||||
if (fstyle->kerning == 1) /* for BLF_width */
|
||||
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
|
||||
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
|
||||
but->ofs = 0;
|
||||
|
||||
/* First shorten num-buttons eg,
|
||||
* Translucency: 0.000
|
||||
* becomes
|
||||
* Trans: 0.000
|
||||
*/
|
||||
|
||||
/* find the space after ':' separator */
|
||||
cpoin = strrchr(but->drawstr, ':');
|
||||
|
||||
if (cpoin && (cpoin < cpend - 2)) {
|
||||
char *cp2 = cpoin;
|
||||
|
||||
/* chop off the leading text, starting from the right */
|
||||
while (but->strwidth > okwidth && cp2 > but->drawstr) {
|
||||
const char *prev_utf8 = BLI_str_find_prev_char_utf8(but->drawstr, cp2);
|
||||
int bytes = cp2 - prev_utf8;
|
||||
|
||||
/* shift the text after and including cp2 back by 1 char, +1 to include null terminator */
|
||||
memmove(cp2 - bytes, cp2, drawstr_len + 1);
|
||||
cp2 -= bytes;
|
||||
|
||||
drawstr_len -= bytes;
|
||||
// BLI_assert(strlen(but->drawstr) == drawstr_len);
|
||||
|
||||
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
|
||||
if (but->strwidth < 10) break;
|
||||
}
|
||||
|
||||
/* after the leading text is gone, chop off the : and following space, with ofs */
|
||||
while ((but->strwidth > okwidth) && (but->ofs < 2)) {
|
||||
ui_text_clip_give_next_off(but, but->drawstr);
|
||||
but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
|
||||
if (but->strwidth < 10) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now just remove trailing chars */
|
||||
/* once the label's gone, chop off the least significant digits */
|
||||
if (but->strwidth > okwidth) {
|
||||
float strwidth;
|
||||
drawstr_len = BLF_width_to_strlen(fstyle->uifont_id, but->drawstr + but->ofs,
|
||||
drawstr_len - but->ofs, okwidth, &strwidth) + but->ofs;
|
||||
but->strwidth = strwidth;
|
||||
but->drawstr[drawstr_len] = 0;
|
||||
}
|
||||
|
||||
if (fstyle->kerning == 1)
|
||||
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
static void widget_draw_text_ime_underline(
|
||||
uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, const rcti *rect,
|
||||
const wmIMEData *ime_data, const char *drawstr)
|
||||
{
|
||||
int ofs_x, width;
|
||||
int rect_x = BLI_rcti_size_x(rect);
|
||||
int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
|
||||
|
||||
if (drawstr[0] != 0) {
|
||||
if (but->pos >= but->ofs) {
|
||||
ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->pos - but->ofs);
|
||||
}
|
||||
else {
|
||||
ofs_x = 0;
|
||||
}
|
||||
|
||||
width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
|
||||
ime_data->composite_len + but->pos - but->ofs);
|
||||
|
||||
glColor4ubv((unsigned char *)wcol->text);
|
||||
UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1);
|
||||
|
||||
/* draw the thick line */
|
||||
if (sel_start != -1 && sel_end != -1) {
|
||||
sel_end -= sel_start;
|
||||
sel_start += but->pos;
|
||||
|
||||
if (sel_start >= but->ofs) {
|
||||
ofs_x = BLF_width(fstyle->uifont_id, drawstr + but->ofs, sel_start - but->ofs);
|
||||
}
|
||||
else {
|
||||
ofs_x = 0;
|
||||
}
|
||||
|
||||
width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
|
||||
sel_end + sel_start - but->ofs);
|
||||
|
||||
UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WITH_INPUT_IME */
|
||||
|
||||
static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect, const char *drawstr)
|
||||
{
|
||||
int drawstr_left_len = UI_MAX_DRAW_STR;
|
||||
const char *drawstr_right = NULL;
|
||||
bool use_right_only = false;
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
const wmIMEData *ime_data;
|
||||
#endif
|
||||
|
||||
UI_fontstyle_set(fstyle);
|
||||
|
||||
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT))
|
||||
fstyle->align = UI_STYLE_TEXT_LEFT;
|
||||
else if (but->drawflag & UI_BUT_TEXT_RIGHT)
|
||||
fstyle->align = UI_STYLE_TEXT_RIGHT;
|
||||
else
|
||||
fstyle->align = UI_STYLE_TEXT_CENTER;
|
||||
|
||||
if (fstyle->kerning == 1) /* for BLF_width */
|
||||
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
|
||||
/* Special case: when we're entering text for multiple buttons,
|
||||
* don't draw the text for any of the multi-editing buttons */
|
||||
if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) {
|
||||
uiBut *but_edit = ui_but_drag_multi_edit_get(but);
|
||||
if (but_edit) {
|
||||
drawstr = but_edit->editstr;
|
||||
fstyle->align = UI_STYLE_TEXT_LEFT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (but->editstr) {
|
||||
/* max length isn't used in this case,
|
||||
* we rely on string being NULL terminated. */
|
||||
drawstr_left_len = INT_MAX;
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
/* FIXME, IME is modifying 'const char *drawstr! */
|
||||
ime_data = ui_but_ime_data_get(but);
|
||||
|
||||
if (ime_data && ime_data->composite_len) {
|
||||
/* insert composite string into cursor pos */
|
||||
BLI_snprintf((char *)drawstr, UI_MAX_DRAW_STR, "%s%s%s",
|
||||
but->editstr, ime_data->str_composite,
|
||||
but->editstr + but->pos);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
drawstr = but->editstr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* text button selection, cursor, composite underline */
|
||||
if (but->editstr && but->pos != -1) {
|
||||
int but_pos_ofs;
|
||||
int tx, ty;
|
||||
|
||||
/* text button selection */
|
||||
if ((but->selend - but->selsta) > 0) {
|
||||
int selsta_draw, selwidth_draw;
|
||||
|
||||
if (drawstr[0] != 0) {
|
||||
|
||||
if (but->selsta >= but->ofs) {
|
||||
selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
|
||||
}
|
||||
else {
|
||||
selsta_draw = 0;
|
||||
}
|
||||
|
||||
selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
|
||||
|
||||
glColor4ubv((unsigned char *)wcol->item);
|
||||
glRecti(rect->xmin + selsta_draw,
|
||||
rect->ymin + 2,
|
||||
min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
|
||||
rect->ymax - 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* text cursor */
|
||||
but_pos_ofs = but->pos;
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
/* if is ime compositing, move the cursor */
|
||||
if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
|
||||
but_pos_ofs += ime_data->cursor_pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (but->pos >= but->ofs) {
|
||||
int t;
|
||||
if (drawstr[0] != 0) {
|
||||
t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but_pos_ofs - but->ofs);
|
||||
}
|
||||
else {
|
||||
t = 0;
|
||||
}
|
||||
|
||||
glColor3f(0.2, 0.6, 0.9);
|
||||
|
||||
tx = rect->xmin + t + 2;
|
||||
ty = rect->ymin + 2;
|
||||
|
||||
/* draw cursor */
|
||||
glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
|
||||
}
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
if (ime_data && ime_data->composite_len) {
|
||||
/* ime cursor following */
|
||||
if (but->pos >= but->ofs) {
|
||||
ui_but_ime_reposition(but, tx + 5, ty + 3, false);
|
||||
}
|
||||
|
||||
/* composite underline */
|
||||
widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fstyle->kerning == 1)
|
||||
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
|
||||
#if 0
|
||||
ui_rasterpos_safe(x, y, but->aspect);
|
||||
transopts = ui_translate_buttons();
|
||||
#endif
|
||||
|
||||
/* cut string in 2 parts - only for menu entries */
|
||||
if ((but->block->flag & UI_BLOCK_LOOP) &&
|
||||
(but->editstr == NULL))
|
||||
{
|
||||
if (but->flag & UI_BUT_HAS_SEP_CHAR) {
|
||||
drawstr_right = strrchr(drawstr, UI_SEP_CHAR);
|
||||
if (drawstr_right) {
|
||||
drawstr_left_len = (drawstr_right - drawstr);
|
||||
drawstr_right++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_NUMBUTS_LR_ALIGN
|
||||
if (!drawstr_right && ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
|
||||
/* if we're editing or multi-drag (fake editing), then use left alignment */
|
||||
(but->editstr == NULL) && (drawstr == but->drawstr))
|
||||
{
|
||||
drawstr_right = strchr(drawstr + but->ofs, ':');
|
||||
if (drawstr_right) {
|
||||
drawstr_right++;
|
||||
drawstr_left_len = (drawstr_right - drawstr);
|
||||
|
||||
while (*drawstr_right == ' ') {
|
||||
drawstr_right++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no prefix, even so use only cpoin */
|
||||
drawstr_right = drawstr + but->ofs;
|
||||
use_right_only = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
glColor4ubv((unsigned char *)wcol->text);
|
||||
|
||||
if (!use_right_only) {
|
||||
/* for underline drawing */
|
||||
float font_xofs, font_yofs;
|
||||
|
||||
UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs,
|
||||
drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
|
||||
|
||||
if (but->menu_key != '\0') {
|
||||
char fixedbuf[128];
|
||||
const char *str;
|
||||
|
||||
BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len));
|
||||
|
||||
str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
|
||||
if (str == NULL)
|
||||
str = strchr(fixedbuf, but->menu_key);
|
||||
|
||||
if (str) {
|
||||
int ul_index = -1;
|
||||
float ul_advance;
|
||||
|
||||
ul_index = (int)(str - fixedbuf);
|
||||
|
||||
if (fstyle->kerning == 1) {
|
||||
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
|
||||
fixedbuf[ul_index] = '\0';
|
||||
ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
|
||||
|
||||
BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
|
||||
BLF_draw(fstyle->uifont_id, "_", 2);
|
||||
|
||||
if (fstyle->kerning == 1) {
|
||||
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* part text right aligned */
|
||||
if (drawstr_right) {
|
||||
fstyle->align = UI_STYLE_TEXT_RIGHT;
|
||||
rect->xmax -= UI_TEXT_CLIP_MARGIN;
|
||||
UI_fontstyle_draw(fstyle, rect, drawstr_right);
|
||||
}
|
||||
}
|
||||
|
||||
/* draws text and icons for buttons */
|
||||
void widget_draw_text_icon(
|
||||
uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but,
|
||||
rcti *rect, const char *str, const int iconid)
|
||||
{
|
||||
const bool show_menu_icon = ui_but_draw_menu_icon(but);
|
||||
float alpha = (float)wcol->text[3] / 255.0f;
|
||||
char password_str[UI_MAX_DRAW_STR];
|
||||
uiButExtraIconType extra_icon_type;
|
||||
|
||||
ui_but_text_password_hide(password_str, but, false);
|
||||
|
||||
/* check for button text label */
|
||||
if (but->type == UI_BTYPE_MENU && (but->flag & UI_BUT_NODE_LINK)) {
|
||||
rcti temp = *rect;
|
||||
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
|
||||
widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
|
||||
}
|
||||
|
||||
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
|
||||
* and offset the text label to accommodate it */
|
||||
|
||||
/* Big previews with optional text label below */
|
||||
if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) {
|
||||
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? iconid + but->iconadd : ICON_NONE;
|
||||
int icon_size = BLI_rcti_size_y(rect);
|
||||
int text_size = 0;
|
||||
|
||||
/* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
|
||||
if (icon_size > BLI_rcti_size_x(rect)) {
|
||||
/* button is not square, it has extra height for label */
|
||||
text_size = UI_UNIT_Y;
|
||||
icon_size -= text_size;
|
||||
}
|
||||
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect->ymin += text_size;
|
||||
glEnable(GL_BLEND);
|
||||
widget_draw_preview(icon, alpha, rect);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* offset rect to draw label in */
|
||||
rect->ymin -= text_size;
|
||||
rect->ymax -= icon_size;
|
||||
|
||||
/* vertically centering text */
|
||||
rect->ymin += UI_UNIT_Y / 2;
|
||||
}
|
||||
/* Icons on the left with optional text label on the right */
|
||||
else if (but->flag & UI_HAS_ICON || show_menu_icon) {
|
||||
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? iconid + but->iconadd : ICON_NONE;
|
||||
const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
|
||||
|
||||
/* menu item - add some more padding so menus don't feel cramped. it must
|
||||
* be part of the button so that this area is still clickable */
|
||||
if (ui_block_is_menu(but->block))
|
||||
rect->xmin += 0.3f * U.widget_unit;
|
||||
|
||||
widget_draw_icon(but, icon, alpha, rect, show_menu_icon);
|
||||
|
||||
rect->xmin += icon_size;
|
||||
/* without this menu keybindings will overlap the arrow icon [#38083] */
|
||||
if (show_menu_icon) {
|
||||
rect->xmax -= icon_size / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
|
||||
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
|
||||
}
|
||||
else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
|
||||
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
|
||||
}
|
||||
|
||||
/* unlink icon for this button type */
|
||||
if ((but->type == UI_BTYPE_SEARCH_MENU) &&
|
||||
((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
|
||||
{
|
||||
rcti temp = *rect;
|
||||
|
||||
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
|
||||
|
||||
if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
|
||||
widget_draw_icon(but, ICON_X, alpha, &temp, false);
|
||||
}
|
||||
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
|
||||
widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
|
||||
rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
|
||||
}
|
||||
|
||||
/* clip but->drawstr to fit in available space */
|
||||
if (but->editstr && but->pos >= 0) {
|
||||
ui_text_clip_cursor(fstyle, but, rect);
|
||||
}
|
||||
else if (but->drawstr[0] == '\0') {
|
||||
/* bypass text clipping on icon buttons */
|
||||
but->ofs = 0;
|
||||
but->strwidth = 0;
|
||||
}
|
||||
else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
|
||||
ui_text_clip_right_label(fstyle, but, rect);
|
||||
}
|
||||
else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
|
||||
/* Clip middle, but protect in all case right part containing the shortcut, if any. */
|
||||
ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
|
||||
}
|
||||
else {
|
||||
ui_text_clip_middle(fstyle, but, rect);
|
||||
}
|
||||
|
||||
/* always draw text for textbutton cursor */
|
||||
widget_draw_text(fstyle, wcol, but, rect, str);
|
||||
|
||||
ui_but_text_password_hide(password_str, but, true);
|
||||
}
|
||||
|
||||
#undef UI_TEXT_CLIP_MARGIN
|
||||
|
Reference in New Issue
Block a user