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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py15
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py3
-rw-r--r--source/blender/blenloader/intern/versioning_270.c42
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c9
-rw-r--r--source/blender/editors/armature/pose_group.c4
-rw-r--r--source/blender/editors/include/UI_interface.h12
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/include/UI_view2d.h6
-rw-r--r--source/blender/editors/interface/interface.c106
-rw-r--r--source/blender/editors/interface/interface_draw.c87
-rw-r--r--source/blender/editors/interface/interface_handlers.c297
-rw-r--r--source/blender/editors/interface/interface_intern.h39
-rw-r--r--source/blender/editors/interface/interface_layout.c77
-rw-r--r--source/blender/editors/interface/interface_panel.c312
-rw-r--r--source/blender/editors/interface/interface_regions.c79
-rw-r--r--source/blender/editors/interface/interface_templates.c6
-rw-r--r--source/blender/editors/interface/interface_widgets.c783
-rw-r--r--source/blender/editors/interface/resources.c69
-rw-r--r--source/blender/editors/interface/view2d.c16
-rw-r--r--source/blender/editors/interface/view2d_ops.c10
-rw-r--r--source/blender/editors/screen/CMakeLists.txt1
-rw-r--r--source/blender/editors/screen/SConscript1
-rw-r--r--source/blender/editors/screen/area.c97
-rw-r--r--source/blender/editors/screen/screen_edit.c36
-rw-r--r--source/blender/editors/space_action/space_action.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c8
-rw-r--r--source/blender/editors/space_graph/space_graph.c1
-rw-r--r--source/blender/editors/space_image/image_buttons.c23
-rw-r--r--source/blender/editors/space_nla/nla_edit.c1
-rw-r--r--source/blender/editors/space_nla/space_nla.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_time/space_time.c1
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c48
-rw-r--r--source/blender/makesdna/DNA_screen_types.h8
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h29
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_screen.c1
-rw-r--r--source/blender/makesrna/intern/rna_space.c36
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c32
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c86
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c3
42 files changed, 1869 insertions, 530 deletions
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 75381a2356e..7a44689e448 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -72,7 +72,7 @@ class USERPREF_HT_header(Header):
class USERPREF_PT_tabs(Panel):
bl_label = ""
bl_space_type = 'USER_PREFERENCES'
- bl_region_type = 'WINDOW'
+ bl_region_type = 'TABS'
bl_options = {'HIDE_HEADER'}
def draw(self, context):
@@ -80,7 +80,7 @@ class USERPREF_PT_tabs(Panel):
userpref = context.user_preferences
- layout.prop(userpref, "active_section", expand=True)
+ layout.prop_tabs(userpref, "active_section")
class USERPREF_MT_interaction_presets(Menu):
@@ -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 bb0ad001c34..7cca831257a 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/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index fabef392601..3bf24d3574f 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -868,7 +868,49 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+ {
+ 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;
+ }
+ }
+ }
+ }
+ }
{
if (!DNA_struct_elem_find(fd->filesdna, "SpaceNode", "float", "backdrop_zoom")) {
bScreen *sc;
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 01af11e78d1..c32b3ac51cf 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 6320724967c..8125ab4297e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -135,8 +135,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 */
@@ -181,13 +182,17 @@ 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)
+#define UI_TAB_REGION_MARGIN_HEIGHT (U.widget_unit * 1.15f)
+
/* but->drawflag - these flags should only affect how the button is drawn. */
/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions
* (except for the 'align' ones)!
@@ -249,6 +254,7 @@ typedef enum {
UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */
UI_BTYPE_CHECKBOX_N = (14 << 9),
UI_BTYPE_COLOR = (15 << 9),
+ UI_BTYPE_TAB = (16 << 9),
UI_BTYPE_SCROLL = (18 << 9),
UI_BTYPE_BLOCK = (19 << 9),
UI_BTYPE_LABEL = (20 << 9),
@@ -634,6 +640,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);
@@ -961,6 +968,7 @@ void uiItemEnumR_prop(uiLayout *layout, const char *name, int icon, struct Point
void uiItemEnumR(uiLayout *layout, const char *name, int icon, struct PointerRNA *ptr, const char *propname, int value);
void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, const char *name, int icon);
void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
+void uiItemTabsR(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, const char *name, int icon, int alignment, int icon_only);
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon);
void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, struct IDProperty *properties, int context, int flag);
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 4caacb65f5f..7335233a215 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 1fccf0fb2d0..0ee4a30d005 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;
@@ -1327,6 +1334,42 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
+/* 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)
{
@@ -1448,6 +1491,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
@@ -2273,6 +2317,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) {
@@ -2564,6 +2614,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_freeN(but->dragpoin);
}
+ 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);
@@ -2973,6 +3027,9 @@ static void ui_block_align_calc_but(uiBut *first, short nr)
/* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */
for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) {
+ if (but->type == UI_BTYPE_TAB)
+ continue;
+
next = but->next;
if (next && next->alignnr != nr)
next = NULL;
@@ -3154,6 +3211,25 @@ void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max)
*max = max_fff(UNPACK3(pixel));
}
+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
*
@@ -3268,6 +3344,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,
@@ -3306,7 +3389,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);
}
}
@@ -3369,9 +3452,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 */
@@ -3577,7 +3658,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)) {
@@ -4310,6 +4391,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);
@@ -4317,7 +4409,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);
@@ -4349,7 +4441,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_draw.c b/source/blender/editors/interface/interface_draw.c
index 66140742e26..968b3ea1934 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -403,6 +403,93 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
+void ui_draw_but_TAB_outline(rcti *rect, float rad, int roundboxtype, unsigned char highlight[3],
+ unsigned char highlight_fade[3])
+{
+ float vec[4][2] = {
+ {0.195, 0.02},
+ {0.55, 0.169},
+ {0.831, 0.45},
+ {0.98, 0.805},
+ };
+ int a;
+ /* the 1px offset makes sure its inside the button, because it doesn't draw nicely outside */
+ int minx = rect->xmin + 1, maxx = rect->xmax - 1;
+ int miny = rect->ymin + 1, maxy = rect->ymax - 1;
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_LINE_STRIP);
+
+ glColor3ubv(highlight);
+
+ /*start with corner left-top*/
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ glVertex2f(minx, maxy - rad);
+ for (a = 0; a < 4; a++) {
+ glVertex2f(minx + vec[a][1], maxy - rad + vec[a][0]);
+ }
+ glVertex2f(minx + rad, maxy);
+ }
+ else {
+ glVertex2f(minx, maxy);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ glVertex2f(maxx - rad, maxy);
+ for (a = 0; a < 4; a++) {
+ glVertex2f(maxx - rad + vec[a][0], maxy - vec[a][1]);
+ }
+ glVertex2f(maxx, maxy - rad);
+ }
+ else {
+ glVertex2f(maxx, maxy);
+ }
+
+ glColor3ubv(highlight_fade);
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ glVertex2f(maxx, miny + rad);
+ for (a = 0; a < 4; a++) {
+ glVertex2f(maxx - vec[a][1], miny + rad - vec[a][0]);
+ }
+ glVertex2f(maxx - rad, miny);
+ }
+ else {
+ glVertex2f(maxx, miny);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ glVertex2f(minx + rad, miny);
+ for (a = 0; a < 4; a++) {
+ glVertex2f(minx + rad - vec[a][0], miny + vec[a][1]);
+ }
+ glVertex2f(minx, miny + rad);
+ }
+ else {
+ glVertex2f(minx, miny);
+ }
+
+ glColor3ubv(highlight);
+
+ /* back to corner left-top */
+ glVertex2f(minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
+
+ glEnd();
+ glShadeModel(GL_FLAT);
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+}
+
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
#ifdef WITH_HEADLESS
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 010bb8b37f1..b2688619e7a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -384,6 +384,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(
@@ -2055,6 +2056,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
ui_apply_but_ROW(C, block, but, data);
break;
case UI_BTYPE_SCROLL:
@@ -3726,6 +3728,17 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
return WM_UI_HANDLER_CONTINUE;
}
+static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) {
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -4266,68 +4279,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 - (UI_PRECISION_FLOAT_SCALE * 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 + (UI_PRECISION_FLOAT_SCALE * 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;
}
@@ -4337,6 +4290,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,
@@ -6502,6 +6489,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)*/
@@ -6524,6 +6512,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;
@@ -6563,7 +6554,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 */
@@ -6579,6 +6570,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLT_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)) {
@@ -6592,11 +6585,13 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLT_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_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"),
@@ -6615,12 +6610,14 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_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_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
@@ -6637,12 +6634,14 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_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_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"),
@@ -6658,10 +6657,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_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
@@ -6729,6 +6730,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
"please use User Preferences otherwise"));
UI_but_flag_enable(but2, UI_BUT_DISABLED);
}
+
+ 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)) {
@@ -6736,11 +6739,15 @@ static bool ui_but_menu(bContext *C, uiBut *but)
CTX_IFACE_(BLT_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);
@@ -6785,8 +6792,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;
@@ -6930,6 +6962,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);
@@ -6940,6 +6982,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
+ case UI_BTYPE_TAB:
+ retval = ui_do_but_TAB(C, but, data, event);
+ break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_ICON_TOGGLE:
@@ -7204,6 +7249,24 @@ uiBut *ui_but_find_active_in_region(ARegion *ar)
return NULL;
}
+uiBut *ui_but_find_activated_tab(const ARegion *ar)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ if (ar->regiontype == RGN_TYPE_TABS) {
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_TAB && but->flag & UI_SELECT) {
+ return but;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
bool ui_but_is_active(ARegion *ar)
{
return (ui_but_find_active_in_region(ar) != NULL);
@@ -7408,6 +7471,26 @@ 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];
+
+ /* XXX (julian) */
+// 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_ex(ARegion *ar, int x, int y)
{
uiBlock *block;
@@ -8095,6 +8178,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;
@@ -8141,6 +8249,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:
@@ -9669,6 +9781,46 @@ static int ui_handle_menus_recursive(
/* *************** UI event handlers **************** */
+static int ui_tab_region_handler(bContext *C, const wmEvent *event, ARegion *ar)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ uiBut *nextbut, *but = NULL;
+
+ if (ar->regiontype == RGN_TYPE_TABS);
+ else if ((sa->flag & AREA_CONTAINS_TABS) && event->ctrl)
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TABS);
+ else
+ return WM_UI_HANDLER_CONTINUE;
+
+ but = ui_but_find_activated_tab(ar);
+
+ if (!but) {
+ WM_event_add_mousemove(C);
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
+ if (event->type == WHEELUPMOUSE) {
+ if (but->next == NULL)
+ nextbut = but->block->buttons.first;
+ else
+ nextbut = but->next;
+ }
+ else {
+ if (but->prev == NULL)
+ nextbut = but->block->buttons.last;
+ else
+ nextbut = but->prev;
+ }
+
+ ui_handle_button_activate(C, ar, nextbut, BUTTON_ACTIVATE_APPLY);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
@@ -9689,6 +9841,9 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use
retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
+ if (retval == WM_UI_HANDLER_CONTINUE)
+ retval = ui_tab_region_handler(C, event, ar);
+
if (retval == WM_UI_HANDLER_CONTINUE && listbox)
retval = ui_handle_list_event(C, event, ar, listbox);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 99316b1f748..811b3583c5d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -71,6 +71,7 @@ typedef enum {
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
UI_WTYPE_EXEC,
+ UI_WTYPE_TAB,
UI_WTYPE_TOOLTIP,
/* strings */
@@ -101,6 +102,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 +127,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 {
@@ -204,8 +222,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;
@@ -446,11 +479,14 @@ 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_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect);
+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);
@@ -655,6 +691,7 @@ void ui_but_clipboard_free(void);
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
+uiBut *ui_but_find_activated_tab(const struct ARegion *ar);
#ifdef WITH_INPUT_IME
void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete);
@@ -671,6 +708,8 @@ void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *re
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol);
void ui_draw_link_bezier(const rcti *rect);
+void ui_draw_but_TAB_outline(rcti *rect, float rad, int roundboxtype, unsigned char highlight[3],
+ unsigned char highlight_fade[3]);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 67b4f183c82..593138869a8 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 {
@@ -1465,6 +1493,45 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
* we don't know the context this is called in */
}
+void uiItemTabsR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, const char *name,
+ int icon, int alignment, int icon_only)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but;
+ EnumPropertyItem *item, *item_array;
+ int itemw, value, h = UI_UNIT_Y;
+ bool free;
+
+ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
+
+ UI_block_layout_set_current(block, ui_item_local_sublayout(layout, layout, 1));
+
+ for (item = item_array; item->identifier; item++) {
+ if (!item->identifier[0])
+ continue;
+
+ name = (!name || name[0]) ? item->name : "";
+ icon = item->icon;
+ value = item->value;
+ itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0);
+
+ if (icon && name[0] && !icon_only)
+ but = uiDefIconTextButR_prop(block, UI_BTYPE_TAB, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ else if (icon)
+ but = uiDefIconButR_prop(block, UI_BTYPE_TAB, 0, icon, 0, 0, 1.3f * itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+ else
+ but = uiDefButR_prop(block, UI_BTYPE_TAB, 0, name, 0, 0, 0.9f * itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL);
+
+ if (RNA_property_flag(prop) & PROP_ENUM_FLAG)
+ UI_but_func_set(but, ui_item_enum_expand_handle, but, SET_INT_IN_POINTER(value));
+
+ but->drawflag |= alignment;
+ }
+
+ if (free)
+ MEM_freeN(item_array);
+}
+
/* Pointer RNA button with search */
typedef struct CollItemSearch {
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5ee7556a042..d9f4689748f 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,10 @@ 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 || ar->regiontype == RGN_TYPE_TABS) ?
+ 0 : UI_PANEL_MARGIN));
if (has_category_tabs) {
if (align == BUT_VERTICAL) {
@@ -865,10 +957,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 +1404,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 +1437,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;
}
@@ -1903,13 +1995,21 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
}
}
+ /* 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);
@@ -1922,10 +2022,22 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
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) {
@@ -1944,13 +2056,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
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;
@@ -1960,12 +2072,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
/* 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;
@@ -1973,7 +2085,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
}
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 40e4da2de94..bfaf03cdce0 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1402,6 +1402,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 {
@@ -1409,8 +1413,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);
@@ -1478,35 +1486,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) {
@@ -2700,14 +2714,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 1238b883e9a..e69fbf7fb8f 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 5d37f5c0fcf..008f129904b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_screen.h"
#include "RNA_access.h"
@@ -64,6 +65,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 +127,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 +237,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 +278,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 +576,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 +585,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 +708,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 +756,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 +971,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 +1579,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 +1684,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 +1735,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);
@@ -1620,9 +1774,13 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
+
+ /* if a widget uses font shadow it has to be deactivated now */
+ BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
+#undef WITH_ICON_TEXT_ALIGNMENT
/* *********************** widget types ************************************* */
@@ -1641,26 +1799,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 +1837,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 +1853,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 +1870,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 +1887,10 @@ static struct uiWidgetColors wcol_pulldown = {
{0, 0, 0, 255},
0,
- 25, -20
+ 25, -20,
+
+ 0, /* pad */
+ 0.2f
};
/* button inside menu */
@@ -1728,21 +1904,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 +1938,10 @@ static struct uiWidgetColors wcol_pie_menu = {
{255, 255, 255, 255},
1,
- 10, -10
+ 10, -10,
+
+ 0, /* pad */
+ 0.5f
};
@@ -1771,7 +1956,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 +1972,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 +1988,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 +2004,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 +2036,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 +2068,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,6 +2084,22 @@ static struct uiWidgetColors wcol_list_item = {
{0, 0, 0, 255},
0,
+ 0, 0,
+
+ 0, /* pad */
+ 0.2f
+};
+
+static struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255},
+ {114, 114, 114, 255},
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255},
+ {0, 0, 0, 255},
+
+ 0,
0, 0
};
@@ -1889,7 +2114,10 @@ static struct uiWidgetColors wcol_tmp = {
{255, 255, 255, 255},
0,
- 0, 0
+ 0, 0,
+
+ 0, /* pad */
+ 0.2f
};
@@ -1900,6 +2128,7 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_tool = wcol_tool;
tui->wcol_text = wcol_text;
tui->wcol_radio = wcol_radio;
+ tui->wcol_tab = wcol_tab;
tui->wcol_option = wcol_option;
tui->wcol_toggle = wcol_toggle;
tui->wcol_num = wcol_num;
@@ -2129,11 +2358,32 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
}
}
+static void widget_state_tab(uiWidgetType *wt, int state)
+{
+ unsigned char col_tab_active[4], col_tab_inactive[4], col_tab_text[3];
+
+ /* tabs are using special theme colors */
+ UI_GetThemeColor4ubv(TH_TAB_ACTIVE, col_tab_active);
+ UI_GetThemeColor4ubv(TH_TAB_INACTIVE, col_tab_inactive);
+ UI_GetThemeColor3ubv(TH_TEXT, col_tab_text); /* updates the font color to always match the region color */
+
+ copy_v3_v3_char(wt->wcol_theme->inner, (char *)col_tab_inactive);
+ copy_v3_v3_char(wt->wcol_theme->inner_sel, (char *)col_tab_active);
+ copy_v3_v3_char(wt->wcol_theme->text, (char *)col_tab_text);
+
+ wt->wcol = *(wt->wcol_theme);
+
+ if (state & UI_SELECT)
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ else if (state & UI_ACTIVE)
+ widget_state_blend(wt->wcol.inner, wt->wcol.inner_sel, 0.2f);
+}
+
/* ************ 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 +2404,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 +2417,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 +2430,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);
}
@@ -2618,46 +2941,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;
@@ -2678,6 +2998,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];
@@ -2739,9 +3114,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;
@@ -2922,7 +3297,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);
@@ -2974,11 +3349,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)) {
@@ -3012,7 +3389,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);
@@ -3035,6 +3412,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);
@@ -3072,7 +3451,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);
}
@@ -3095,7 +3474,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);
@@ -3110,7 +3489,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 */
@@ -3130,7 +3509,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 */
@@ -3147,7 +3526,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);
@@ -3166,7 +3545,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);
@@ -3200,7 +3579,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;
@@ -3216,15 +3595,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);
}
@@ -3232,34 +3610,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 */
@@ -3290,7 +3677,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);
@@ -3314,9 +3701,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);
@@ -3326,20 +3714,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);
@@ -3349,6 +3752,54 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widgetbase_draw(&wtb, wcol);
}
+static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+{
+ uiWidgetBase wtb;
+ uiStyle *style = UI_style_get();
+ const uiFontStyle *fstyle = &style->widget;
+ const int px = (max_ii(1, iroundf(U.pixelsize)));
+ const int fontid = fstyle->uifont_id;
+ const float aspect = but->block->aspect;
+ const float zoom = 1.0f / aspect;
+ const float rad = ((px * 3) * UI_DPI_FAC) * zoom;
+ bool is_active = but->flag & UI_SELECT;
+ unsigned char theme_col_tab_highlight[3];
+
+ /* create outline highlight colors */
+ if (is_active)
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel,
+ (unsigned char *)wcol->outline, 0.2f);
+ else
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner,
+ (unsigned char *)wcol->outline, 0.12f);
+
+ widget_init(&wtb);
+
+ /* space between tabs */
+ BLI_rcti_resize(rect, BLI_rcti_size_x(rect) - 0.07f * U.dpi, BLI_rcti_size_y(rect));
+ BLI_rcti_translate(rect, -(0.3f * U.widget_unit), 0.2f * U.widget_unit);
+
+ /* copy the new rect to the button's rect */
+ BLI_rctf_resize(&but->rect, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
+ BLI_rctf_translate(&but->rect, -(0.3f * U.widget_unit), 0.2f * U.widget_unit);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ /* draw inner */
+ wtb.draw_outline = 0;
+ widgetbase_draw(&wtb, wcol);
+
+ /* draw outline (3d look) */
+ ui_draw_but_TAB_outline(rect, rad, roundboxalign, theme_col_tab_highlight,
+ is_active ? (unsigned char *)wcol->inner_sel : (unsigned char *)wcol->inner);
+
+ /* text shadow */
+ BLF_enable(fontid, BLF_SHADOW);
+ BLF_shadow(fontid, 3, 1.0f, 1.0f, 1.0f, 0.25f);
+ BLF_shadow_offset(fontid, 0, -1);
+}
+
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
uiWidgetBase wtb;
@@ -3403,6 +3854,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:
@@ -3418,6 +3870,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:
@@ -3431,9 +3884,15 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_roundbut;
break;
+ case UI_WTYPE_TAB:
+ wt.custom = widget_tab;
+ wt.wcol_theme = &btheme->tui.wcol_tab;
+ wt.state = widget_state_tab;
+ break;
+
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
- wt.draw = widget_menu_back;
+ wt.draw = widget_tooltip_back;
break;
@@ -3489,7 +3948,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 */
@@ -3612,14 +4070,14 @@ 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);
break;
}
}
- else if (but->dt == UI_EMBOSS_NONE) {
+ else if (but->dt == UI_EMBOSS_NONE && (but->flag & UI_ACTIVE) == 0) {
/* "nothing" */
wt = widget_type(UI_WTYPE_ICON);
}
@@ -3627,7 +4085,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
}
else {
- BLI_assert(but->dt == UI_EMBOSS);
+ BLI_assert(but->dt == UI_EMBOSS || (but->dt == UI_EMBOSS_NONE && (but->flag & UI_ACTIVE)));
switch (but->type) {
case UI_BTYPE_LABEL:
@@ -3672,7 +4130,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
if (but->block->flag & UI_BLOCK_LOOP)
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
-
+
+ case UI_BTYPE_TAB:
+ wt = widget_type(UI_WTYPE_TAB);
+ break;
+
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_TOGGLE_N:
@@ -3842,6 +4304,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);
@@ -3854,27 +4326,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');
}
}
@@ -4023,7 +4490,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 4f5285fa2f9..c19cef6fadc 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -171,8 +171,12 @@ 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)
+ if (ELEM(theme_regionid, RGN_TYPE_WINDOW, RGN_TYPE_TABS))
cp = ts->back;
else if (theme_regionid == RGN_TYPE_CHANNELS)
cp = ts->list;
@@ -192,7 +196,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
setting = ts->gradients.show_grad;
break;
case TH_TEXT:
- if (theme_regionid == RGN_TYPE_WINDOW)
+ if (ELEM(theme_regionid, RGN_TYPE_WINDOW, RGN_TYPE_TABS))
cp = ts->text;
else if (theme_regionid == RGN_TYPE_CHANNELS)
cp = ts->list_text;
@@ -258,13 +262,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->button_text_hi; break;
case TH_TAB_ACTIVE:
- cp = ts->tab_active; break;
+ cp = ts->tabs.tab_active; break;
case TH_TAB_INACTIVE:
- cp = ts->tab_inactive; break;
+ cp = ts->tabs.tab_inactive; break;
case TH_TAB_BACK:
- cp = ts->tab_back; break;
+ cp = ts->tabs.tab_back; break;
case TH_TAB_OUTLINE:
- cp = ts->tab_outline; break;
+ cp = ts->tabs.tab_outline; break;
case TH_SHADE1:
cp = ts->shade1; break;
@@ -846,7 +850,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;
@@ -2636,6 +2642,55 @@ void init_userdef_do_versions(void)
if (!USER_VERSION_ATLEAST(276, 2)) {
bTheme *btheme;
+ ThemeSpace *ts;
+
+ /* interface_widgets.c */
+ struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255}, /* gets overwritten later */
+ {114, 114, 114, 255}, /* gets overwritten later */
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255}, /* gets overwritten later */
+ {0, 0, 0, 255},
+
+ 0,
+ 0, 0
+ };
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ btheme->tui.wcol_tab = wcol_tab;
+ for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
+ copy_v4_v4_char(ts->tabs.tab_active, ts->tab_active);
+ copy_v4_v4_char(ts->tabs.tab_inactive, ts->tab_inactive);
+ copy_v4_v4_char(ts->tabs.tab_back, ts->tab_back);
+ copy_v4_v4_char(ts->tabs.tab_outline, ts->tab_outline);
+ }
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(276, 2)) {
+ 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 (!USER_VERSION_ATLEAST(276, 2)) {
+ bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tui.xaxis, 1.0f, 0.27f, 0.27f, 1.0f); /* red */
rgba_char_args_set_fl(btheme->tui.yaxis, 0.27f, 1.0f, 0.27f, 1.0f); /* green */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 9976f42a48a..d966cedc133 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, bool 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, bool 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;
}
@@ -317,8 +320,9 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->keeptot = V2D_KEEPTOT_BOUNDS;
/* note, scroll is being flipped in ED_region_panels() drawing */
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
+ if ((v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) == 0) {
+ v2d->scroll |= V2D_SCROLL_RIGHT;
+ }
if (do_init) {
float panelzoom = (style) ? style->panelzoom : 1.0f;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index ca1efb82ae9..2ebdf467ceb 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -166,9 +166,13 @@ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
-
- /* request updates to be done... */
- ED_region_tag_redraw(vpd->ar);
+
+ /* request updates to be done (special case: tab region! we need to redraw the complete area here!) */
+ if (vpd->ar->regiontype == RGN_TYPE_TABS)
+ ED_area_tag_redraw(vpd->sa);
+ else
+ ED_region_tag_redraw(vpd->ar);
+
WM_event_add_mousemove(C);
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index ed86ffa5e16..dbbf0653ca4 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -20,6 +20,7 @@
set(INC
../include
+ ../interface
../../blenfont
../../blenkernel
../../blenlib
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
index 5f48894c3e7..4a05ce5915b 100644
--- a/source/blender/editors/screen/SConscript
+++ b/source/blender/editors/screen/SConscript
@@ -34,6 +34,7 @@ incs = [
env['BF_GLEW_INC'],
'#/intern/glew-mx',
'../include',
+ '../interface',
'../../blenfont',
'../../blenkernel',
'../../blenlib',
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 43b71af3845..3e0bbd47eda 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -85,33 +85,32 @@ 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 {
+ /* XXX (julian) */
+// 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);
}
@@ -1116,6 +1115,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
if (ar->regiontype == RGN_TYPE_HEADER) {
prefsizey = ED_area_headersize();
}
+ else if (ar->regiontype == RGN_TYPE_TABS) {
+ prefsizey = UI_TAB_REGION_MARGIN_HEIGHT;
+ }
else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
}
@@ -1444,6 +1446,11 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
for (ar = sa->regionbase.first; ar; ar = ar->next)
ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype);
+
+ if (BKE_area_find_region_type(sa, RGN_TYPE_TABS))
+ sa->flag |= AREA_CONTAINS_TABS;
+ else
+ sa->flag &= ~AREA_CONTAINS_TABS;
/* area sizes */
area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win));
@@ -1737,7 +1744,8 @@ 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;
+ int theme_col_bg = TH_BACK;
bool is_context_new = 0;
int redo;
int scroll;
@@ -1759,7 +1767,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
- v2d->scroll |= (V2D_SCROLL_RIGHT);
}
else {
/* for now, allow scrolling in both directions (since layouts are optimized for vertical,
@@ -1826,7 +1833,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);
@@ -1850,36 +1857,49 @@ 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 layout = UI_LAYOUT_VERTICAL;
short panelContext;
/* panel context can either be toolbar region or normal panels region */
- if (ar->regiontype == RGN_TYPE_TOOLS)
+ if (ar->regiontype == RGN_TYPE_TOOLS) {
panelContext = UI_LAYOUT_TOOLBAR;
- else
+ }
+ else if (ar->regiontype == RGN_TYPE_TABS) {
+ panelContext = UI_LAYOUT_HEADER;
+ if (sa->spacetype != SPACE_USERPREF) {
+ layout = UI_LAYOUT_HORIZONTAL;
+ }
+ }
+ else {
panelContext = UI_LAYOUT_PANEL;
+ }
panel->layout = UI_block_layout(
- block, UI_LAYOUT_VERTICAL, panelContext,
+ block, layout, panelContext,
style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
pt->draw(C, panel);
@@ -1935,16 +1955,21 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
}
/* clear */
+ if (ar->regiontype == RGN_TYPE_PREVIEW)
+ theme_col_bg = TH_PREVIEW_BACK;
+ else if (ar->regiontype == RGN_TYPE_TABS)
+ theme_col_bg = TH_TAB_BACK;
+
if (ar->overlap) {
/* view should be in pixelspace */
UI_view2d_view_restore(C);
glEnable(GL_BLEND);
- UI_ThemeColor4((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
- glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1);
+ UI_ThemeColor4(theme_col_bg);
+ glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
glDisable(GL_BLEND);
}
else {
- UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ UI_ThemeClearColor(theme_col_bg);
glClear(GL_COLOR_BUFFER_BIT);
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 559c83590ad..f46486601af 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -64,6 +64,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"
@@ -1011,47 +1012,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 *************************** */
@@ -1136,10 +1128,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 5bbd13fa949..ac2a478ebd2 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -160,6 +160,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 2f87d437033..1ee9a67a7a1 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 = 0;
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 f7673d86f94..29324882736 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 05078e30192..242182f7a0e 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -193,6 +193,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 9ecea7462ff..da4cfb27965 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -675,6 +675,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/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index b5a6821d147..fea627a13c3 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -44,6 +44,8 @@
#include "ED_screen.h"
#include "ED_space_api.h"
+#include "UI_view2d.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -66,6 +68,26 @@ static SpaceLink *userpref_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
+ /* tab region */
+ ar = MEM_callocN(sizeof(ARegion), "tab region for userpref");
+
+ BLI_addtail(&spref->regionbase, ar);
+ ar->regiontype = RGN_TYPE_TABS;
+ ar->alignment = RGN_ALIGN_TOP;
+
+ {
+ View2D *v2d = &ar->v2d;
+
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
+ v2d->minzoom = ar->v2d.maxzoom = 1.0f;
+
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+
+ /* no scrollers! */
+ v2d->scroll = 0;
+ }
+
/* main area */
ar = MEM_callocN(sizeof(ARegion), "main area for userpref");
@@ -125,6 +147,23 @@ static void userpref_keymap(struct wmKeyConfig *UNUSED(keyconf))
}
+static void userpref_tab_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ wmKeyMap *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ keymap = WM_keymap_find(wm->defaultconf, "View2D Buttons List", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+}
+
+static void userpref_tab_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_panels(C, ar, NULL, -1, true);
+
+ ar->v2d.keepofs = (V2D_LOCKOFS_Y);
+}
+
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
@@ -178,6 +217,15 @@ void ED_spacetype_userpref(void)
BLI_addhead(&st->regiontypes, art);
+ /* regions: tab region*/
+ art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
+ art->regionid = RGN_TYPE_TABS;
+ art->init = userpref_tab_area_init;
+ art->draw = userpref_tab_area_draw;
+ art->keymapflag = ED_KEYMAP_UI;
+
+ BLI_addhead(&st->regiontypes, art);
+
/* regions: header */
art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
art->regionid = RGN_TYPE_HEADER;
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 6095a9a8e52..71dd6f4f349 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -103,9 +103,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 */
@@ -286,6 +286,7 @@ enum {
AREA_FLAG_STACKED_FULLSCREEN = (1 << 7),
/* update action zones (even if the mouse is not intersecting them) */
AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8),
+ AREA_CONTAINS_TABS = (1 << 9),
};
#define EDGEWIDTH 1
@@ -375,7 +376,8 @@ enum {
RGN_TYPE_UI = 4,
RGN_TYPE_TOOLS = 5,
RGN_TYPE_TOOL_PROPS = 6,
- RGN_TYPE_PREVIEW = 7
+ RGN_TYPE_PREVIEW = 7,
+ RGN_TYPE_TABS = 8
};
/* use for function args */
#define RGN_TYPE_ANY -1
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 722100e7625..e2c7478f5d3 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -129,7 +129,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 {
@@ -142,6 +144,13 @@ typedef struct uiWidgetStateColors {
float blend, pad;
} uiWidgetStateColors;
+typedef struct uiTabColors {
+ char tab_active[4];
+ char tab_inactive[4];
+ char tab_back[4];
+ char tab_outline[4];
+} uiTabColors;
+
typedef struct uiPanelColors {
char header[4];
char back[4];
@@ -161,14 +170,20 @@ typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
uiWidgetColors wcol_regular, wcol_tool, wcol_text;
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
- uiWidgetColors wcol_num, wcol_numslider;
+ uiWidgetColors wcol_num, wcol_numslider, wcol_tab;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;
uiWidgetStateColors wcol_state;
+ uiTabColors tab;
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 */
@@ -200,7 +215,7 @@ typedef struct ThemeSpace {
char header_text[4];
char header_text_hi[4];
- /* region tabs */
+ /* region tabs - DEPRECATED, use ThemeUI->tab */
char tab_active[4];
char tab_inactive[4];
char tab_back[4];
@@ -223,7 +238,8 @@ typedef struct ThemeSpace {
/* char panel_title[4]; unused */
/* char panel_text[4]; unused */
/* char panel_text_hi[4]; unused */
-
+
+ uiTabColors tabs;
/* note, cannot use name 'panel' because of DNA mapping old files */
uiPanelColors panelcolors;
@@ -903,6 +919,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_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 477a9dbca4f..7fe0fde8774 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -45,6 +45,7 @@ EnumPropertyItem region_type_items[] = {
{RGN_TYPE_TOOLS, "TOOLS", 0, "Tools", ""},
{RGN_TYPE_TOOL_PROPS, "TOOL_PROPS", 0, "Tool Properties", ""},
{RGN_TYPE_PREVIEW, "PREVIEW", 0, "Preview", ""},
+ {RGN_TYPE_TABS, "TABS", 0, "Tabs", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index ac8b2e9ca15..8a7ef7cfac1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -63,28 +63,38 @@
EnumPropertyItem space_type_items[] = {
/* empty must be here for python, is skipped for UI */
{SPACE_EMPTY, "EMPTY", ICON_NONE, "Empty", ""},
+
+ /* Workspaces - for authoring new data directly */
+ {0, "", ICON_NONE, "Workspaces", ""},
{SPACE_VIEW3D, "VIEW_3D", ICON_VIEW3D, "3D View", "3D viewport"},
- {0, "", ICON_NONE, NULL, NULL},
+ {SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"},
+ {SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"},
+ {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequencer", "Video editing tools"},
+ {SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"},
+
+ /* animation editors */
+ {0, "", ICON_NONE, "Animation", ""},
{SPACE_TIME, "TIMELINE", ICON_TIME, "Timeline", "Timeline and playback controls"},
{SPACE_IPO, "GRAPH_EDITOR", ICON_IPO, "Graph Editor", "Edit drivers and keyframe interpolation"},
{SPACE_ACTION, "DOPESHEET_EDITOR", ICON_ACTION, "Dope Sheet", "Adjust timing of keyframes"},
{SPACE_NLA, "NLA_EDITOR", ICON_NLA, "NLA Editor", "Combine and layer Actions"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"},
- {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"},
- {SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"},
+
+ /* scripting */
+ {0, "", ICON_NONE, "Scripting", ""},
{SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"},
- {SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"},
{SPACE_LOGIC, "LOGIC_EDITOR", ICON_LOGIC, "Logic Editor", "Game logic editing"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related datablocks"},
+ {SPACE_CONSOLE, "CONSOLE", ICON_CONSOLE, "Python Console", "Interactive programmatic console for "
+ "advanced editing and script development"},
+ {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages "
+ "(drag down to expand and display)"},
+
+ /* data */
+ {0, "", ICON_NONE, "Data", ""},
{SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available datablocks"},
- {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"},
- {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"},
- {0, "", ICON_NONE, NULL, NULL},
+ {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related datablocks"},
{SPACE_FILE, "FILE_BROWSER", ICON_FILESEL, "File Browser", "Browse for files and assets"},
- {0, "", ICON_NONE, NULL, NULL},
- {SPACE_CONSOLE, "CONSOLE", ICON_CONSOLE, "Python Console", "Interactive programmatic console for advanced editing and script development"},
+ {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent "
+ "configuration settings"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 81b6a77f683..4bb2e4946a3 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -125,6 +125,22 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname,
uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon);
}
+static void rna_uiItemTabsR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt,
+ int translate, int icon, int alignment, int icon_only)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ uiItemTabsR(layout, ptr, prop, name, icon, alignment, icon_only);
+}
+
static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name,
const char *text_ctxt, int translate, int icon)
{
@@ -429,6 +445,14 @@ void RNA_api_ui_layout(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem tabs_alignment_items[] = {
+ {UI_BUT_ALIGN_TOP, "TOP", 0, "Top", ""},
+ {UI_BUT_ALIGN_DOWN, "DOWN", 0, "Down", ""},
+ {UI_BUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
+ {UI_BUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static float node_socket_color_default[] = { 0.0f, 0.0f, 0.0f, 1.0f };
/* simple layout specifiers */
@@ -544,6 +568,14 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
api_ui_item_common(func);
+ func = RNA_def_function(srna, "prop_tabs", "rna_uiItemTabsR");
+ RNA_def_function_ui_description(func, "Item. Exposes an RNA item and draws it as a tab into the layout");
+ api_ui_item_rna_common(func);
+ api_ui_item_common(func);
+ RNA_def_enum(func, "alignment", tabs_alignment_items, UI_BUT_ALIGN_DOWN, "Alignment",
+ "The direction to which the tabs will be aligned to");
+ RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in tabs, no text");
+
func = RNA_def_function(srna, "prop_search", "rna_uiItemPointerR");
api_ui_item_rna_common(func);
parm = RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 76870e5299f..5c88e03efab 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -882,6 +882,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)
@@ -929,6 +934,38 @@ static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
+static void rna_def_userdef_theme_ui_tabs(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThemeTabColors", NULL);
+ RNA_def_struct_sdna(srna, "uiTabColors");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Theme Tab Color", "Theme settings for tab colors");
+
+ prop = RNA_def_property(srna, "tab_active", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Tab Active", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "tab_inactive", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Tab Inactive", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "tab_back", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Tab Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "tab_outline", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Tab Outline", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+}
+
static void rna_def_userdef_theme_ui_panel(BlenderRNA *brna)
{
StructRNA *srna;
@@ -940,10 +977,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");
@@ -987,8 +1026,15 @@ 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_tabs(brna);
rna_def_userdef_theme_ui_panel(brna);
rna_def_userdef_theme_ui_gradient(brna);
@@ -1092,6 +1138,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);
@@ -1172,6 +1230,12 @@ static void rna_def_userdef_theme_space_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Header Text Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ /* tabs */
+ prop = RNA_def_property(srna, "tabs", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Tab Colors", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
/* panel settings */
prop = RNA_def_property(srna, "panelcolors", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -1199,28 +1263,6 @@ static void rna_def_userdef_theme_space_common(StructRNA *srna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Region Text Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- /* tabs */
- prop = RNA_def_property(srna, "tab_active", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Tab Active", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "tab_inactive", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Tab Inactive", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "tab_back", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 4);
- RNA_def_property_ui_text(prop, "Tab Background", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "tab_outline", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Tab Outline", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
/* } */
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 58b413c32f2..98f88c9a081 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1150,10 +1150,10 @@ static int wm_operator_invoke(
((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR));
}
- /* exception, cont. grab in header is annoying */
+ /* exception, cont. grab in header or tab regions is annoying */
if (wrap) {
ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_HEADER) {
+ if (ar && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TABS)) {
wrap = false;
}
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index fec2671edba..a60a2d28acb 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -519,9 +519,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
- /* widgetmaps after freeing blender, so no deleted data get accessed during cleaning up of areas */
- WM_widgetmaptypes_free();
-
BLF_exit();
#ifdef WITH_INTERNATIONAL