diff options
33 files changed, 1325 insertions, 470 deletions
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3783ae2272d..55a436b6967 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -625,6 +625,8 @@ class USERPREF_PT_theme(Panel): subsub.active = widget_style.show_shaded subsub.prop(widget_style, "shadetop") subsub.prop(widget_style, "shadedown") + subsub = colsub.column(align=True) + subsub.prop(widget_style, "roundness") layout.separator() @@ -685,6 +687,14 @@ class USERPREF_PT_theme(Panel): col = split.column() ui = theme.user_interface + row = col.row() + subsplit = row.split(percentage=0.47) + subsplit.prop(ui, "interface_style") + + col.separator() + col.separator() + col.separator() + col.label(text="Regular:") self._theme_widget_style(col, ui.wcol_regular) @@ -799,6 +809,7 @@ class USERPREF_PT_theme(Panel): colsub = padding.column() colsub = padding.column() colsub.row().prop(ui, "widget_emboss") + colsub.row().prop(ui, "area_edges") col.separator() col.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b936e2df165..f5db15dae35 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1345,7 +1345,8 @@ class VIEW3D_MT_object_specials(Menu): props.input_scale = 0.05 props.header_text = "Clip End: %.2f" - layout.separator() + if obj.type in {'CAMERA', 'CURVE', 'FONT', 'EMPTY', 'LAMP'}: + layout.separator() props = layout.operator("object.isolate_type_render") props = layout.operator("object.hide_render_clear_all") diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 2a9583b99d2..1032e32951a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 275 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 1e309f59fba..571a8cc49e5 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -851,4 +851,48 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } #undef BRUSH_TORUS } + + { + bScreen *screen; + for (screen = main->screen.first; screen; screen = screen->id.next) { + ScrArea *sa; + + for (sa = screen->areabase.first; sa; sa = sa->next) { + const char needed_type = (sa->spacetype == SPACE_CLIP) ? RGN_TYPE_PREVIEW : RGN_TYPE_WINDOW; + ARegion *ar = BKE_area_find_region_type(sa, needed_type); + SpaceLink *sl; + + if (ar == NULL) + continue; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + switch (sl->spacetype) { + case SPACE_TIME: + case SPACE_ACTION: + case SPACE_NLA: + ar->v2d.flag |= V2D_USES_UNITS_HORIZONTAL; + break; + case SPACE_IPO: + case SPACE_SEQ: + ar->v2d.flag |= (V2D_USES_UNITS_HORIZONTAL | V2D_USES_UNITS_VERTICAL); + break; + case SPACE_CLIP: + { + SpaceClip *sc = (SpaceClip *)sl; + + if (sc->view == SC_VIEW_DOPESHEET) { + ar->v2d.flag |= V2D_USES_UNITS_HORIZONTAL; + } + else if (sc->view == SC_VIEW_GRAPH) { + ar->v2d.flag |= (V2D_USES_UNITS_HORIZONTAL | V2D_USES_UNITS_VERTICAL); + } + break; + } + default: + break; + } + } + } + } + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 0e8e6e9d144..17b0f388af4 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -52,6 +52,8 @@ */ void BLO_update_defaults_userpref_blend(void) { + uiStyle *style; + /* defaults from T37518 */ U.uiflag |= USER_ZBUF_CURSOR; @@ -60,6 +62,13 @@ void BLO_update_defaults_userpref_blend(void) U.versions = 1; U.savetime = 2; + + U.dpi = 78; + + for (style = U.uistyles.first; style; style = style->next) { + style->paneltitle.points = style->widgetlabel.points = style->widget.points = 10; + style->paneltitle.shadow = style->widgetlabel.shadow = 0; + } } /** diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 4d9df06f33f..465fda71837 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -164,7 +164,9 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U */ if (strstr(op->idname, "assign")) { uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0); - uiItemS(layout); + if (!BLI_listbase_is_empty(&pose->agroups)) { + uiItemS(layout); + } } /* add entries for each group */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 330484bf72b..fee0447b923 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -133,8 +133,9 @@ enum { /* block->flag bits 14-17 are identical to but->drawflag bits */ -#define UI_BLOCK_LIST_ITEM (1 << 19) -#define UI_BLOCK_RADIAL (1 << 20) +#define UI_BLOCK_LIST_ITEM (1 << 19) +#define UI_BLOCK_RADIAL (1 << 20) +#define UI_BLOCK_HAS_SUBMENU (1 << 21) /* the block has at least one button leading to a submenu */ /* uiPopupBlockHandle->menuretval */ #define UI_RETURN_CANCEL (1 << 0) /* cancel all menus cascading */ @@ -179,11 +180,13 @@ enum { UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */ UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */ UI_BUT_SEARCH_UNLINK = (1 << 30), /* show unlink for search button */ + UI_BUT_MENU_TITLE = (1 << 31), /* title of a menu - XXX maybe new BTYPE? */ }; #define UI_PANEL_WIDTH 340 #define UI_COMPACT_PANEL_WIDTH 160 +#define UI_PANEL_MARGIN (U.widget_unit * 0.25f) #define UI_PANEL_CATEGORY_MARGIN_WIDTH (U.widget_unit * 1.0f) /* but->drawflag - these flags should only affect how the button is drawn. */ @@ -631,6 +634,7 @@ int UI_icon_from_report_type(int type); uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip); uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char *str, int x, int y, short width, short height, const char *tip); +uiBut *uiDefMenuTitleBut(uiBlock *block, const char *str); uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip); uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, int x, int y, short width, short height, const char *tip); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 2b19b6180e5..20115468ef8 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -55,6 +55,9 @@ enum { TH_REDALERT, TH_THEMEUI, + + TH_AREA_EDGES, + // common colors among spaces TH_BACK, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 2c8f5f6590a..43a55845d49 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -103,8 +103,10 @@ enum eView2D_Gridlines { /* ------ Defines for Scrollers ----- */ /* scroller area */ -#define V2D_SCROLL_HEIGHT (0.85f * U.widget_unit) -#define V2D_SCROLL_WIDTH (0.85f * U.widget_unit) +#define V2D_SCROLL_HEIGHT (0.50f * U.widget_unit) +#define V2D_SCROLL_WIDTH (0.50f * U.widget_unit) +#define V2D_SCROLL_HEIGHT_TEXT (0.85f * U.widget_unit) +#define V2D_SCROLL_WIDTH_TEXT (0.85f * U.widget_unit) /* scroller 'handles' hotspot radius for mouse */ #define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d11c1957d33..24f1f42fa8c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -161,6 +161,13 @@ void ui_block_to_window_rctf(const ARegion *ar, uiBlock *block, rctf *rct_dst, c ui_block_to_window_fl(ar, block, &rct_dst->xmax, &rct_dst->ymax); } +void ui_block_to_window_rcti(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src) +{ + *rct_dst = *rct_src; + ui_block_to_window(ar, block, &rct_dst->xmin, &rct_dst->ymin); + ui_block_to_window(ar, block, &rct_dst->xmax, &rct_dst->ymax); +} + void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y) /* for mouse cursor */ { float a, b, c, d, e, f, px, py; @@ -1321,6 +1328,43 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u rect->ymax = floorf(rectf.ymax); } + +/* project a rcti to pixels in regionspace */ +void ui_rcti_to_pixelrect(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src) +{ + rcti rect; + + ui_block_to_window_rcti(ar, block, &rect, rct_src); + + rect.xmin -= ar->winrct.xmin; + rect.ymin -= ar->winrct.ymin; + rect.xmax -= ar->winrct.xmin; + rect.ymax -= ar->winrct.ymin; + + rct_dst->xmin = iroundf(rect.xmin); + rct_dst->ymin = iroundf(rect.ymin); + rct_dst->xmax = iroundf(rect.xmax); + rct_dst->ymax = iroundf(rect.ymax); +} + +/* project a rctf to pixels in regionspace */ +void ui_rctf_to_pixelrect(const ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src) +{ + rctf rect; + + ui_block_to_window_rctf(ar, block, &rect, rct_src); + + rect.xmin -= ar->winrct.xmin; + rect.ymin -= ar->winrct.ymin; + rect.xmax -= ar->winrct.xmin; + rect.ymax -= ar->winrct.ymin; + + rct_dst->xmin = floorf(rect.xmin); + rct_dst->ymin = floorf(rect.ymin); + rct_dst->xmax = floorf(rect.xmax); + rct_dst->ymax = floorf(rect.ymax); +} + /* uses local copy of style, to scale things down, and allow widgets to change stuff */ void UI_block_draw(const bContext *C, uiBlock *block) { @@ -2233,6 +2277,12 @@ static void ui_but_string_set_internal(uiBut *but, const char *str, size_t str_l memcpy(but->str, str, str_len); } +static void ui_but_submenu_enable(uiBlock *block, uiBut *but) +{ + but->flag |= UI_BUT_ICON_SUBMENU; + block->flag |= UI_BLOCK_HAS_SUBMENU; +} + static void ui_but_string_free_internal(uiBut *but) { if (but->str) { @@ -2520,6 +2570,10 @@ static void ui_but_free(const bContext *C, uiBut *but) IMB_freeImBuf((struct ImBuf *)but->poin); } + if ((BLI_listbase_is_empty(&but->subbuts)) == false) { + BLI_freelistN(&but->subbuts); + } + BLI_assert(UI_butstore_is_registered(but->block, but) == false); MEM_freeN(but); @@ -3096,6 +3150,25 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]) IMB_colormanagement_display_to_scene_linear_v3(pixel, display); } +static uiSubBut *ui_def_subbut( + uiBut *but, const int type, + uiSubButAlign alignment, + const int width, const int height) +{ + uiSubBut *sbut = MEM_callocN(sizeof(uiSubBut), "uiSubBut"); + + sbut->type = type; + sbut->align = alignment; + sbut->width = width; + sbut->height = height; + + /* sbut->rect is calculated later */ + + BLI_addtail(&but->subbuts, sbut); + + return sbut; +} + /** * \brief ui_def_but is the function that draws many button types * @@ -3210,6 +3283,13 @@ static uiBut *ui_def_but( } } + if (but->type == UI_BTYPE_NUM) { + const int sbut_width = MIN2(width / 3, height); + + ui_def_subbut(but, UI_SBUT_TYPE_VAL_DECREASE, UI_SBUT_ALIGN_LEFT, sbut_width, height); + ui_def_subbut(but, UI_SBUT_TYPE_VAL_INCREASE, UI_SBUT_ALIGN_RIGHT, sbut_width, height); + } + /* keep track of UI_interface.h */ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL, @@ -3248,7 +3328,7 @@ void ui_def_but_icon(uiBut *but, const int icon, const int flag) but->flag |= flag; if (but->str && but->str[0]) { - but->drawflag |= UI_BUT_ICON_LEFT; + but->drawflag |= (UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT); } } @@ -3311,9 +3391,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu rows++; /* Title */ - uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_property_ui_name(but->rnaprop), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - uiItemS(layout); + uiDefMenuTitleBut(block, RNA_property_ui_name(but->rnaprop)); /* note, item_array[...] is reversed on access */ @@ -3519,7 +3597,7 @@ static uiBut *ui_def_but_rna( } if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) { - but->flag |= UI_BUT_ICON_SUBMENU; + ui_but_submenu_enable(block, but); } if (!RNA_property_editable(&but->rnapoin, prop)) { @@ -4226,6 +4304,17 @@ uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, const char return but; } +uiBut *uiDefMenuTitleBut(uiBlock *block, const char *str) +{ + uiBut *but = ui_def_but(block, UI_BTYPE_LABEL, 0, str, 0, 0, UI_MENU_TITLE_WIDTH, UI_MENU_TITLE_HEIGHT, + NULL, 0.0, 0.0, 0.0, 0.0, ""); + but->flag |= UI_BUT_MENU_TITLE; + + ui_but_update(but); + + return but; +} + uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, const char *str, int x, int y, short width, short height, const char *tip) { uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); @@ -4233,7 +4322,7 @@ uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, in ui_def_but_icon(but, icon, UI_HAS_ICON); but->drawflag |= UI_BUT_ICON_LEFT; - but->flag |= UI_BUT_ICON_SUBMENU; + ui_but_submenu_enable(block, but); but->menu_create_func = func; ui_but_update(but); @@ -4265,7 +4354,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, but->drawflag |= UI_BUT_ICON_LEFT; } but->flag |= UI_HAS_ICON; - but->flag |= UI_BUT_ICON_SUBMENU; + ui_but_submenu_enable(block, but); but->block_create_func = func; ui_but_update(but); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 82660a8eeae..ffb320783ad 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -381,6 +381,7 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my); static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y); static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit); static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event); +static uiSubBut *ui_subbut_find_mouse_over(const ARegion *ar, const uiBut *but, const int mouse_xy[2]); static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state); static void button_activate_exit( @@ -4248,68 +4249,8 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } if (click) { - /* we can click on the side arrows to increment/decrement, - * or click inside to edit the value directly */ - float tempf, softmin, softmax; - float handlewidth; - int temp; - - softmin = but->softmin; - softmax = but->softmax; - - handlewidth = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect)); - - if (!ui_but_is_float(but)) { - if (mx < (but->rect.xmin + handlewidth)) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - temp = (int)data->value - 1; - if (temp >= softmin && temp <= softmax) - data->value = (double)temp; - else - data->cancel = true; - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else if (mx > (but->rect.xmax - handlewidth)) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - temp = (int)data->value + 1; - if (temp >= softmin && temp <= softmax) - data->value = (double)temp; - else - data->cancel = true; - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else { - button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); - } - } - else { - if (mx < (but->rect.xmin + handlewidth)) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - tempf = (float)data->value - 0.01f * but->a1; - if (tempf < softmin) tempf = softmin; - data->value = tempf; - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else if (mx > but->rect.xmax - handlewidth) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - tempf = (float)data->value + 0.01f * but->a1; - if (tempf > softmax) tempf = softmax; - data->value = tempf; - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else { - button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); - } - } - + /* start textediting - clicking to increase/decrease numbers is handled via sub-buttons */ + button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval = WM_UI_HANDLER_BREAK; } @@ -4319,6 +4260,40 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return retval; } +static int ui_do_subbut_NUM(bContext *C, uiBut *but, const uiSubBut *sbut, const wmEvent *event) +{ + uiHandleButtonData *data = but->active; + const float softmin = but->softmin; + const float softmax = but->softmax; + const bool is_float = ui_but_is_float(but); + const bool increase = (sbut->type == UI_SBUT_TYPE_VAL_INCREASE); + float tempf; + int temp; + + if (event->type != LEFTMOUSE || event->val != KM_RELEASE || data->dragchange) + return WM_UI_HANDLER_CONTINUE; + + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + if (is_float) { + tempf = (float)data->value + (increase ? 0.01f : -0.01f) * but->a1; + CLAMP(tempf, softmin, softmax); + data->value = tempf; + } + else { + temp = (int)data->value + (increase ? 1 : -1); + if (IN_RANGE_INCL(temp, softmin, softmax)) + data->value = (double)temp; + else + data->cancel = true; + } + + button_activate_state(C, but, BUTTON_STATE_EXIT); + + /* always break */ + return WM_UI_HANDLER_BREAK; +} + static bool ui_numedit_but_SLI( uiBut *but, uiHandleButtonData *data, int mx, const bool is_horizontal, @@ -6466,6 +6441,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiPopupMenu *pup; uiLayout *layout; bool is_array, is_array_component; + bool is_first_item = true; /* will the next added item be the first menu entry? */ uiStringInfo label = {BUT_GET_LABEL, NULL}; /* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ @@ -6488,6 +6464,9 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); + /* adds a separator if it wouldn't be the first item (after title) */ +#define ADD_SEPARATOR_CONDITIONAL if (is_first_item == false) uiItemS(layout); + if (but->rnapoin.data && but->rnaprop) { PointerRNA *ptr = &but->rnapoin; PropertyRNA *prop = but->rnaprop; @@ -6527,7 +6506,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) /* keyframe settings */ uiItemS(layout); - + is_first_item = false; } else if (but->flag & UI_BUT_DRIVEN) { /* pass */ @@ -6543,6 +6522,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1); } + + is_first_item = false; } if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { @@ -6556,11 +6537,13 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1); } + + is_first_item = false; } /* Drivers */ if (but->flag & UI_BUT_DRIVEN) { - uiItemS(layout); + ADD_SEPARATOR_CONDITIONAL if (is_array_component) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"), @@ -6579,12 +6562,14 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), ICON_NONE, "ANIM_OT_paste_driver_button"); } + + is_first_item = false; } else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { /* pass */ } else if (is_anim) { - uiItemS(layout); + ADD_SEPARATOR_CONDITIONAL if (is_array_component) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"), @@ -6601,12 +6586,14 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), ICON_NONE, "ANIM_OT_paste_driver_button"); } + + is_first_item = false; } /* Keying Sets */ /* TODO: check on modifyability of Keying Set when doing this */ if (is_anim) { - uiItemS(layout); + ADD_SEPARATOR_CONDITIONAL if (is_array_component) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"), @@ -6622,10 +6609,12 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), ICON_NONE, "ANIM_OT_keyingset_button_remove"); } + + is_first_item = false; } - - uiItemS(layout); - + + ADD_SEPARATOR_CONDITIONAL + /* Property Operators */ /* Copy Property Value @@ -6680,17 +6669,23 @@ static bool ui_but_menu(bContext *C, uiBut *but) but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); UI_but_func_set(but2, remove_shortcut_func, but, NULL); + + is_first_item = false; } /* only show 'add' if there's a suitable key map for it to go in */ else if (WM_keymap_guess_opname(C, but->optype->idname)) { but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); + + is_first_item = false; } - - uiItemS(layout); + + ADD_SEPARATOR_CONDITIONAL } +#undef ADD_SEPARATOR_CONDITIONAL + /* Show header tools for header buttons. */ if (ui_block_is_menu(but->block) == false) { ARegion *ar = CTX_wm_region(C); @@ -6735,8 +6730,33 @@ static bool ui_but_menu(bContext *C, uiBut *but) return true; } +static int ui_do_but_subbut(bContext *C, uiBut *but, uiSubBut *sbut, const wmEvent *event) +{ + int retval = WM_UI_HANDLER_CONTINUE; + + BLI_assert(sbut->is_hovered); + + switch (but->type) { + case UI_BTYPE_NUM: + retval = ui_do_subbut_NUM(C, but, sbut, event); + break; + default: + break; + } + + if (retval == WM_UI_HANDLER_BREAK) { + BLI_assert(ui_but_contains_point_px(CTX_wm_region(C), but, event->x, event->y)); + button_activate_exit(C, but, but->active, true, false); + /* reactivate highlight state */ + button_activate_init(C, CTX_wm_region(C), but, BUTTON_ACTIVATE_OVER); + } + + return retval; +} + static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event) { + uiSubBut *sbut; uiHandleButtonData *data; int retval; @@ -6880,6 +6900,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * } } + sbut = ui_subbut_find_mouse_over(CTX_wm_region(C), but, &event->x); + + if (sbut) { + retval = ui_do_but_subbut(C, but, sbut, event); + + if (retval == WM_UI_HANDLER_BREAK) { + return retval; + } + } + switch (but->type) { case UI_BTYPE_BUT: retval = ui_do_but_BUT(C, but, data, event); @@ -7354,6 +7384,25 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event) } +static uiSubBut *ui_subbut_find_mouse_over(const ARegion *ar, const uiBut *but, const int mouse_xy[2]) +{ + uiSubBut *sbut; + float mx = mouse_xy[0]; + float my = mouse_xy[1]; + + BLI_assert(ui_but_contains_point_px(ar, but, UNPACK2(mouse_xy))); + + ui_window_to_block_fl(ar, but->block, &mx, &my); + + for (sbut = but->subbuts.first; sbut; sbut = sbut->next) { + if (BLI_rcti_isect_x(&sbut->rect, mx)) { + return sbut; + } + } + return NULL; +} + + static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y) { uiBlock *block; @@ -8036,6 +8085,31 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu /************ handle events for an activated button ***********/ +static void ui_handle_but_subbuts(ARegion *ar, const uiBut *but, const int mouse_xy[2]) +{ + uiSubBut *sbut = ui_subbut_find_mouse_over(ar, but, mouse_xy); + bool changed = false; + + if (sbut) { + if (sbut->is_hovered == false) { + sbut->is_hovered = true; + changed = true; + } + } + else { + for (sbut = but->subbuts.first; sbut; sbut = sbut->next) { + if (sbut->is_hovered) { + sbut->is_hovered = false; + changed = true; + } + } + } + + if (changed) { + ED_region_tag_redraw(ar); + } +} + static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) { uiHandleButtonData *data = but->active; @@ -8082,6 +8156,10 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) button_tooltip_timer_reset(C, but); } + if (BLI_listbase_is_empty(&but->subbuts) == false) { + ui_handle_but_subbuts(ar, but, &event->x); + } + break; } case TIMER: @@ -8754,7 +8832,7 @@ static int ui_handle_menu_event( /* check if mouse is inside block */ inside = BLI_rctf_isect_pt(&block->rect, mx, my); - inside_title = inside && ((my + (UI_UNIT_Y * 1.5f)) > block->rect.ymax); + inside_title = inside && ((my + UI_MENU_TITLE_HEIGHT) > block->rect.ymax); /* if there's an active modal button, don't check events or outside, except for search menu */ but = ui_but_find_active_in_region(ar); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 9461547a164..92e5b4a4d1b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -101,6 +101,11 @@ typedef enum { UI_WTYPE_PROGRESSBAR, } uiWidgetTypeEnum; +/* general menu defines */ +#define UI_MENU_TITLE_WIDTH (short)(UI_UNIT_X * 5.0f) +#define UI_MENU_TITLE_HEIGHT (short)(UI_UNIT_Y * 1.1f) +#define UI_MENU_SUBMENU_PADDING (10 * UI_DPI_FAC) /* some extra padding added to menus containing submenu icons */ + /* menu scrolling */ #define UI_MENU_SCROLL_ARROW 12 #define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2) @@ -121,6 +126,18 @@ enum { /* warn: rest of uiBut->flag in UI_interface.h */ }; +/* uiSubBut->type */ +typedef enum uiSubButType { + UI_SBUT_TYPE_VAL_DECREASE, + UI_SBUT_TYPE_VAL_INCREASE, +} uiSubButType; + +/* uiSubBut->align */ +typedef enum uiSubButAlign { + UI_SBUT_ALIGN_LEFT, + UI_SBUT_ALIGN_RIGHT, +} uiSubButAlign; + /* some buttons display icons only under special conditions * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */ typedef enum uiButExtraIconType { @@ -199,8 +216,23 @@ typedef struct { ListBase lines; } uiLink; +typedef struct uiSubBut { + struct uiSubBut *next, *prev; + + uiSubButType type; + uiSubButAlign align; /* alignment within but */ + + int width, height; + rcti rect; /* block relative coords */ + + bool is_hovered; /* could be made into flag */ +} uiSubBut; + struct uiBut { struct uiBut *next, *prev; + + ListBase subbuts; + int flag, drawflag; eButType type; eButPointerType pointype; @@ -440,10 +472,13 @@ extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT; extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y); extern void ui_block_to_window_rctf(const struct ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src); +extern void ui_block_to_window_rcti(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src); extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y); extern void ui_window_to_region(const ARegion *ar, int *x, int *y); extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y); +extern void ui_rcti_to_pixelrect(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src); +extern void ui_rctf_to_pixelrect(const ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src); extern double ui_but_value_get(uiBut *but); extern void ui_but_value_set(uiBut *but, double value); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 6b16bc95d7f..3181908100f 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -281,12 +281,40 @@ static void ui_item_position(uiItem *item, int x, int y, int w, int h) { if (item->type == ITEM_BUTTON) { uiButtonItem *bitem = (uiButtonItem *)item; + uiBut *but = bitem->but; + + but->rect.xmin = x; + but->rect.ymin = y; + but->rect.xmax = x + w; + but->rect.ymax = y + h; + + /* set subbut sizes */ + if (BLI_listbase_is_empty(&but->subbuts) == false) { + uiSubBut *sbut; + for (sbut = but->subbuts.first; sbut; sbut = sbut->next) { + if (sbut->align == UI_SBUT_ALIGN_LEFT) { + sbut->rect.xmin = but->rect.xmin - 2; /* - 2 looks a bit better */ + sbut->rect.xmax = sbut->rect.xmin + sbut->width; + } + else if (sbut->align == UI_SBUT_ALIGN_RIGHT) { + sbut->rect.xmax = but->rect.xmax + 4; /* + 4 looks a bit better */ + sbut->rect.xmin = but->rect.xmax - sbut->width; + } + else { + BLI_assert(0); + } + sbut->rect.ymin = but->rect.ymin + (U.pixelsize - 1.0f); + sbut->rect.ymax = sbut->rect.ymin + sbut->height; + + if (but->block->panel) { + uiStyle *style = UI_style_get_dpi(); + + sbut->rect.ymin += (but->block->panel->sizey - style->panelspace); + sbut->rect.ymax += (but->block->panel->sizey - style->panelspace); + } + } + } - bitem->but->rect.xmin = x; - bitem->but->rect.ymin = y; - bitem->but->rect.xmax = x + w; - bitem->but->rect.ymax = y + h; - ui_but_update(bitem->but); /* for strlen */ } else { diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index c69aed76b22..9e1d7d366d0 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -427,16 +427,43 @@ void UI_draw_icon_tri(float x, float y, char dir) } } -/* triangle 'icon' inside rect */ -static void ui_draw_tria_rect(const rctf *rect, char dir) +static void ui_draw_tria_rect(const rctf *rect, const bool is_closed) { - if (dir == 'h') { + const float col_tint = 50; + const int px = (int)UI_DPI_FAC; + float col[3]; + + /* XXX ensure contrast */ + UI_GetThemeColorShade3fv(TH_TITLE, col_tint, col); + + /* color for shadow drawing */ + glColor4f(0.0f, 0.0f, 0.0f, 0.3f); + + if (is_closed) { float half = 0.5f * BLI_rctf_size_y(rect); - ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half); + + /* draw shadow first */ + ui_draw_anti_tria(rect->xmin + px, rect->ymin - px, + rect->xmin + px, rect->ymax - px, + rect->xmax + px, rect->ymin + half - px); + + glColor3fv(col); + ui_draw_anti_tria(rect->xmin, rect->ymin, + rect->xmin, rect->ymax, + rect->xmax, rect->ymin + half); } else { - float half = 0.5f * BLI_rctf_size_x(rect); - ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin); + float half = 0.5f * BLI_rctf_size_y(rect); + + /* draw shadow first */ + ui_draw_anti_tria(rect->xmin + px, rect->ymax - px, + rect->xmax + px, rect->ymax - px, + rect->xmin + half + px, rect->ymin - px); + + glColor3fv(col); + ui_draw_anti_tria(rect->xmin, rect->ymax, + rect->xmax, rect->ymax, + rect->xmin + half, rect->ymin); } } @@ -462,9 +489,7 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2) /* x 'icon' for panel header */ static void ui_draw_x_icon(float x, float y) { - ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f); - } #define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ @@ -492,86 +517,133 @@ static void ui_draw_panel_scalewidget(const rcti *rect) fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1); glDisable(GL_BLEND); } + static void ui_draw_panel_dragwidget(const rctf *rect) { unsigned char col_back[3], col_high[3], col_dark[3]; - const int col_tint = 84; + const int col_tint = 60; - const int px = (int)U.pixelsize; + const int px = (int)UI_DPI_FAC; const int px_zoom = max_ii(iroundf(BLI_rctf_size_y(rect) / 22.0f), 1); const int box_margin = max_ii(iroundf((float)(px_zoom * 2.0f)), px); const int box_size = max_ii(iroundf((BLI_rctf_size_y(rect) / 8.0f) - px), px); + const int box_rows = 4; const int x_min = rect->xmin; const int y_min = rect->ymin; - const int y_ofs = max_ii(iroundf(BLI_rctf_size_y(rect) / 3.0f), px); - const int x_ofs = y_ofs; - int i_x, i_y; + const int y_ofs = (BLI_rctf_size_y(rect) / box_rows) - (box_margin * 0.5f); + int i; UI_GetThemeColor3ubv(UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK, col_back); - UI_GetColorPtrShade3ubv(col_back, col_high, col_tint); - UI_GetColorPtrShade3ubv(col_back, col_dark, -col_tint); + UI_GetColorPtrShade3ubv(col_back, col_high, col_tint); + UI_GetColorPtrShade3ubv(col_back, col_dark, -(col_tint * 0.4)); /* draw multiple boxes */ - for (i_x = 0; i_x < 4; i_x++) { - for (i_y = 0; i_y < 2; i_y++) { - const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin)); - const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin)); - - glColor3ubv(col_dark); - glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom); - glColor3ubv(col_high); - glRectf(x_co - box_size, y_co, x_co, y_co + box_size); - } + for (i = 0; i < box_rows; i++) { + const int y_co = (y_min + y_ofs) + (i * (box_size + box_margin)); + + glColor3ubv(col_dark); + glRectf(x_min - box_size + px_zoom, y_co - px_zoom, x_min + px_zoom, (y_co + box_size) - px_zoom); + glColor3ubv(col_high); + glRectf(x_min - box_size, y_co, x_min, y_co + box_size); } } - -static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const rcti *rect, char dir) +static void ui_draw_aligned_panel_header( + const uiStyle *style, const uiBlock *block, + const rcti *rect, const char dir) { - Panel *panel = block->panel; - rcti hrect; - int pnl_icons; + const Panel *panel = block->panel; + const int px = (int)UI_DPI_FAC; const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname; + rcti hrect; - /* + 0.001f to avoid flirting with float inaccuracy */ - if (panel->control & UI_PNL_CLOSE) - pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f; - else - pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f; - /* active tab */ /* draw text label */ UI_ThemeColor(TH_TITLE); - + hrect = *rect; if (dir == 'h') { - hrect.xmin = rect->xmin + pnl_icons; - hrect.ymin += 2.0f / block->aspect; + hrect.xmin = rect->xmin + BLI_rcti_size_y(rect); + hrect.ymin += (2.0f / block->aspect) * px; UI_fontstyle_draw(&style->paneltitle, &hrect, activename); } else { - /* ignore 'pnl_icons', otherwise the text gets offset horizontally - * + 0.001f to avoid flirting with float inaccuracy - */ - hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f; + hrect.xmin = rect->xmin + ((PNL_HEADER - 1) / block->aspect); UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename); } } +static void ui_draw_panel_shadow( + const rctf shadowrect, const float aspect, + const float alpha_fac, const bool is_selected) +{ + float alpha_fac_tmp = 0.2f * alpha_fac; + const int px = MAX2(iroundf(UI_DPI_FAC * (1 / aspect)), 1); + short shadow_ofs = is_selected ? 2.0f * px : 1.0f * px; + + glEnable(GL_BLEND); + + if (is_selected) { + /* draw a big soft shadow while dragging */ + UI_draw_box_shadow(alpha_fac * 255, shadowrect.xmin, shadowrect.ymin, shadowrect.xmax, shadowrect.ymax); + } + else { + short i; + + /* draw a soft 2px shadow */ + for (i = 0; i < 2; i++) { + glColor4f(0.0f, 0.0f, 0.0f, alpha_fac_tmp); + + glRectf(shadowrect.xmin + shadow_ofs, shadowrect.ymin - shadow_ofs, + shadowrect.xmax + shadow_ofs, shadowrect.ymax - shadow_ofs); + + shadow_ofs += px; + alpha_fac_tmp *= 0.5f; + } + } + + glDisable(GL_BLEND); +} + +static void panel_boundbox_get( + const uiBlock *block, const Panel *pa, + const rcti *blockrect, const rcti *headrect, + rctf *r_bounds) +{ + const int xmax = (pa->flag & PNL_CLOSEDX) ? (blockrect->xmin + (PNL_HEADER / block->aspect)) : blockrect->xmax; + const int ymin = (pa->flag & PNL_CLOSED) ? headrect->ymin : blockrect->ymin; + + BLI_rctf_init(r_bounds, blockrect->xmin, xmax, ymin, headrect->ymax); +} + /* panel integrated in buttonswindow, tool/property lists etc */ -void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin) +void ui_draw_aligned_panel( + uiStyle *style, uiBlock *block, + const rcti *rect, + const bool show_pin) { Panel *panel = block->panel; + rctf fullrect, itemrect; rcti headrect; - rctf itemrect; int ofsx; + + const bool is_selected = (panel->flag & PNL_SELECT) ? true : false; + const float alpha_fac = is_selected ? 0.7f : 1.0f; + + /* panel states */ + const bool is_inside = ELEM(panel->mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER); + const bool is_closed_xy = (panel->flag & PNL_CLOSED) ? true : false; const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; + /* theme options */ + const bool draw_header = UI_GetThemeValue(TH_PANEL_SHOW_HEADER); + const bool draw_back = UI_GetThemeValue(TH_PANEL_SHOW_BACK); + if (panel->paneltab) return; if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return; @@ -581,20 +653,45 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con headrect.ymin = headrect.ymax; headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f); + /* set fullrect */ + panel_boundbox_get(block, panel, rect, &headrect, &fullrect); + + if (draw_header == false && is_closed_xy) { + /* skip */ + } + /* draw panel shadow */ + else if (draw_header || draw_back) { + rctf shadowrect = fullrect; + + /* adjust shadowrect for special case: draw background but not header */ + if (draw_back && !draw_header) { + shadowrect.ymax = rect->ymax; + } + + ui_draw_panel_shadow(shadowrect, block->aspect, alpha_fac, is_selected); + } + { float minx = rect->xmin; - float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax; + float maxx = is_closed_x ? (minx + (PNL_HEADER / block->aspect)) : rect->xmax; float y = headrect.ymax; glEnable(GL_BLEND); - if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) { - /* draw with background color */ - UI_ThemeColor4(TH_PANEL_HEADER); - glRectf(minx, headrect.ymin + 1, maxx, y); + if (draw_header) { + float col[3]; - fdrawline(minx, y, maxx, y); - fdrawline(minx, y, maxx, y); + if (is_inside) { + /* highlight if mouse is inside */ + UI_GetThemeColorShade3fv(TH_PANEL_HEADER, 7, col); + } + else { + UI_GetThemeColor3fv(TH_PANEL_HEADER, col); + } + + /* draw with background color */ + glColor4f(UNPACK3(col), alpha_fac); + glRectf(minx, headrect.ymin, maxx, y); } else if (!(panel->runtime_flag & PNL_FIRST)) { /* draw embossed separator */ @@ -622,24 +719,24 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con #endif { glEnable(GL_BLEND); - UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect), + UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 1.8f) / block->aspect), headrect.ymin + (5.0f / block->aspect), (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED, (block->aspect / UI_DPI_FAC), 1.0f); glDisable(GL_BLEND); } - /* horizontal title */ if (is_closed_x == false) { + /* horizontal title */ ui_draw_aligned_panel_header(style, block, &headrect, 'h'); - /* itemrect smaller */ - itemrect.xmax = headrect.xmax - 5.0f / block->aspect; - itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect); - itemrect.ymin = headrect.ymin; - itemrect.ymax = headrect.ymax; + /* drag widget */ + if (is_inside) { + BLI_rctf_rcti_copy(&itemrect, &headrect); + /* itemrect smaller */ + itemrect.xmin = itemrect.xmax - (5.0f / block->aspect); - BLI_rctf_scale(&itemrect, 0.7f); - ui_draw_panel_dragwidget(&itemrect); + ui_draw_panel_dragwidget(&itemrect); + } } /* if the panel is minimized vertically: @@ -654,21 +751,23 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con } /* an open panel */ else { - /* in some occasions, draw a border */ - if (panel->flag & PNL_SELECT) { - if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL); - else UI_draw_roundbox_corner_set(UI_CNR_NONE); - - UI_ThemeColorShade(TH_BACK, -120); - UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8); - } - /* panel backdrop */ - if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) { + if (draw_back) { /* draw with background color */ + float col[3]; + + if (is_inside) { + /* highlight if mouse is inside */ + UI_GetThemeColorShade3fv(TH_PANEL_BACK, 7, col); + } + else { + UI_GetThemeColor3fv(TH_PANEL_BACK, col); + } + glEnable(GL_BLEND); - UI_ThemeColor4(TH_PANEL_BACK); + glColor4f(UNPACK3(col), alpha_fac); glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax); + glDisable(GL_BLEND); } if (panel->control & UI_PNL_SCALE) @@ -684,23 +783,14 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con ofsx = 22; } - /* draw collapse icon */ - UI_ThemeColor(TH_TITLE); - /* itemrect smaller */ - itemrect.xmin = headrect.xmin + 5.0f / block->aspect; + itemrect.xmin = headrect.xmin + (is_closed_x ? (1.0f / block->aspect) : (3.0f / block->aspect)); itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect); itemrect.ymin = headrect.ymin; itemrect.ymax = headrect.ymax; - BLI_rctf_scale(&itemrect, 0.35f); - if (is_closed_y) - ui_draw_tria_rect(&itemrect, 'h'); - else if (is_closed_x) - ui_draw_tria_rect(&itemrect, 'h'); - else - ui_draw_tria_rect(&itemrect, 'v'); + ui_draw_tria_rect(&itemrect, is_closed_xy); (void)ofsx; } @@ -851,8 +941,9 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo /* no smart other default start loc! this keeps switching f5/f6/etc compatible */ ps = panelsort; - ps->pa->ofsx = 0; - ps->pa->ofsy = -get_panel_size_y(ps->pa); + ps->pa->ofsx = UI_PANEL_MARGIN; + /* offset first panel, but not for properties editor, there is already some space making this look odd */ + ps->pa->ofsy = -(get_panel_size_y(ps->pa) + (sa->spacetype == SPACE_BUTS ? 0 : UI_PANEL_MARGIN)); if (has_category_tabs) { if (align == BUT_VERTICAL) { @@ -865,10 +956,10 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo if (align == BUT_VERTICAL) { psnext->pa->ofsx = ps->pa->ofsx; - psnext->pa->ofsy = get_panel_real_ofsy(ps->pa) - get_panel_size_y(psnext->pa); + psnext->pa->ofsy = get_panel_real_ofsy(ps->pa) - get_panel_size_y(psnext->pa) - UI_PANEL_MARGIN; } else { - psnext->pa->ofsx = get_panel_real_ofsx(ps->pa); + psnext->pa->ofsx = get_panel_real_ofsx(ps->pa) + UI_PANEL_MARGIN * 2; psnext->pa->ofsy = ps->pa->ofsy + get_panel_size_y(ps->pa) - get_panel_size_y(psnext->pa); } } @@ -1312,17 +1403,17 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in int align = panel_aligned(sa, ar), button = 0; rctf rect_drag, rect_pin; - float rect_leftmost; + float collapse_xmax; /* drag and pin rect's */ rect_drag = block->rect; - rect_drag.xmin = block->rect.xmax - (PNL_ICON * 1.5f); + rect_drag.xmin = block->rect.xmax - (PNL_ICON * 0.8f); rect_pin = rect_drag; if (show_pin) { BLI_rctf_translate(&rect_pin, -PNL_ICON, 0.0f); } - rect_leftmost = rect_pin.xmin; + collapse_xmax = rect_pin.xmin; /* mouse coordinates in panel space! */ @@ -1345,7 +1436,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in if (mx <= block->rect.xmax - 8 - PNL_ICON) button = 2; //else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) button = 1; } - else if (mx < rect_leftmost) { + else if (mx < collapse_xmax) { button = 1; } @@ -1897,13 +1988,21 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } } + /* do a first iteration over all panels to see if we have one that is already being dragged */ + for (block = ar->uiblocks.last; block; block = block->prev) { + if (block->panel && block->panel->flag & PNL_SELECT) { + /* don't handle any further interaction while a panel + * is dragged (which is handled separately) */ + retval = WM_UI_HANDLER_BREAK; + break; + } + } + if (retval == WM_UI_HANDLER_BREAK) { return retval; } for (block = ar->uiblocks.last; block; block = block->prev) { - uiPanelMouseState mouse_state; - mx = event->x; my = event->y; ui_window_to_block(ar, block, &mx, &my); @@ -1916,10 +2015,22 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */ continue; - mouse_state = ui_panel_mouse_state_get(block, pa, mx, my); + pa->mouse_state = ui_panel_mouse_state_get(block, pa, mx, my); + + /* some special redrawing (skipped if area is already tagged for redraw) */ + if (event->type == MOUSEMOVE && ar->do_draw == 0) { + int mx_prev = event->prevx; + int my_prev = event->prevy; + + ui_window_to_block(ar, block, &mx_prev, &my_prev); + /* redraw if mouse state has changed for mouse hover feedback */ + if (pa->mouse_state != ui_panel_mouse_state_get(block, pa, mx_prev, my_prev)) { + ED_region_tag_redraw(ar); + } + } /* XXX hardcoded key warning */ - if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) { + if (ELEM(pa->mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) { if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) { if (pa->flag & PNL_CLOSEDY) { @@ -1938,13 +2049,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) if (ui_but_is_active(ar)) continue; - if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { + if (ELEM(pa->mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { if (event->val == KM_PRESS) { /* open close on header */ if (ELEM(event->type, RETKEY, PADENTER)) { - if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + if (pa->mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; @@ -1954,12 +2065,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) /* all inside clicks should return in break - overlapping/float panels */ retval = WM_UI_HANDLER_BREAK; - if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + if (pa->mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } - else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) { + else if ((pa->mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) { panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE); retval = WM_UI_HANDLER_BREAK; break; @@ -1967,7 +2078,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } else if (event->type == RIGHTMOUSE) { - if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + if (pa->mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_panel_menu(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 6aabbbe76b6..08db44fe07c 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1353,6 +1353,10 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, for (bt = block->buttons.first; bt; bt = bt->next) { BLI_rctf_union(&block->rect, &bt->rect); + + if (UNLIKELY(block->flag & UI_BLOCK_HAS_SUBMENU)) { + bt->rect.xmax += UI_MENU_SUBMENU_PADDING; + } } } else { @@ -1360,8 +1364,12 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, block->rect.xmin = block->rect.ymin = 0; block->rect.xmax = block->rect.ymax = 20; } + + if (block->flag & UI_BLOCK_HAS_SUBMENU) { + block->rect.xmax += UI_MENU_SUBMENU_PADDING; + } } - + /* aspect = (float)(BLI_rcti_size_x(&block->rect) + 4);*/ /*UNUSED*/ ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect); @@ -1429,35 +1437,41 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP; } - if (dir1 == UI_DIR_LEFT) { - xof = butrct.xmin - block->rect.xmax; - if (dir2 == UI_DIR_UP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING; - else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING; - } - else if (dir1 == UI_DIR_RIGHT) { - xof = butrct.xmax - block->rect.xmin; - if (dir2 == UI_DIR_UP) yof = butrct.ymin - block->rect.ymin - center - MENU_PADDING; - else yof = butrct.ymax - block->rect.ymax + center + MENU_PADDING; - } - else if (dir1 == UI_DIR_UP) { - yof = butrct.ymax - block->rect.ymin; - if (dir2 == UI_DIR_RIGHT) xof = butrct.xmax - block->rect.xmax; - else xof = butrct.xmin - block->rect.xmin; - /* changed direction? */ - if ((dir1 & block->direction) == 0) { - UI_block_order_flip(block); - } - } - else if (dir1 == UI_DIR_DOWN) { - yof = butrct.ymin - block->rect.ymax; - if (dir2 == UI_DIR_RIGHT) xof = butrct.xmax - block->rect.xmax; - else xof = butrct.xmin - block->rect.xmin; - /* changed direction? */ - if ((dir1 & block->direction) == 0) { - UI_block_order_flip(block); - } +#define RECTS_BUT_BLOCK_DIFF(member) (butrct.member - block->rect.member) + + switch (dir1) { + case UI_DIR_LEFT: + xof = butrct.xmin - block->rect.xmax; + if (dir2 == UI_DIR_UP) yof = RECTS_BUT_BLOCK_DIFF(ymin) - center - MENU_PADDING; + else yof = RECTS_BUT_BLOCK_DIFF(ymax) + center + MENU_PADDING; + break; + case UI_DIR_RIGHT: + xof = butrct.xmax - block->rect.xmin; + if (dir2 == UI_DIR_UP) yof = RECTS_BUT_BLOCK_DIFF(ymin) - center - MENU_PADDING; + else yof = RECTS_BUT_BLOCK_DIFF(ymax) + center + MENU_PADDING; + break; + case UI_DIR_UP: + yof = iroundf(butrct.ymax - block->rect.ymin - (2.0f * U.pixelsize)); + if (dir2 == UI_DIR_RIGHT) xof = RECTS_BUT_BLOCK_DIFF(xmax); + else xof = RECTS_BUT_BLOCK_DIFF(xmin); + /* changed direction? */ + if ((dir1 & block->direction) == 0) { + UI_block_order_flip(block); + } + break; + case UI_DIR_DOWN: + yof = iroundf(butrct.ymin - block->rect.ymax + (2.0f * U.pixelsize)); + if (dir2 == UI_DIR_RIGHT) xof = RECTS_BUT_BLOCK_DIFF(xmax); + else xof = RECTS_BUT_BLOCK_DIFF(xmin); + /* changed direction? */ + if ((dir1 & block->direction) == 0) { + UI_block_order_flip(block); + } + break; } +#undef RECTS_BUT_BLOCK_DIFF + /* and now we handle the exception; no space below or to top */ if (top == 0 && down == 0) { if (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT) { @@ -2651,14 +2665,15 @@ uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon) if (icon) { BLI_snprintf(titlestr, sizeof(titlestr), " %s", title); - uiDefIconTextBut(pup->block, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + but = uiDefIconTextBut(pup->block, UI_BTYPE_LABEL, 0, icon, titlestr, 0, 0, + UI_MENU_TITLE_WIDTH, UI_MENU_TITLE_HEIGHT, NULL, + 0.0, 0.0, 0, 0, ""); + but->flag |= UI_BUT_MENU_TITLE; } else { - but = uiDefBut(pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + but = uiDefMenuTitleBut(pup->block, title); but->drawflag = UI_BUT_TEXT_LEFT; } - - uiItemS(pup->layout); } return pup; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 80e098cfdc9..21049b50e11 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -79,6 +79,8 @@ #include "UI_interface.h" #include "UI_interface_icons.h" +#include "UI_view2d.h" + #include "interface_intern.h" void UI_template_fix_linking(void) @@ -3122,7 +3124,7 @@ void uiTemplateList( /* add scrollbar */ if (len > layoutdata.visual_items) { col = uiLayoutColumn(row, false); - uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, V2D_SCROLL_WIDTH, UI_UNIT_Y * dyn_data->visual_height, &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, dyn_data->visual_height, 0, ""); } @@ -3211,7 +3213,7 @@ void uiTemplateList( /* add scrollbar */ if (len > layoutdata.visual_items) { /* col = */ uiLayoutColumn(row, false); - uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, V2D_SCROLL_WIDTH, UI_UNIT_Y * dyn_data->visual_height, &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, dyn_data->visual_height, 0, ""); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 253f4616843..dd36c1a4232 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -64,6 +64,10 @@ /* 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)) +/* for checking interface style type */ +#define IFACE_STYLE_IS_CLASSIC (((bTheme *)UI_GetTheme())->tui.interface_style == TH_IFACE_STYLE_CLASSIC) +#define IFACE_STYLE_IS_FLAT (((bTheme *)UI_GetTheme())->tui.interface_style == TH_IFACE_STYLE_FLAT) + /* ************** widget base functions ************** */ /** * - in: roundbox codes for corner types and radius @@ -122,6 +126,7 @@ typedef struct uiWidgetType { void (*state)(struct uiWidgetType *, int state); void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign); void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign); + void (*subbut_draw)(uiSubBut *, uiWidgetColors *, rcti *, int state, int roundboxalign); void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *); } uiWidgetType; @@ -231,6 +236,40 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m glDisable(GL_BLEND); } +static void ui_draw_anti_circle(float rad) +{ + float color[4]; + int j; + + glEnable(GL_BLEND); + glGetFloatv(GL_CURRENT_COLOR, color); + color[3] *= 0.125f; + glColor4fv(color); + + for (j = 0; j < WIDGET_AA_JITTER; j++) { + glTranslatef(jit[j][0], jit[j][1], 0.0f); + glutil_draw_filled_arc(0.0f, M_PI * 2.0f, rad, 40); + glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + } + + glDisable(GL_BLEND); +} + +static void ui_draw_anti_circle_rect(const rcti *rect) +{ + const int size_x = BLI_rcti_size_x(rect); + const int size_y = BLI_rcti_size_y(rect); + const float rad = size_y / 2; + + glPushMatrix(); + + /* origin is center of the rect */ + glTranslatef(rect->xmin + size_x / 2, rect->ymin + size_y / 2, 0.0f); + ui_draw_anti_circle(rad); + + glPopMatrix(); +} + static void widget_init(uiWidgetBase *wtb) { wtb->totvert = wtb->halfwayvert = 0; @@ -238,21 +277,38 @@ static void widget_init(uiWidgetBase *wtb) wtb->tria2.tot = 0; wtb->draw_inner = true; - wtb->draw_outline = true; - wtb->draw_emboss = true; wtb->draw_shadedir = true; + + if (IFACE_STYLE_IS_CLASSIC) { + wtb->draw_outline = true; + wtb->draw_emboss = true; + } + else { + BLI_assert(IFACE_STYLE_IS_FLAT); + + /* don't draw outline or emboss by default */ + wtb->draw_outline = false; + wtb->draw_emboss = false; + } } /* 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) +static int round_box_shadow_edges( + float (*vert)[2], const rcti *rect, + float rad, int roundboxalign, float step, + const bool has_outline) { float vec[WIDGET_CURVE_RESOLU][2]; float minx, miny, maxx, maxy; int a, tot = 0; rad += step; - + + if (has_outline == false) { + step -= U.pixelsize; + } + if (2.0f * rad > BLI_rcti_size_y(rect)) rad = 0.5f * BLI_rcti_size_y(rect); @@ -519,6 +575,8 @@ static void widget_draw_tria_ex( tria->index = tris; } +/* number button triangles are now drawn using sub-buttons */ +#if 0 static void widget_num_tria(uiWidgetTrias *tria, const rcti *rect, float triasize, char where) { widget_draw_tria_ex( @@ -526,6 +584,7 @@ static void widget_num_tria(uiWidgetTrias *tria, const rcti *rect, float triasiz num_tria_vert, ARRAY_SIZE(num_tria_vert), num_tria_face, ARRAY_SIZE(num_tria_face)); } +#endif static void widget_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where) { @@ -648,7 +707,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) /* backdrop non AA */ if (wtb->draw_inner) { - if (wcol->shaded == 0) { + if (wcol->shaded == 0 || IFACE_STYLE_IS_FLAT) { if (wcol->alpha_check) { float inner_v_half[WIDGET_SIZE_MAX][2]; float x_mid = 0.0f; /* used for dumb clamping of values */ @@ -696,11 +755,18 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) } else { /* simple fill */ - glColor4ubv((unsigned char *)wcol->inner); + glColor4ub(UNPACK3(wcol->inner), wcol->inner[3] * 0.285f); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v); - glDrawArrays(GL_POLYGON, 0, wtb->totvert); + + /* for each AA step */ + for (j = 0; j < WIDGET_AA_JITTER; j++) { + glTranslatef(jit[j][0], jit[j][1], 0.0f); + glDrawArrays(GL_POLYGON, 0, wtb->totvert); + glTranslatef(-jit[j][0], -jit[j][1], 0.0f); + } + glDisableClientState(GL_VERTEX_ARRAY); } } @@ -904,10 +970,19 @@ static void widget_draw_icon( } if (show_menu_icon) { - xs = rect->xmax - UI_DPI_ICON_SIZE - aspect; + rcti tria; + const int size = (int)(ICON_DEFAULT_HEIGHT / aspect); + + xs = rect->xmax - (UI_MENU_SUBMENU_PADDING * 0.5f); ys = (rect->ymin + rect->ymax - height) / 2.0f; - - UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha); + + BLI_rcti_init(&tria, xs, xs + size, ys, ys + size); + BLI_rcti_scale(&tria, 0.5f); + + glColor3f(1.0f, 1.0f, 1.0f); + ui_draw_anti_tria(tria.xmin, tria.ymin, + tria.xmax, tria.ymin + BLI_rcti_size_y(&tria) / 2, + tria.xmin, tria.ymax); } glDisable(GL_BLEND); @@ -1503,30 +1578,91 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } } +#define WITH_DUMMY_ICON_TEXT_ALIGN + +#ifdef WITH_DUMMY_ICON_TEXT_ALIGN +static bool ui_block_has_real_icon_but(const uiBlock *block) +{ + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + if ((but->flag & UI_HAS_ICON) && (but->icon != ICON_BLANK1)) { + return true; + } + } + + return false; +} +#endif + /* draws text and icons for buttons */ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect) { - const bool show_menu_icon = ui_but_draw_menu_icon(but); + uiBlock *block = but->block; float alpha = (float)wcol->text[3] / 255.0f; + const int size_y = BLI_rcti_size_y(rect); + int add_y = 0; char password_str[UI_MAX_DRAW_STR]; uiButExtraIconType extra_icon_type; + const bool show_menu_icon = ui_but_draw_menu_icon(but); + const bool is_block_menu = ui_block_is_menu(block); + + ui_but_text_password_hide(password_str, but, false); + /* scale down rect so the text isn't drawn into the + * extra space for added for submenu triangles */ + if (UNLIKELY((is_block_menu == true) && + (block->flag & UI_BLOCK_HAS_SUBMENU) && + (but->type != UI_BTYPE_SEPR_LINE))) + { + rect->xmax -= UI_MENU_SUBMENU_PADDING; + } + + /* add some offset for menu titles to make them centered vertically - ugly but works best */ + if (but->type == UI_BTYPE_LABEL && but->flag & UI_BUT_MENU_TITLE) { + BLI_assert(is_block_menu); + + if (block->direction == UI_DIR_UP || block->flag & UI_BLOCK_POPUP) { + rect->ymin += 2 * (int)(0.2f * UI_UNIT_Y); /* 2 * MENU_PADDING */ + rect->ymin -= 2.0f * U.pixelsize; + } + else if (block->direction == UI_DIR_DOWN) { + rect->ymin -= (int)(0.2f * UI_UNIT_Y); /* MENU_PADDING */ + } + else { + BLI_assert(0); + } + } + /* 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; + temp.xmin = rect->xmax - size_y - 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 */ +#ifdef WITH_DUMMY_ICON_TEXT_ALIGN + if (ui_block_has_real_icon_but(but->block) == false) { + /* block doesn't have any real icons so we can skip */ + + /* we still want to draw the submenu triangle icon though */ + if (show_menu_icon) { + widget_draw_icon(but, ICON_NONE, alpha, rect, show_menu_icon); + } + } + /* Big previews with optional text label below */ + else if (but->flag & UI_BUT_ICON_PREVIEW && is_block_menu) { +#else /* Big previews with optional text label below */ - if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) { + if (but->flag & UI_BUT_ICON_PREVIEW && is_block_menu) { +#endif const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE; - int icon_size = BLI_rcti_size_y(rect); + int icon_size = size_y; int text_size = 0; /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ @@ -1547,32 +1683,49 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB rect->ymax -= icon_size; /* vertically centering text */ - rect->ymin += UI_UNIT_Y / 2; + rect->ymin += (size_y + add_y) / 2; } /* Icons on the left with optional text label on the right */ - else if (but->flag & UI_HAS_ICON || show_menu_icon) { +#ifdef WITH_DUMMY_ICON_TEXT_ALIGN + 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); /* 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 (is_block_menu) 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; + } +#else + else if ((but->flag & UI_HAS_ICON) && but->icon != ICON_BLANK1) { + const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + 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 (is_block_menu) { + rect->xmin += 0.3f * U.widget_unit; } + + widget_draw_icon(but, icon, alpha, rect, show_menu_icon); + + rect->xmin += icon_size; } + else if (show_menu_icon) { + const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE; + widget_draw_icon(but, icon, alpha, rect, show_menu_icon); + } +#endif if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) { - rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; + rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / block->aspect; } else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) { - rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; + rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / block->aspect; } /* unlink icon for this button type */ @@ -1581,7 +1734,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB { rcti temp = *rect; - temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); + temp.xmin = temp.xmax - (size_y * 1.08f); if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { widget_draw_icon(but, ICON_X, alpha, &temp, false); @@ -1623,6 +1776,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } #undef UI_TEXT_CLIP_MARGIN +#undef WITH_ICON_TEXT_ALIGNMENT /* *********************** widget types ************************************* */ @@ -1641,26 +1795,32 @@ static struct uiWidgetColors wcol_num = { {25, 25, 25, 255}, {180, 180, 180, 255}, {153, 153, 153, 255}, - {90, 90, 90, 255}, + {90, 90, 90, 160}, {0, 0, 0, 255}, {255, 255, 255, 255}, 1, - -20, 0 + -20, 0, + + 0, /* pad */ + 0.5f }; static struct uiWidgetColors wcol_numslider = { {25, 25, 25, 255}, {180, 180, 180, 255}, {153, 153, 153, 255}, - {128, 128, 128, 255}, + {140, 140, 140, 255}, {0, 0, 0, 255}, {255, 255, 255, 255}, 1, - -20, 0 + -20, 0, + + 0, /* pad */ + 0.5f }; static struct uiWidgetColors wcol_text = { @@ -1673,7 +1833,10 @@ static struct uiWidgetColors wcol_text = { {255, 255, 255, 255}, 1, - 0, 25 + 0, 25, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_option = { @@ -1686,7 +1849,10 @@ static struct uiWidgetColors wcol_option = { {255, 255, 255, 255}, 1, - 15, -15 + 15, -15, + + 0, /* pad */ + 0.35f }; /* button that shows popup */ @@ -1700,7 +1866,10 @@ static struct uiWidgetColors wcol_menu = { {204, 204, 204, 255}, 1, - 15, -15 + 15, -15, + + 0, /* pad */ + 0.2f }; /* button that starts pulldown */ @@ -1714,7 +1883,10 @@ static struct uiWidgetColors wcol_pulldown = { {0, 0, 0, 255}, 0, - 25, -20 + 25, -20, + + 0, /* pad */ + 0.2f }; /* button inside menu */ @@ -1728,21 +1900,27 @@ static struct uiWidgetColors wcol_menu_item = { {0, 0, 0, 255}, 1, - 38, 0 + 38, 0, + + 0, /* pad */ + 0.2f }; /* backdrop menu + title text color */ static struct uiWidgetColors wcol_menu_back = { {0, 0, 0, 255}, - {25, 25, 25, 230}, + {40, 40, 40, 230}, {45, 45, 45, 230}, {100, 100, 100, 255}, - {160, 160, 160, 255}, + {220, 220, 220, 255}, {255, 255, 255, 255}, 0, - 25, -20 + 25, -20, + + 0, /* pad */ + 0.25f }; /* pie menus */ @@ -1756,7 +1934,10 @@ static struct uiWidgetColors wcol_pie_menu = { {255, 255, 255, 255}, 1, - 10, -10 + 10, -10, + + 0, /* pad */ + 0.5f }; @@ -1771,7 +1952,10 @@ static struct uiWidgetColors wcol_tooltip = { {255, 255, 255, 255}, 0, - 25, -20 + 25, -20, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_radio = { @@ -1784,11 +1968,14 @@ static struct uiWidgetColors wcol_radio = { {0, 0, 0, 255}, 1, - 15, -15 + 15, -15, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_regular = { - {25, 25, 25, 255}, + {40, 40, 40, 255}, {153, 153, 153, 255}, {100, 100, 100, 255}, {25, 25, 25, 255}, @@ -1797,7 +1984,10 @@ static struct uiWidgetColors wcol_regular = { {255, 255, 255, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_tool = { @@ -1810,24 +2000,30 @@ static struct uiWidgetColors wcol_tool = { {255, 255, 255, 255}, 1, - 15, -15 + 15, -15, + + 0, /* pad */ + 0.25f }; static struct uiWidgetColors wcol_box = { - {25, 25, 25, 255}, - {128, 128, 128, 255}, - {100, 100, 100, 255}, + {50, 50, 50, 255}, + {140, 140, 140, 255}, + {130, 130, 130, 255}, {25, 25, 25, 255}, {0, 0, 0, 255}, {255, 255, 255, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_toggle = { - {25, 25, 25, 255}, + {70, 70, 70, 255}, {153, 153, 153, 255}, {100, 100, 100, 255}, {25, 25, 25, 255}, @@ -1836,20 +2032,26 @@ static struct uiWidgetColors wcol_toggle = { {255, 255, 255, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_scroll = { {50, 50, 50, 180}, {80, 80, 80, 180}, {100, 100, 100, 180}, - {128, 128, 128, 255}, + {140, 140, 140, 255}, {0, 0, 0, 255}, {255, 255, 255, 255}, 1, - 5, -5 + 5, -5, + + 0, /* pad */ + 0.5f }; static struct uiWidgetColors wcol_progress = { @@ -1862,7 +2064,10 @@ static struct uiWidgetColors wcol_progress = { {255, 255, 255, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; static struct uiWidgetColors wcol_list_item = { @@ -1875,7 +2080,10 @@ static struct uiWidgetColors wcol_list_item = { {0, 0, 0, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; /* free wcol struct to play with */ @@ -1889,7 +2097,10 @@ static struct uiWidgetColors wcol_tmp = { {255, 255, 255, 255}, 0, - 0, 0 + 0, 0, + + 0, /* pad */ + 0.2f }; @@ -2133,7 +2344,7 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) /* ************ menu backdrop ************************* */ /* outside of rect, rad to left/bottom/right */ -static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin) +static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin, const bool has_outline) { bTheme *btheme = UI_GetTheme(); uiWidgetBase wtb; @@ -2154,7 +2365,10 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r 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); + totvert = round_box_shadow_edges( + wtb.inner_v, &rect1, radin, + roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), + 0.0f, has_outline); /* we draw a number of increasing size alpha quad strips */ alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout; @@ -2164,7 +2378,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r 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); + round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step, has_outline); glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac)); @@ -2177,34 +2391,104 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r glDisableClientState(GL_VERTEX_ARRAY); } -static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction) +static void widget_menu_back(uiWidgetColors *wcol, const uiBlock *block, rcti *rect) { uiWidgetBase wtb; + const uiBut *title_but; + rcti rect_title = *rect; int roundboxalign = UI_CNR_ALL; - + int roundbox_cpy = 0; + const bool is_popup = block->flag & UI_BLOCK_POPUP; + widget_init(&wtb); - - /* menu is 2nd level or deeper */ - if (flag & UI_BLOCK_POPUP) { - //rect->ymin -= 4.0; - //rect->ymax += 4.0; + + wtb.draw_emboss = 0; + + /* search a menu title button */ + for (title_but = block->buttons.first; title_but; title_but = title_but->next) { + if (title_but->flag & UI_BUT_MENU_TITLE) { + break; + } } - else if (direction == UI_DIR_DOWN) { - roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); - rect->ymin -= 0.1f * U.widget_unit; + + if (is_popup) { + if (title_but) { + rect_title.ymin = title_but->rect.ymin; + } } - else if (direction == UI_DIR_UP) { + else if (block->direction == UI_DIR_UP) { roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT; rect->ymax += 0.1f * U.widget_unit; + + if (title_but) { + /* adjust title rect */ + rect_title.ymin = title_but->rect.ymin; + rect_title.ymax = rect->ymax; + } } - + else if (block->direction == UI_DIR_DOWN) { + roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); + rect->ymin -= 0.1f * U.widget_unit; + + if (title_but) { + /* adjust title rect */ + rect_title.ymax = title_but->rect.ymax; + rect_title.ymin = rect->ymin; + } + } + roundbox_cpy = roundboxalign; + glEnable(GL_BLEND); - widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit); - - round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit); + widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit, wtb.draw_outline); + + /* adjust the main rect after shadow drawing to exclude the title rect */ + if (title_but) { + if (block->direction == UI_DIR_UP || is_popup) { + rect->ymax = rect_title.ymin + (int)(2.0f * U.pixelsize); + roundboxalign &= ~(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); + } + else if (block->direction == UI_DIR_DOWN) { + rect->ymin = rect_title.ymax - (int)(2.0f * U.pixelsize); + roundboxalign &= ~(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT); + } + } + + round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit); + widgetbase_draw(&wtb, wcol); + + /* draw title rect (in a darker color) */ + if (title_but) { + uiWidgetColors wcol_title = *wcol; + const char tint = -12; + const char inner_title[3] = {UNPACK3_EX(, wcol->inner, + tint)}; /* XXX _util function? */ + + copy_v3_v3_char(wcol_title.inner, inner_title); + + /* invert the temporarily tweaked roundboxalign with + * its earlier value to get the corners we need now */ + roundboxalign ^= roundbox_cpy; + + round_box_edges(&wtb, roundboxalign, &rect_title, wcol->roundness * U.widget_unit); + widgetbase_draw(&wtb, &wcol_title); + } + + glDisable(GL_BLEND); +} + +static void widget_tooltip_back(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) +{ + uiWidgetBase wtb; + + widget_init(&wtb); wtb.draw_emboss = false; + + glEnable(GL_BLEND); + widget_softshadow(rect, UI_CNR_ALL, wcol->roundness * U.widget_unit, wtb.draw_outline); + + round_box_edges(&wtb, UI_CNR_ALL, rect, wcol->roundness * U.widget_unit); + widgetbase_draw(&wtb, wcol); - + glDisable(GL_BLEND); } @@ -2615,46 +2899,43 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) /* ************ separator, for menus etc ***************** */ + +#define WIDGET_SEPARATOR_HEIGHT (2.0f * UI_DPI_FAC) + static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol) { - int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1; - unsigned char col[4]; - - col[0] = wcol->text[0]; - col[1] = wcol->text[1]; - col[2] = wcol->text[2]; - col[3] = 30; + int y = rect->ymin + (BLI_rcti_size_y(rect) - WIDGET_SEPARATOR_HEIGHT) / 2; + const unsigned char tint = 30; glEnable(GL_BLEND); - glColor4ubv(col); - sdrawline(rect->xmin, y, rect->xmax, y); + glLineWidth(WIDGET_SEPARATOR_HEIGHT); + glColor4ub(UNPACK3_EX(, wcol->inner, + tint), wcol->inner[3] / 2); + sdrawline(rect->xmin + UI_DPI_FAC, y, rect->xmax, y); + glLineWidth(1); glDisable(GL_BLEND); } +#undef WIDGET_SEPARATOR_HEIGHT + /* ************ button callbacks, draw ***************** */ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss) { uiWidgetBase wtb; - const float rad = 0.5f * BLI_rcti_size_y(rect); - float textofs = rad * 0.85f; + const int sizey = BLI_rcti_size_y(rect); + const float rad = wcol->roundness * sizey; + float textofs = 0.43f * sizey; if (state & UI_SELECT) SWAP(short, wcol->shadetop, wcol->shadedown); - + widget_init(&wtb); - + if (!emboss) { round_box_edges(&wtb, roundboxalign, rect, rad); } - /* decoration */ - if (!(state & UI_TEXTINPUT)) { - widget_num_tria(&wtb.tria1, rect, 0.6f, 'l'); - widget_num_tria(&wtb.tria2, rect, 0.6f, 'r'); - } - widgetbase_draw(&wtb, wcol); - + if (!(state & UI_TEXTINPUT)) { /* text space */ rect->xmin += textofs; @@ -2675,6 +2956,61 @@ static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti widget_numbut_draw(wcol, rect, state, roundboxalign, true); } +static void widget_numbut_subbut(uiSubBut *sbut, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) +{ + uiWidgetBase wtb; + uiWidgetColors wcol_cpy = *wcol; + int half; + + if ((state & UI_ACTIVE) == 0 || (state & UI_TEXTINPUT)) + return; + + widget_init(&wtb); + + if (sbut->is_hovered) { + rcti circle_rect = *rect; + int origin_x, origin_y; + int size_x, size_y; + + /* smaller version of rect */ + BLI_rcti_scale(&circle_rect, 0.7f); + + size_x = BLI_rcti_size_x(&circle_rect); + size_y = BLI_rcti_size_y(&circle_rect); + origin_x = circle_rect.xmin + (size_x / 2); + origin_y = circle_rect.ymin + (size_y / 2); + + glColor4ub(UNPACK3((unsigned char *)wcol->item), wcol->item[3] * 0.8f); + glPushMatrix(); + glTranslatef(origin_x, origin_y, 0.0f); + + ui_draw_anti_circle(size_y / 2); + + glPopMatrix(); + } + + /* rect smaller */ + BLI_rcti_scale(rect, 0.4f); + /* offset rect a bit - looks better */ + BLI_rcti_translate(rect, (sbut->align == UI_SBUT_ALIGN_LEFT) ? -UI_DPI_FAC : UI_DPI_FAC, 0); + half = iroundf(BLI_rcti_size_y(rect) / 2); + + glColor4ubv((unsigned char *)(sbut->is_hovered ? wcol->inner : wcol_cpy.item)); + glEnable(GL_BLEND); + + if (sbut->type == UI_SBUT_TYPE_VAL_DECREASE) { + ui_draw_anti_tria(rect->xmin, rect->ymin + half, rect->xmax, rect->ymin, rect->xmax, rect->ymax); + } + else if (sbut->type == UI_SBUT_TYPE_VAL_INCREASE) { + ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmax, rect->ymin + half, rect->xmin, rect->ymax); + } + else { + BLI_assert(0); + } + + glDisable(GL_BLEND); +} + bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) { float dist, vec[4][2]; @@ -2736,9 +3072,9 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect)); if (horizontal) - rad = 0.5f * BLI_rcti_size_y(rect); + rad = wcol->roundness * BLI_rcti_size_y(rect); else - rad = 0.5f * BLI_rcti_size_x(rect); + rad = wcol->roundness * BLI_rcti_size_x(rect); wtb.draw_shadedir = (horizontal) ? true : false; @@ -2919,7 +3255,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s /* backdrop first */ /* fully rounded */ - offs = 0.5f * BLI_rcti_size_y(rect); + offs = wcol->roundness * BLI_rcti_size_y(rect); toffs = offs * 0.75f; round_box_edges(&wtb, roundboxalign, rect, offs); @@ -2971,11 +3307,13 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s if (!(state & UI_SELECT)) SWAP(short, wcol->shadetop, wcol->shadedown); } - + /* outline */ - wtb.draw_outline = true; - wtb.draw_inner = false; - widgetbase_draw(&wtb, wcol); + if (IFACE_STYLE_IS_CLASSIC) { + wtb.draw_outline = true; + wtb.draw_inner = false; + 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)) { @@ -3009,7 +3347,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat widget_init(&wtb); /* half rounded */ - rad = 0.25f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); ui_but_v3_get(but, col); @@ -3032,6 +3370,8 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat rgba_float_to_uchar((unsigned char *)wcol->inner, col); + /* always draw an outline for color buts to prevent them from being invisible */ + wtb.draw_outline = true; wcol->shaded = 0; wcol->alpha_check = (wcol->inner[3] < 255); @@ -3069,7 +3409,7 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i wtb.draw_outline = false; /* rounded */ - rad = 0.5f * BLI_rcti_size_y(rect); + rad = wcol->roundness * BLI_rcti_size_y(rect); round_box_edges(&wtb, UI_CNR_ALL, rect, rad); widgetbase_draw(&wtb, wcol); } @@ -3092,7 +3432,7 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun widget_init(&wtb); /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); @@ -3107,7 +3447,7 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), widget_init(&wtb); /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); /* decoration */ @@ -3127,7 +3467,7 @@ static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat widget_init(&wtb); /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); /* decoration */ @@ -3144,7 +3484,7 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat widget_init(&wtb); /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); wcol->inner[0] = min_ii(wcol->inner[0] + 15, 255); @@ -3163,7 +3503,7 @@ static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int { if (state & UI_ACTIVE) { uiWidgetBase wtb; - const float rad = 0.2f * U.widget_unit; + const float rad = wcol->roundness * U.widget_unit; widget_init(&wtb); @@ -3197,7 +3537,7 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r wtb.draw_emboss = false; - rad = 0.5f * BLI_rcti_size_y(rect); + rad = wcol->roundness * BLI_rcti_size_y(rect); round_box_edges(&wtb, UI_CNR_ALL, rect, rad); wcol->inner[3] *= fac; @@ -3213,15 +3553,14 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) { uiWidgetBase wtb; - float rad; + const float rad = wcol->roundness * U.widget_unit; widget_init(&wtb); /* rounded, but no outline */ wtb.draw_outline = false; - rad = 0.2f * U.widget_unit; round_box_edges(&wtb, UI_CNR_ALL, rect, rad); - + widgetbase_draw(&wtb, wcol); } @@ -3229,34 +3568,43 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN { uiWidgetBase wtb; rcti recttemp = *rect; - float rad; - int delta; - + const bool is_style_flat = IFACE_STYLE_IS_FLAT; + widget_init(&wtb); - + /* square */ recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp); - + /* smaller */ - delta = 1 + BLI_rcti_size_y(&recttemp) / 8; - recttemp.xmin += delta; - recttemp.ymin += delta; - recttemp.xmax -= delta; - recttemp.ymax -= delta; - - /* half rounded */ - rad = 0.2f * U.widget_unit; - round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad); - + BLI_rcti_scale(&recttemp, is_style_flat ? 0.8f : 0.7f); + + if (is_style_flat) { + /* draw circle as inner */ + glColor4ubv((unsigned char *)wcol->inner); + ui_draw_anti_circle_rect(&recttemp); + + /* adjust recttemp for decoration */ + BLI_rcti_translate(&recttemp, -0.1f * U.widget_unit, -0.1f * U.widget_unit); + BLI_rcti_scale(&recttemp, 0.9f); + } + else { + round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 0.2f * U.widget_unit); + } + /* decoration */ if (state & UI_SELECT) { widget_check_trias(&wtb.tria1, &recttemp); } - + + if (is_style_flat) { + /* disable inner as this was already drawn */ + wtb.draw_inner = false; + } widgetbase_draw(&wtb, wcol); - + /* text space */ - rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta; + rect->xmin += BLI_rcti_size_y(rect) * 0.7f; + rect->ymin += 0.1f * U.widget_unit; } /* labels use Editor theme colors for text */ @@ -3287,7 +3635,7 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), widget_init(&wtb); /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); @@ -3311,9 +3659,10 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED( } /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); + wtb.draw_outline = true; widgetbase_draw(&wtb, wcol); copy_v3_v3_char(wcol->inner, old_col); @@ -3323,20 +3672,35 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int { uiWidgetBase wtb; float rad; - + widget_init(&wtb); - + /* half rounded */ - rad = 0.2f * U.widget_unit; + rad = wcol->roundness * U.widget_unit; round_box_edges(&wtb, roundboxalign, rect, rad); - + + widgetbase_draw(&wtb, wcol); +} + +static void widget_toggle(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) +{ + uiWidgetBase wtb; + float rad; + + widget_init(&wtb); + + /* half rounded */ + rad = wcol->roundness * U.widget_unit; + round_box_edges(&wtb, roundboxalign, rect, rad); + + wtb.draw_outline = true; widgetbase_draw(&wtb, wcol); } static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) { uiWidgetBase wtb; - const float rad = 0.25f * U.widget_unit; + const float rad = wcol->roundness * U.widget_unit; widget_init(&wtb); @@ -3400,6 +3764,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_TOGGLE: wt.wcol_theme = &btheme->tui.wcol_toggle; + wt.draw = widget_toggle; break; case UI_WTYPE_CHECKBOX: @@ -3415,6 +3780,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_NUMBER: wt.wcol_theme = &btheme->tui.wcol_num; wt.draw = widget_numbut; + wt.subbut_draw = widget_numbut_subbut; break; case UI_WTYPE_SLIDER: @@ -3430,7 +3796,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_TOOLTIP: wt.wcol_theme = &btheme->tui.wcol_tooltip; - wt.draw = widget_menu_back; + wt.draw = widget_tooltip_back; break; @@ -3486,7 +3852,6 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_MENU_BACK: wt.wcol_theme = &btheme->tui.wcol_menu_back; - wt.draw = widget_menu_back; break; /* specials */ @@ -3609,7 +3974,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct widget_draw_text_icon(&style->widgetlabel, &tui->wcol_menu_back, but, rect); break; case UI_BTYPE_SEPR_LINE: - ui_draw_separator(rect, &tui->wcol_menu_item); + ui_draw_separator(rect, &tui->wcol_menu_back); break; default: wt = widget_type(UI_WTYPE_MENU_ITEM); @@ -3839,6 +4204,16 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct else if (wt->draw) wt->draw(&wt->wcol, rect, state, roundboxalign); + /* draw sub-buts */ + if (wt->subbut_draw && but->subbuts.first) { + uiSubBut *sbut; + for (sbut = but->subbuts.first; sbut; sbut = sbut->next) { + rcti sbut_rect; + ui_rcti_to_pixelrect(ar, but->block, &sbut_rect, &sbut->rect); + wt->subbut_draw(sbut, &wt->wcol, &sbut_rect, state, roundboxalign); + } + } + if (disabled) glEnable(GL_BLEND); wt->text(fstyle, &wt->wcol, but, rect); @@ -3851,27 +4226,22 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct } } -void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) +void ui_draw_menu_back(struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect) { uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK); - + wt->state(wt, 0); - if (block) - wt->draw(&wt->wcol, rect, block->flag, block->direction); - else - wt->draw(&wt->wcol, rect, 0, 0); - - if (block) { - if (block->flag & UI_BLOCK_CLIPTOP) { - /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't'); - } - if (block->flag & UI_BLOCK_CLIPBOTTOM) { - /* XXX no scaling for UI here yet */ - glColor3ubv((unsigned char *)wt->wcol.text); - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v'); - } + widget_menu_back(&wt->wcol, block, rect); + + if (block->flag & UI_BLOCK_CLIPTOP) { + /* XXX no scaling for UI here yet */ + glColor3ubv((unsigned char *)wt->wcol.text); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't'); + } + if (block->flag & UI_BLOCK_CLIPBOTTOM) { + /* XXX no scaling for UI here yet */ + glColor3ubv((unsigned char *)wt->wcol.text); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v'); } } @@ -4020,7 +4390,7 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) uiWidgetType *wt = widget_type(UI_WTYPE_BOX); glEnable(GL_BLEND); - widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit); + widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit, IFACE_STYLE_IS_CLASSIC); glDisable(GL_BLEND); wt->state(wt, 0); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 5eaee734789..e8a599c9747 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -171,6 +171,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo } switch (colorid) { + case TH_AREA_EDGES: + cp = btheme->tui.area_edges; + break; + case TH_BACK: if (theme_regionid == RGN_TYPE_WINDOW) cp = ts->back; @@ -798,6 +802,11 @@ static void ui_theme_init_new_do(ThemeSpace *ts) rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255); rgba_char_args_set(ts->tab_back, 64, 64, 64, 255); rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255); + + /* XXX maybe remove show_back/show_header options? */ + ts->panelcolors.show_back = ts->panelcolors.show_header = true; + rgba_char_args_set(ts->panelcolors.back, 128, 128, 128, 255); + rgba_char_args_set(ts->panelcolors.header, 97, 97, 97, 255); } static void ui_theme_init_new(bTheme *btheme) @@ -846,7 +855,9 @@ void ui_theme_init_default(void) /* UI buttons */ ui_widget_color_init(&btheme->tui); - + + rgba_char_args_set_fl(btheme->tui.area_edges, 0.15f, 0.15f, 0.15f, 1.0f); + btheme->tui.iconfile[0] = 0; btheme->tui.panel.show_back = false; btheme->tui.panel.show_header = false; @@ -870,10 +881,6 @@ void ui_theme_init_default(void) ui_theme_init_new(btheme); /* space view3d */ - btheme->tv3d.panelcolors.show_back = false; - btheme->tv3d.panelcolors.show_header = false; - rgba_char_args_set_fl(btheme->tv3d.panelcolors.back, 0.45, 0.45, 0.45, 0.5); - rgba_char_args_set_fl(btheme->tv3d.panelcolors.header, 0, 0, 0, 0.01); rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0); rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255); rgba_char_args_set(btheme->tv3d.text_hi, 255, 255, 255, 255); @@ -2639,6 +2646,26 @@ void init_userdef_do_versions(void) U.node_margin = 80; } + if (U.versionfile < 275 || (U.versionfile == 275 && U.subversionfile < 5)) { + bTheme *btheme; + ThemeSpace *ts; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) { + /* XXX maybe remove show_back/show_header options? */ + ts->panelcolors.show_back = ts->panelcolors.show_header = true; + rgba_char_args_set(ts->panelcolors.back, 128, 128, 128, 255); + rgba_char_args_set(ts->panelcolors.header, 97, 97, 97, 255); + } + + rgba_char_args_set_fl(btheme->tui.area_edges, 0.10f, 0.10f, 0.10f, 1.0f); + + btheme->tui.interface_style = TH_IFACE_STYLE_FLAT; + + ui_widget_color_init(&btheme->tui); + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 5f0c3ff6993..a0439d106a9 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -152,18 +152,21 @@ static void view2d_masks(View2D *v2d, int check_scrollers) * - if they overlap, they must not occupy the corners (which are reserved for other widgets) */ if (scroll) { + const int scroll_width = (v2d->flag & V2D_USES_UNITS_VERTICAL) ? V2D_SCROLL_WIDTH_TEXT : V2D_SCROLL_WIDTH; + const int scroll_height = (v2d->flag & V2D_USES_UNITS_HORIZONTAL) ? V2D_SCROLL_HEIGHT_TEXT : V2D_SCROLL_HEIGHT; + /* vertical scroller */ if (scroll & V2D_SCROLL_LEFT) { /* on left-hand edge of region */ v2d->vert = v2d->mask; - v2d->vert.xmax = V2D_SCROLL_WIDTH; + v2d->vert.xmax = scroll_width; v2d->mask.xmin = v2d->vert.xmax + 1; } else if (scroll & V2D_SCROLL_RIGHT) { /* on right-hand edge of region */ v2d->vert = v2d->mask; v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */ - v2d->vert.xmin = v2d->vert.xmax - V2D_SCROLL_WIDTH; + v2d->vert.xmin = v2d->vert.xmax - scroll_width; v2d->mask.xmax = v2d->vert.xmin - 1; } @@ -171,13 +174,13 @@ static void view2d_masks(View2D *v2d, int check_scrollers) if (scroll & (V2D_SCROLL_BOTTOM)) { /* on bottom edge of region */ v2d->hor = v2d->mask; - v2d->hor.ymax = V2D_SCROLL_HEIGHT; + v2d->hor.ymax = scroll_height; v2d->mask.ymin = v2d->hor.ymax + 1; } else if (scroll & V2D_SCROLL_TOP) { /* on upper edge of region */ v2d->hor = v2d->mask; - v2d->hor.ymin = v2d->hor.ymax - V2D_SCROLL_HEIGHT; + v2d->hor.ymin = v2d->hor.ymax - scroll_height; v2d->mask.ymax = v2d->hor.ymin - 1; } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 79d6b845361..a008f90617b 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -78,33 +78,31 @@ extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, static void region_draw_emboss(const ARegion *ar, const rcti *scirct) { rcti rect; - + + if (!ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_PROPS)) + return; + /* translate scissor rect to region space */ rect.xmin = scirct->xmin - ar->winrct.xmin; rect.ymin = scirct->ymin - ar->winrct.ymin; rect.xmax = scirct->xmax - ar->winrct.xmin; rect.ymax = scirct->ymax - ar->winrct.ymin; - + /* set transp line */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* right */ - glColor4ub(0, 0, 0, 30); - sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax); - + glColor4ub(0, 0, 0, 50); + /* bottom */ - glColor4ub(0, 0, 0, 30); - sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin); - + if (ar->alignment == RGN_ALIGN_TOP) { + sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin); + } /* top */ - glColor4ub(255, 255, 255, 30); - sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax); + else { + BLI_assert(ar->alignment == RGN_ALIGN_BOTTOM); + sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax); + } - /* left */ - glColor4ub(255, 255, 255, 30); - sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax); - glDisable(GL_BLEND); } @@ -1729,7 +1727,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c Panel *panel; View2D *v2d = &ar->v2d; View2DScrollers *scrollers; - int x, y, xco, yco, w, em, triangle; + int x, y, xco, yco, w, em; bool is_context_new = 0; int redo; int scroll; @@ -1818,7 +1816,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c em = (ar->type->prefsizex) ? 10 : 20; } - w -= margin_x; + w -= margin_x + UI_PANEL_MARGIN * 2.0f; /* create panels */ UI_panels_begin(C, ar); @@ -1842,24 +1840,28 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS); panel = UI_panel_begin(sa, ar, block, pt, panel, &open); - /* bad fixed values */ - triangle = (int)(UI_UNIT_Y * 1.1f); - if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + const int ar_x = (int)BLI_rctf_size_x(&ar->v2d.cur); + const int ofs_x = iroundf(MIN2(UI_UNIT_X * 0.6f, ar_x * 0.1f)); + /* using panel->sizex causes too much jittering */ + const int panel_sizex = ar_x - (int)(UI_PANEL_MARGIN * 2.0f); + /* for enabled buttons */ - panel->layout = UI_block_layout( - block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, - triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style); + uiLayout *row; + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, + -ofs_x, (UI_UNIT_Y * 1.1f) + style->panelspace, + panel_sizex, 1, 0, style); + + + row = uiLayoutRow(layout, 1); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); + panel->layout = row; pt->draw_header(C, panel); - UI_block_layout_resolve(block, &xco, &yco); - panel->labelofs = xco - triangle; panel->layout = NULL; } - else { - panel->labelofs = 0; - } if (open) { short panelContext; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index ae0d2619645..4429c04bcf9 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -63,6 +63,7 @@ #include "ED_render.h" #include "UI_interface.h" +#include "UI_resources.h" /* XXX actually should be not here... solve later */ #include "wm_subwindow.h" @@ -1010,47 +1011,38 @@ static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir)) glDisable(GL_BLEND); } -static void drawscredge_area_draw(int sizex, int sizey, int x1, int y1, int x2, int y2, int a) +static void drawscredge_area_draw(int sizex, int sizey, int x1, int y1, int x2, int y2) { /* right border area */ if (x2 < sizex - 1) - sdrawline(x2 + a, y1, x2 + a, y2); + sdrawline(x2, y1, x2, y2); /* left border area */ if (x1 > 0) /* otherwise it draws the emboss of window over */ - sdrawline(x1 + a, y1, x1 + a, y2); + sdrawline(x1, y1, x1, y2); /* top border area */ if (y2 < sizey - 1) - sdrawline(x1, y2 + a, x2, y2 + a); + sdrawline(x1, y2, x2, y2); /* bottom border area */ if (y1 > 0) - sdrawline(x1, y1 + a, x2, y1 + a); + sdrawline(x1, y1, x2, y1); } /** screen edges drawing **/ -static void drawscredge_area(ScrArea *sa, int sizex, int sizey, int center) +static void drawscredge_area(ScrArea *sa, int sizex, int sizey) { short x1 = sa->v1->vec.x; short y1 = sa->v1->vec.y; short x2 = sa->v3->vec.x; short y2 = sa->v3->vec.y; - - if (center == 0) { - if (U.pixelsize > 1.0f) { - - glColor3ub(0x50, 0x50, 0x50); - glLineWidth((2.0f * U.pixelsize) - 1); - drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0); - glLineWidth(1.0f); - } - } - else { - glColor3ub(0, 0, 0); - drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0); - } + + glLineWidth(UI_DPI_FAC * 2.0f); + UI_ThemeColor(TH_AREA_EDGES); + drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2); + glLineWidth(1.0f); } /* ****************** EXPORTED API TO OTHER MODULES *************************** */ @@ -1133,10 +1125,8 @@ void ED_screen_draw(wmWindow *win) if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; - drawscredge_area(sa, winsize_x, winsize_y, 0); + drawscredge_area(sa, winsize_x, winsize_y); } - for (sa = win->screen->areabase.first; sa; sa = sa->next) - drawscredge_area(sa, winsize_x, winsize_y, 1); /* blended join arrow */ if (sa1 && sa2) { diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 5d0b34a2e0c..af16f9cf73a 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -118,7 +118,7 @@ static SpaceLink *action_new(const bContext *C) ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; ar->v2d.align = V2D_ALIGN_NO_POS_Y; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + ar->v2d.flag = (V2D_VIEWSYNC_AREA_VERTICAL | V2D_USES_UNITS_HORIZONTAL); return (SpaceLink *)saction; } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index f119fe23c12..96c7e99c917 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -104,7 +104,7 @@ static void init_preview_region(const bContext *C, ARegion *ar) ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; ar->v2d.align = V2D_ALIGN_NO_POS_Y; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + ar->v2d.flag = (V2D_VIEWSYNC_AREA_VERTICAL | V2D_USES_UNITS_HORIZONTAL); } else { ar->v2d.tot.xmin = 0.0f; @@ -128,7 +128,7 @@ static void init_preview_region(const bContext *C, ARegion *ar) ar->v2d.keepzoom = 0; ar->v2d.keepofs = 0; ar->v2d.align = 0; - ar->v2d.flag = 0; + ar->v2d.flag = (V2D_USES_UNITS_HORIZONTAL | V2D_USES_UNITS_VERTICAL); ar->v2d.keeptot = 0; } @@ -143,8 +143,8 @@ static void reinit_preview_region(const bContext *C, ARegion *ar) init_preview_region(C, ar); } else { - if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) - init_preview_region(C, ar); + /* XXX check with sergey */ + init_preview_region(C, ar); } } diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 4c7ac532411..e3866e6e469 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -156,6 +156,7 @@ static SpaceLink *graph_new(const bContext *C) ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.flag |= (V2D_USES_UNITS_HORIZONTAL | V2D_USES_UNITS_VERTICAL); ar->v2d.keeptot = 0; diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 3aaa7c24219..5a222c3ef09 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -292,9 +292,7 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * Image *image = image_p; int slot; - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - uiItemS(layout); + uiDefMenuTitleBut(block, IFACE_("Slot")); slot = IMA_MAX_RENDER_SLOT; while (slot--) { @@ -346,9 +344,7 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Layer"), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - uiItemS(layout); + uiDefMenuTitleBut(block, IFACE_("Layer")); nr = BLI_listbase_count(&rr->layers) - 1; fake_name = ui_imageuser_layer_fake_name(rr); @@ -413,10 +409,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pass"), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - - uiItemS(layout); + uiDefMenuTitleBut(block, IFACE_("Pass")); nr = (rl ? BLI_listbase_count(&rl->passes) : 0) - 1; fake_name = ui_imageuser_pass_fake_name(rl); @@ -472,10 +465,7 @@ static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, voi UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - - uiItemS(layout); + uiDefMenuTitleBut(block, IFACE_("View")); nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1; for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) { @@ -498,10 +488,7 @@ static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layo UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"), - 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - - uiItemS(layout); + uiDefMenuTitleBut(block, IFACE_("View")); nr = BLI_listbase_count(&image->views) - 1; for (iv = image->views.last; iv; iv = iv->prev, nr--) { diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 19e6f5a8100..6c00e698cef 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -2236,7 +2236,6 @@ static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const w /* add entry to add this type of modifier */ uiItemEnumO(layout, "NLA_OT_fmodifier_add", fmi->name, 0, "type", i); } - uiItemS(layout); UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 9fc7b5d6f8f..08b2c4d0c65 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -158,7 +158,7 @@ static SpaceLink *nla_new(const bContext *C) ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; ar->v2d.align = V2D_ALIGN_NO_POS_Y; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + ar->v2d.flag = (V2D_VIEWSYNC_AREA_VERTICAL | V2D_USES_UNITS_HORIZONTAL); return (SpaceLink *)snla; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 9b6c61c7af0..216668f3271 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -190,6 +190,7 @@ static SpaceLink *sequencer_new(const bContext *C) ar->v2d.keepzoom = 0; ar->v2d.keeptot = 0; ar->v2d.align = V2D_ALIGN_NO_NEG_Y; + ar->v2d.flag |= (V2D_USES_UNITS_HORIZONTAL | V2D_USES_UNITS_VERTICAL); return (SpaceLink *)sseq; } diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 91a09708e1d..dbd6bff2a93 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -671,6 +671,7 @@ static SpaceLink *time_new(const bContext *C) ar->v2d.align |= V2D_ALIGN_NO_NEG_Y; ar->v2d.keepofs |= V2D_LOCKOFS_Y; ar->v2d.keepzoom |= V2D_LOCKZOOM_Y; + ar->v2d.flag |= V2D_USES_UNITS_HORIZONTAL; return (SpaceLink *)stime; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 45b3aad92e4..25e88825304 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -102,9 +102,9 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */ char panelname[64], tabname[64]; /* defined as UI_MAX_NAME_STR */ char drawname[64]; /* panelname is identifier for restoring location */ int ofsx, ofsy, sizex, sizey; - short labelofs, pad; short flag, runtime_flag; - short control; + short mouse_state; /* is mouse inside header/content/...? */ + short control, pad; short snap; int sortorder; /* panels are aligned according to increasing sortorder */ struct Panel *paneltab; /* this panel is tabbed in *paneltab */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index bc2c7463e7f..6acc4c618a7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -128,7 +128,9 @@ typedef struct uiWidgetColors { char text_sel[4]; short shaded; short shadetop, shadedown; - short alpha_check; + short pad; + float roundness; + short alpha_check, pad2; } uiWidgetColors; typedef struct uiWidgetStateColors { @@ -168,6 +170,11 @@ typedef struct ThemeUI { uiPanelColors panel; /* depricated, but we keep it for do_versions (2.66.1) */ + short interface_style; /* flat/classic - don't confuse with uiStyle */ + short pad2; + + char area_edges[4]; + char widget_emboss[4]; /* fac: 0 - 1 for blend factor, width in pixels */ @@ -897,6 +904,11 @@ typedef enum eOpensubdiv_Computee_Type { USER_OPENSUBDIV_COMPUTE_GLSL_COMPUTE = 6, } eOpensubdiv_Computee_Type; +typedef enum eTheme_InterfaceStyle { + TH_IFACE_STYLE_CLASSIC = 0, + TH_IFACE_STYLE_FLAT = 1, +} eTheme_InterfaceStyle; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h index 6f2e347c84d..4a019476ee7 100644 --- a/source/blender/makesdna/DNA_view2d_types.h +++ b/source/blender/makesdna/DNA_view2d_types.h @@ -114,6 +114,9 @@ typedef struct View2D { #define V2D_PIXELOFS_Y (1<<3) /* view settings need to be set still... */ #define V2D_IS_INITIALISED (1<<10) + /* for screens that need to draw units on top of the scroller */ +#define V2D_USES_UNITS_VERTICAL (1 << 11) +#define V2D_USES_UNITS_HORIZONTAL (1 << 12) /* scroller flags for View2D (v2d->scroll) */ /* left scrollbar */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index b4ae82290fd..6a1f9650752 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -906,6 +906,11 @@ static void rna_def_userdef_theme_ui_wcol(BlenderRNA *brna) RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_text(prop, "Shade Down", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "roundness", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.1f, 0.5f); + RNA_def_property_ui_text(prop, "Roundness", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna) @@ -964,10 +969,12 @@ static void rna_def_userdef_theme_ui_panel(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Theme Panel Color", "Theme settings for panel colors"); prop = RNA_def_property(srna, "header", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Header", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Background", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); @@ -1011,6 +1018,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem interface_style_items[] = { + {TH_IFACE_STYLE_CLASSIC, "CLASSIC", 0, "Classic", "Use a classic interface drawing style"}, + {TH_IFACE_STYLE_FLAT, "FLAT", 0, "Flat", "Use a flat interface drawing style"}, + {0, NULL, 0, NULL, NULL} + }; + rna_def_userdef_theme_ui_wcol(brna); rna_def_userdef_theme_ui_wcol_state(brna); rna_def_userdef_theme_ui_panel(brna); @@ -1116,6 +1129,18 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_ui_text(prop, "State Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "interface_style", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "interface_style"); + RNA_def_property_enum_items(prop, interface_style_items); + RNA_def_property_ui_text(prop, "Interface Style", "Adjusts the interface drawing for different styles"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "area_edges", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "area_edges"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Area Edges", "Color of the 1px separator between areas"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "menu_shadow_fac", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Menu Shadow Strength", "Blending factor for menu shadows"); RNA_def_property_range(prop, 0.01f, 1.0f); |