diff options
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 237 |
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); } } + +/** \} */ |