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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r--source/blender/editors/interface/interface_widgets.c237
1 files changed, 163 insertions, 74 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b3736a71e74..f1f193f1b02 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -66,6 +66,19 @@
/* 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))
+/* Button state argument shares bits with 'uiBut.flag'.
+ * reuse flags that aren't needed for drawing to avoid collision. */
+enum {
+ /* Show that holding the button opens a menu. */
+ UI_STATE_HOLD_ACTION = UI_BUT_UPDATE_DELAY,
+ UI_STATE_TEXT_INPUT = UI_BUT_UNDO,
+
+ UI_STATE_FLAGS_ALL = (UI_STATE_HOLD_ACTION | UI_STATE_TEXT_INPUT),
+};
+/* Prevent accidental use. */
+#define UI_BUT_UPDATE_DELAY ((void)0)
+#define UI_BUT_UNDO ((void)0)
+
/* ************** widget base functions ************** */
/**
* - in: roundbox codes for corner types and radius
@@ -145,45 +158,54 @@ static const float jit[WIDGET_AA_JITTER][2] = {
{-0.272855, 0.269918}, { 0.095909, 0.388710}
};
-static const float num_tria_vert[3][2] = {
+/* -------------------------------------------------------------------- */
+/** \name Shape Preset Data
+ * \{ */
+
+static const float g_shape_preset_number_arrow_vert[3][2] = {
{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}
};
-
-static const unsigned int num_tria_face[1][3] = {
+static const uint g_shape_preset_number_arrow_face[1][3] = {
{0, 1, 2}
};
-static const float scroll_circle_vert[16][2] = {
+static const float g_shape_preset_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] = {
+static const uint g_shape_preset_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 float menu_tria_vert[6][2] = {
+static const float g_shape_preset_menu_arrow_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 uint g_shape_preset_menu_arrow_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
-
-
-static const unsigned int menu_tria_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
-
-static const float check_tria_vert[6][2] = {
+static const float g_shape_preset_checkmark_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] = {
+static const uint g_shape_preset_checkmark_face[4][3] = {
{3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}
};
+#define OY -0.2
+#define SC 0.35
+static const float g_shape_preset_hold_action_vert[6][2] = {
+ {-0.5 + SC, 1.0 + OY}, {0.5, 1.0 + OY}, {0.5, 0.0 + OY + SC},
+};
+static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
+#undef OY
+#undef SC
+
+/** \} */
+
/* ************************************************* */
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
@@ -480,9 +502,12 @@ static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rec
round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
}
+/* -------------------------------------------------------------------- */
+/** \name Shape Preset Mini API
+ * \{ */
/* based on button rect, return scaled array of triangles */
-static void widget_draw_tria_ex(
+static void shape_preset_init_trias_ex(
uiWidgetTrias *tria, const rcti *rect, float triasize, char where,
/* input data */
const float verts[][2], const int verts_tot,
@@ -521,23 +546,31 @@ static void widget_draw_tria_ex(
tria->index = tris;
}
-static void widget_num_tria(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+{
+ shape_preset_init_trias_ex(
+ tria, rect, triasize, where,
+ g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert),
+ g_shape_preset_number_arrow_face, ARRAY_SIZE(g_shape_preset_number_arrow_face));
+}
+
+static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
- widget_draw_tria_ex(
+ shape_preset_init_trias_ex(
tria, rect, triasize, where,
- num_tria_vert, ARRAY_SIZE(num_tria_vert),
- num_tria_face, ARRAY_SIZE(num_tria_face));
+ g_shape_preset_hold_action_vert, ARRAY_SIZE(g_shape_preset_hold_action_vert),
+ g_shape_preset_hold_action_face, ARRAY_SIZE(g_shape_preset_hold_action_face));
}
-static void widget_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
+static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
- widget_draw_tria_ex(
+ shape_preset_init_trias_ex(
tria, rect, triasize, where,
- scroll_circle_vert, ARRAY_SIZE(scroll_circle_vert),
- scroll_circle_face, ARRAY_SIZE(scroll_circle_face));
+ g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
+ g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
}
-static void widget_trias_draw(uiWidgetTrias *tria)
+static void shape_preset_draw_trias(uiWidgetTrias *tria)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, tria->vec);
@@ -545,7 +578,7 @@ static void widget_trias_draw(uiWidgetTrias *tria)
glDisableClientState(GL_VERTEX_ARRAY);
}
-static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
+static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
{
float centx, centy, size;
int a;
@@ -556,15 +589,15 @@ static void widget_menu_trias(uiWidgetTrias *tria, const rcti *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->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
+ tria->vec[a][1] = size * g_shape_preset_menu_arrow_vert[a][1] + centy;
}
tria->tot = 2;
- tria->index = menu_tria_face;
+ tria->index = g_shape_preset_menu_arrow_face;
}
-static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
+static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rcti *rect)
{
float centx, centy, size;
int a;
@@ -575,14 +608,16 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *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->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
+ tria->vec[a][1] = size * g_shape_preset_checkmark_vert[a][1] + centy;
}
tria->tot = 4;
- tria->index = check_tria_face;
+ tria->index = g_shape_preset_checkmark_face;
}
+/** \} */
+
/* prepares shade colors */
static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
@@ -650,6 +685,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
/* backdrop non AA */
if (wtb->draw_inner) {
+ BLI_assert(wtb->totvert != 0);
if (wcol->shaded == 0) {
if (wcol->alpha_check) {
float inner_v_half[WIDGET_SIZE_MAX][2];
@@ -729,6 +765,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
/* for each AA step */
if (wtb->draw_outline) {
+ BLI_assert(wtb->totvert != 0);
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 */
@@ -783,12 +820,13 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
for (j = 0; j < WIDGET_AA_JITTER; j++) {
glTranslate2fv(jit[j]);
- if (wtb->tria1.tot)
- widget_trias_draw(&wtb->tria1);
+ if (wtb->tria1.tot) {
+ shape_preset_draw_trias(&wtb->tria1);
+ }
+ if (wtb->tria2.tot) {
+ shape_preset_draw_trias(&wtb->tria2);
+ }
- if (wtb->tria2.tot)
- widget_trias_draw(&wtb->tria2);
-
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
}
@@ -830,9 +868,9 @@ static int ui_but_draw_menu_icon(const uiBut *but)
/* 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)
+static void widget_draw_icon_ex(
+ const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const bool show_menu_icon,
+ const int icon_size)
{
float xs = 0.0f, ys = 0.0f;
float aspect, height;
@@ -848,7 +886,7 @@ static void widget_draw_icon(
if (icon == ICON_BLANK1 && (but->flag & UI_BUT_ICON_SUBMENU) == 0) return;
aspect = but->block->aspect / UI_DPI_FAC;
- height = ICON_DEFAULT_HEIGHT / aspect;
+ height = icon_size / aspect;
/* calculate blend color */
if (ELEM(but->type, UI_BTYPE_TOGGLE, UI_BTYPE_ROW, UI_BTYPE_TOGGLE_N, UI_BTYPE_LISTROW)) {
@@ -874,21 +912,18 @@ static void widget_draw_icon(
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 {
+ /* special case - icon_only pie buttons */
+ if (ui_block_is_pie_menu(but->block) && but->type != UI_BTYPE_MENU && but->str && but->str[0] == '\0')
+ xs = rect->xmin + 2.0f * ofs;
+ else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL)
+ xs = rect->xmin + 2.0f * 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;
}
+ 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) {
@@ -915,6 +950,12 @@ static void widget_draw_icon(
glDisable(GL_BLEND);
}
+static void widget_draw_icon(
+ const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const bool show_menu_icon)
+{
+ widget_draw_icon_ex(but, icon, alpha, rect, show_menu_icon, ICON_DEFAULT_HEIGHT);
+}
+
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);
@@ -1520,6 +1561,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rcti temp = *rect;
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
+ rect->xmax = temp.xmin;
}
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
@@ -1554,11 +1596,15 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* 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) ? but->icon + but->iconadd : ICON_NONE;
- const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
+ const float icon_size = ICON_DEFAULT_WIDTH_SCALE;
/* 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))
+ if (ui_block_is_pie_menu(but->block)) {
+ if (but->dt == UI_EMBOSS_RADIAL)
+ rect->xmin += 0.3f * U.widget_unit;
+ }
+ else if (ui_block_is_menu(but->block))
rect->xmin += 0.3f * U.widget_unit;
widget_draw_icon(but, icon, alpha, rect, show_menu_icon);
@@ -1951,7 +1997,7 @@ static void widget_state(uiWidgetType *wt, int state)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
- if ((state & UI_BUT_LIST_ITEM) && !(state & UI_TEXTINPUT)) {
+ if ((state & UI_BUT_LIST_ITEM) && !(state & UI_STATE_TEXT_INPUT)) {
/* Override default widget's colors. */
bTheme *btheme = UI_GetTheme();
wt->wcol_theme = &btheme->tui.wcol_list_item;
@@ -2643,16 +2689,20 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
if (!emboss) {
round_box_edges(&wtb, roundboxalign, rect, rad);
}
+ else {
+ wtb.draw_inner = false;
+ wtb.draw_outline = false;
+ }
/* decoration */
- if (!(state & UI_TEXTINPUT)) {
- widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
- widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
+ if (!(state & UI_STATE_TEXT_INPUT)) {
+ shape_preset_init_number_arrows(&wtb.tria1, rect, 0.6f, 'l');
+ shape_preset_init_number_arrows(&wtb.tria2, rect, 0.6f, 'r');
}
widgetbase_draw(&wtb, wcol);
- if (!(state & UI_TEXTINPUT)) {
+ if (!(state & UI_STATE_TEXT_INPUT)) {
/* text space */
rect->xmin += textofs;
rect->xmax -= textofs;
@@ -2782,12 +2832,12 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
wcol->item[3] = 255;
if (horizontal) {
- widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
- widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
+ shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
+ shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
}
else {
- widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
- widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
+ shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
+ shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
}
}
widgetbase_draw(&wtb, wcol);
@@ -2931,7 +2981,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
widgetbase_draw(&wtb, wcol);
/* draw left/right parts only when not in text editing */
- if (!(state & UI_TEXTINPUT)) {
+ if (!(state & UI_STATE_TEXT_INPUT)) {
int roundboxalign_slider;
/* slider part */
@@ -2982,7 +3032,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
widgetbase_draw(&wtb, wcol);
/* add space at either side of the button so text aligns with numbuttons (which have arrow icons) */
- if (!(state & UI_TEXTINPUT)) {
+ if (!(state & UI_STATE_TEXT_INPUT)) {
rect->xmax -= toffs;
rect->xmin += toffs;
}
@@ -3124,7 +3174,7 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
round_box_edges(&wtb, roundboxalign, rect, rad);
/* decoration */
- widget_menu_trias(&wtb.tria1, rect);
+ shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
widgetbase_draw(&wtb, wcol);
@@ -3263,7 +3313,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
/* decoration */
if (state & UI_SELECT) {
- widget_check_trias(&wtb.tria1, &recttemp);
+ shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
}
widgetbase_draw(&wtb, wcol);
@@ -3346,6 +3396,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
widgetbase_draw(&wtb, wcol);
}
+#if 0
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
@@ -3358,6 +3409,25 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widgetbase_draw(&wtb, wcol);
}
+#endif
+
+static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ uiWidgetBase wtb;
+ const float rad = 0.25f * U.widget_unit;
+
+ widget_init(&wtb);
+
+ if (state & UI_STATE_HOLD_ACTION) {
+ /* Show that keeping pressed performs another action (typically a menu). */
+ shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
+ }
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ widgetbase_draw(&wtb, wcol);
+}
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
@@ -3438,7 +3508,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_EXEC:
wt.wcol_theme = &btheme->tui.wcol_tool;
- wt.draw = widget_roundbut;
+ wt.draw = widget_roundbut_exec;
break;
case UI_WTYPE_TOOLTIP:
@@ -3613,6 +3683,10 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
return roundbox;
}
+/* -------------------------------------------------------------------- */
+/** \name Public API
+ * \{ */
+
/* conversion from old to new buttons, so still messy */
void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
{
@@ -3654,11 +3728,15 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
switch (but->type) {
case UI_BTYPE_LABEL:
- if (but->block->flag & UI_BLOCK_LOOP)
- widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect);
- else {
- wt = widget_type(UI_WTYPE_LABEL);
- fstyle = &style->widgetlabel;
+ wt = widget_type(UI_WTYPE_LABEL);
+ fstyle = &style->widgetlabel;
+ if (but->drawflag & UI_BUT_BOX_ITEM) {
+ wt->wcol_theme = &tui->wcol_box;
+ wt->state = widget_state;
+ }
+ else if (but->block->flag & UI_BLOCK_LOOP) {
+ wt->wcol_theme = &tui->wcol_menu_back;
+ wt->state = widget_state;
}
break;
@@ -3844,12 +3922,21 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
roundboxalign = widget_roundbox_set(but, rect);
- state = but->flag;
+ /* Mask out flags re-used for local state. */
+ state = but->flag & ~UI_STATE_FLAGS_ALL;
+
+ if (state & UI_SELECT_DRAW) {
+ state |= UI_SELECT;
+ }
if ((but->editstr) ||
(UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but)))
{
- state |= UI_TEXTINPUT;
+ state |= UI_STATE_TEXT_INPUT;
+ }
+
+ if (but->hold_func) {
+ state |= UI_STATE_HOLD_ACTION;
}
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
@@ -4178,3 +4265,5 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
UI_fontstyle_draw(fstyle, &trect, drawstr);
}
}
+
+/** \} */