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.
This commit is contained in:
parent
2349b9777a
commit
4ec467d3b5
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
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);
|
||||
|
||||
/* set view2d view matrix - UI_block_begin() stores it */
|
||||
UI_view2d_view_ortho(v2d);
|
||||
|
||||
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
|
||||
{
|
||||
bool open;
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
pt->draw_header(C, panel);
|
||||
|
||||
UI_block_layout_resolve(block, &xco, &yco);
|
||||
panel->labelofs = xco - triangle;
|
||||
panel->layout = NULL;
|
||||
}
|
||||
else {
|
||||
w = UI_PANEL_WIDTH;
|
||||
em = (ar->type->prefsizex) ? 10 : 20;
|
||||
panel->labelofs = 0;
|
||||
}
|
||||
|
||||
w -= margin_x;
|
||||
|
||||
/* create panels */
|
||||
UI_panels_begin(C, ar);
|
||||
if (open) {
|
||||
short panelContext;
|
||||
|
||||
/* set view2d view matrix - UI_block_begin() stores it */
|
||||
UI_view2d_view_ortho(v2d);
|
||||
/* 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;
|
||||
|
||||
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
|
||||
{
|
||||
bool open;
|
||||
panel->layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, panelContext,
|
||||
style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
|
||||
|
||||
panel = UI_panel_find_by_type(ar, pt);
|
||||
pt->draw(C, panel);
|
||||
|
||||
if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
|
||||
if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UI_block_layout_resolve(block, &xco, &yco);
|
||||
panel->layout = NULL;
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
UI_block_layout_resolve(block, &xco, &yco);
|
||||
panel->labelofs = xco - triangle;
|
||||
panel->layout = NULL;
|
||||
}
|
||||
else {
|
||||
panel->labelofs = 0;
|
||||
}
|
||||
|
||||
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->layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, panelContext,
|
||||
style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
|
||||
|
||||
pt->draw(C, panel);
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
yco -= 2 * style->panelspace;
|
||||
UI_panel_end(block, w, -yco);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
y = -y;
|
||||
yco = 0;
|
||||
UI_panel_end(block, w, 0);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
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);
|
||||
}
|
||||
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 */
|
||||
#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);
|
||||
|
|
Loading…
Reference in New Issue