From 4ec467d3b52744ba2aa4f938973efa27202b23ee Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 27 Apr 2018 00:49:00 +0200 Subject: UI: Draw scroll-bars overlapping with editor content Scroll-bars used to draw in a little extra space in the editor, causing buttons to jump a bit when they appeared/disappeared. Now they draw on top of the buttons, just small enough to avoid bigger overlaps. Followup commits will do further adjustments. With this we can get rid of a hack that was calling the (often Python defined) panel definition - the panel 'draw' callback - twice. --- source/blender/editors/include/UI_view2d.h | 10 +- .../blender/editors/interface/interface_handlers.c | 4 +- source/blender/editors/interface/interface_panel.c | 5 + source/blender/editors/interface/view2d.c | 42 +---- source/blender/editors/interface/view2d_ops.c | 2 +- source/blender/editors/screen/area.c | 206 ++++++++++----------- 6 files changed, 117 insertions(+), 152 deletions(-) (limited to 'source') diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 65c69c7f287..a19b2f05e2e 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -103,11 +103,11 @@ enum eView2D_Gridlines { /* ------ Defines for Scrollers ----- */ /* scroller area */ -#define V2D_SCROLL_HEIGHT (0.55f * U.widget_unit) -#define V2D_SCROLL_WIDTH (0.55f * U.widget_unit) +#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit) +#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit) /* For scrollers with scale markings (text written onto them) */ -#define V2D_SCROLL_HEIGHT_TEXT (0.85f * U.widget_unit) -#define V2D_SCROLL_WIDTH_TEXT (0.85f * U.widget_unit) +#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit) +#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit) /* scroller 'handles' hotspot radius for mouse */ #define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit) @@ -222,7 +222,7 @@ void UI_view2d_center_set(struct View2D *v2d, float x, float y); void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac); -short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y); +short UI_view2d_mouse_in_scrollers(const struct ARegion *ar, struct View2D *v2d, int x, int y); /* cached text drawing in v2d, to allow pixel-aligned draw as post process */ void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 4d6a43d3a75..704a602f6c1 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -75,6 +75,7 @@ #include "ED_keyframing.h" #include "UI_interface.h" +#include "UI_view2d.h" #include "BLF_api.h" @@ -7411,8 +7412,9 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y) ui_window_to_region(ar, &mx, &my); /* check if in the rect */ - if (!BLI_rcti_isect_pt(&v2d->mask, mx, my)) + if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) { return false; + } } return true; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index aa10efe45cb..f621a906789 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2017,6 +2017,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons retval = WM_UI_HANDLER_CONTINUE; + /* Scrollbars can overlap panels now, they have handling priority. */ + if (UI_view2d_mouse_in_scrollers(ar, &ar->v2d, event->x, event->y)) { + return retval; + } + /* handle category tabs */ if (has_category_tabs) { if (event->val == KM_PRESS) { diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 10be0b52ba5..8342387f956 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -147,7 +147,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers) scroll = view2d_scroll_mapped(v2d->scroll); - /* scrollers shrink mask area, but should be based off regionsize + /* scrollers are based off regionsize * - they can only be on one to two edges of the region they define * - if they overlap, they must not occupy the corners (which are reserved for other widgets) */ @@ -162,14 +162,12 @@ static void view2d_masks(View2D *v2d, bool check_scrollers) /* on left-hand edge of region */ v2d->vert = v2d->mask; 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 - scroll_width; - v2d->mask.xmax = v2d->vert.xmin - 1; } /* horizontal scroller */ @@ -177,25 +175,22 @@ static void view2d_masks(View2D *v2d, bool check_scrollers) /* on bottom edge of region */ v2d->hor = v2d->mask; 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 - scroll_height; - v2d->mask.ymax = v2d->hor.ymin - 1; } /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */ if (scroll & V2D_SCROLL_VERTICAL) { - /* just set y min/max for vertical scroller to y min/max of mask as appropriate */ if (scroll & (V2D_SCROLL_BOTTOM)) { /* on bottom edge of region */ - v2d->vert.ymin = v2d->mask.ymin; + v2d->vert.ymin = v2d->hor.ymax; } else if (scroll & V2D_SCROLL_TOP) { /* on upper edge of region */ - v2d->vert.ymax = v2d->mask.ymax; + v2d->vert.ymax = v2d->hor.ymin; } } } @@ -1650,7 +1645,7 @@ View2DScrollers *UI_view2d_scrollers_calc( hor = v2d->hor; /* slider rects need to be smaller than region */ - smaller = (int)(0.2f * U.widget_unit); + smaller = (int)(0.1f * U.widget_unit); hor.xmin += smaller; hor.xmax -= smaller; if (scroll & V2D_SCROLL_BOTTOM) @@ -1848,20 +1843,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v { state |= UI_SCROLL_ARROWS; } - - /* clean rect behind slider, but not with transparent background */ - if (scrollers_back_color[3] == 255) { - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformColor3ubv(scrollers_back_color); - immRecti(pos, v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax); - immUnbindProgram(); - } - UI_draw_widget_scroll(&wcol, &hor, &slider, state); /* scale indicators */ @@ -1960,19 +1942,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v state |= UI_SCROLL_ARROWS; } - /* clean rect behind slider, but not with transparent background */ - if (scrollers_back_color[3] == 255) { - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformColor3ubv(scrollers_back_color); - immRecti(pos, v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax); - - immUnbindProgram(); - } - UI_draw_widget_scroll(&wcol, &vert, &slider, state); @@ -2427,9 +2396,8 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac) * - 'v' = in vertical scroller. * - 0 = not in scroller. */ -short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y) +short UI_view2d_mouse_in_scrollers(const ARegion *ar, View2D *v2d, int x, int y) { - ARegion *ar = CTX_wm_region(C); int co[2]; int scroll = view2d_scroll_mapped(v2d->scroll); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 6150b7e254e..90ef47aa712 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1908,7 +1908,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * short in_scroller = 0; /* check if mouse in scrollbars, if they're enabled */ - in_scroller = UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y); + in_scroller = UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y); /* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */ if (in_scroller) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 89e22aebed0..58dbebd2b75 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1986,7 +1986,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c View2DScrollers *scrollers; int x, y, xco, yco, w, em, triangle; bool is_context_new = 0; - int redo; int scroll; bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)); /* XXX, should use some better check? */ @@ -2064,140 +2063,131 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c } - /* sortof hack - but we cannot predict the height of panels, until it's being generated */ - /* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */ - /* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */ - for (redo = 2; redo > 0; redo--) { - - if (vertical) { - w = BLI_rctf_size_x(&v2d->cur); - em = (ar->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */ - } - else { - w = UI_PANEL_WIDTH; - em = (ar->type->prefsizex) ? 10 : 20; - } + if (vertical) { + w = BLI_rctf_size_x(&v2d->cur); + em = (ar->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */ + } + else { + w = UI_PANEL_WIDTH; + em = (ar->type->prefsizex) ? 10 : 20; + } - w -= margin_x; - - /* create panels */ - UI_panels_begin(C, ar); + w -= margin_x; - /* set view2d view matrix - UI_block_begin() stores it */ - UI_view2d_view_ortho(v2d); + /* create panels */ + UI_panels_begin(C, ar); - BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt) - { - bool open; + /* set view2d view matrix - UI_block_begin() stores it */ + UI_view2d_view_ortho(v2d); - panel = UI_panel_find_by_type(ar, pt); + BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt) + { + bool open; - if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) { - if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) { - continue; - } + panel = UI_panel_find_by_type(ar, pt); + + if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) { + if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) { + continue; } + } - /* draw panel */ - block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS); - panel = UI_panel_begin(sa, ar, block, pt, panel, &open); + /* draw panel */ + 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); + /* bad fixed values */ + triangle = (int)(UI_UNIT_Y * 1.1f); - if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { - /* 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); + if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + /* 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); - pt->draw_header(C, panel); + pt->draw_header(C, panel); - UI_block_layout_resolve(block, &xco, &yco); - panel->labelofs = xco - triangle; - panel->layout = NULL; - } - else { - panel->labelofs = 0; - } + UI_block_layout_resolve(block, &xco, &yco); + panel->labelofs = xco - triangle; + panel->layout = NULL; + } + else { + panel->labelofs = 0; + } - if (open) { - short panelContext; + if (open) { + short panelContext; - /* panel context can either be toolbar region or normal panels region */ - if (ar->regiontype == RGN_TYPE_TOOLS) - panelContext = UI_LAYOUT_TOOLBAR; - else - panelContext = UI_LAYOUT_PANEL; + /* panel context can either be toolbar region or normal panels region */ + if (ar->regiontype == RGN_TYPE_TOOLS) + panelContext = UI_LAYOUT_TOOLBAR; + else + panelContext = UI_LAYOUT_PANEL; - panel->layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, panelContext, - style->panelspace, 0, w - 2 * style->panelspace, em, 0, style); + panel->layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, panelContext, + style->panelspace, 0, w - 2 * style->panelspace, em, 0, style); - pt->draw(C, panel); + pt->draw(C, panel); - UI_block_layout_resolve(block, &xco, &yco); - panel->layout = NULL; + UI_block_layout_resolve(block, &xco, &yco); + panel->layout = NULL; + + yco -= 2 * style->panelspace; + UI_panel_end(block, w, -yco); + } + else { + yco = 0; + UI_panel_end(block, w, 0); + } + + UI_block_end(C, block); + } + BLI_SMALLSTACK_ITER_END; - yco -= 2 * style->panelspace; - UI_panel_end(block, w, -yco); + /* align panels and return size */ + UI_panels_end(C, ar, &x, &y); + + /* before setting the view */ + if (vertical) { + /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */ + if (v2d->cur.ymax < -FLT_EPSILON) { + /* Clamp to lower view boundary */ + if (v2d->tot.ymin < -v2d->winy) { + y = min_ii(y, 0); } else { - yco = 0; - UI_panel_end(block, w, 0); + y = min_ii(y, v2d->cur.ymin); } - - UI_block_end(C, block); } - BLI_SMALLSTACK_ITER_END; - /* align panels and return size */ - UI_panels_end(C, ar, &x, &y); - - /* before setting the view */ - if (vertical) { - /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */ - if (v2d->cur.ymax < -FLT_EPSILON) { - /* Clamp to lower view boundary */ - if (v2d->tot.ymin < -v2d->winy) { - y = min_ii(y, 0); - } - else { - y = min_ii(y, v2d->cur.ymin); - } + y = -y; + } + else { + /* don't jump back when panels close or hide */ + if (!is_context_new) { + if (v2d->tot.xmax > v2d->winx) { + x = max_ii(x, 0); } - - y = -y; - } - else { - /* don't jump back when panels close or hide */ - if (!is_context_new) { - if (v2d->tot.xmax > v2d->winx) { - x = max_ii(x, 0); - } - else { - x = max_ii(x, v2d->cur.xmax); - } + else { + x = max_ii(x, v2d->cur.xmax); } - - y = -y; } - - /* this also changes the 'cur' */ - UI_view2d_totRect_set(v2d, x, y); - - if (scroll != v2d->scroll) { - /* Note: this code scales fine, but because of rounding differences, positions of elements - * flip +1 or -1 pixel compared to redoing the entire layout again. - * Leaving in commented code for future tests */ + + y = -y; + } + + /* this also changes the 'cur' */ + UI_view2d_totRect_set(v2d, x, y); + + if (scroll != v2d->scroll) { + /* Note: this code scales fine, but because of rounding differences, positions of elements + * flip +1 or -1 pixel compared to redoing the entire layout again. + * Leaving in commented code for future tests */ #if 0 - UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur)); - break; + UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur)); + break; #endif - } - else { - break; - } } region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); -- cgit v1.2.3