#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_linklist_stack.h"
#include "BLF_translation.h"
int dx = x2 - x1;
int dy = y2 - y1;
- dx = copysign(ceilf(0.3f * fabsf(dx)), dx);
- dy = copysign(ceilf(0.3f * fabsf(dy)), dy);
+ dx = copysign(ceilf(0.3f * abs(dx)), dx);
+ dy = copysign(ceilf(0.3f * abs(dy)), dy);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
ar->drawrct = ar->winrct;
/* note; this sets state, so we can use wmOrtho and friends */
- wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
+ wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct, true);
UI_SetTheme(sa ? sa->spacetype : 0, ar->type ? ar->type->regionid : 0);
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegionType *at = ar->type;
-
+ bool scissor_pad;
+
/* see BKE_spacedata_draw_locks() */
if (at->do_lock)
return;
/* if no partial draw rect set, full rect */
- if (ar->drawrct.xmin == ar->drawrct.xmax)
+ if (ar->drawrct.xmin == ar->drawrct.xmax) {
ar->drawrct = ar->winrct;
+ scissor_pad = true;
+ }
else {
/* extra clip for safety */
BLI_rcti_isect(&ar->winrct, &ar->drawrct, &ar->drawrct);
+ scissor_pad = false;
}
+
+ ar->do_draw |= RGN_DRAWING;
/* note; this sets state, so we can use wmOrtho and friends */
- wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
+ wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct, scissor_pad);
UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
glDisable(GL_BLEND);
#endif
- ar->do_draw = FALSE;
+ ar->do_draw = 0;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
uiFreeInactiveBlocks(C, &ar->uiblocks);
void ED_region_tag_redraw(ARegion *ar)
{
- if (ar) {
+ /* don't tag redraw while drawing, it shouldn't happen normally
+ * but python scripts can cause this to happen indirectly */
+ if (ar && !(ar->do_draw & RGN_DRAWING)) {
/* zero region means full region redraw */
ar->do_draw = RGN_DRAW;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
{
- if (ar) {
+ if (ar && !(ar->do_draw & RGN_DRAWING)) {
if (!ar->do_draw) {
/* no redraw set yet, set partial region */
ar->do_draw = RGN_DRAW_PARTIAL;
static int rct_fits(rcti *rect, char dir, int size)
{
if (dir == 'h') {
- return BLI_rcti_size_x(rect) - size;
+ return BLI_rcti_size_x(rect) + 1 - size;
}
else { /* 'v' */
- return BLI_rcti_size_y(rect) - size;
+ return BLI_rcti_size_y(rect) + 1 - size;
}
}
if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
return 1;
}
- else if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
+ else if (sa->spacetype == SPACE_IMAGE) {
if (ELEM4(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW))
return 1;
}
static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
{
- short rt = U.pixelsize > 1.0f ? 1 : 0;
+ short rt = (short) U.pixelsize;
- if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + 1 + rt;
+ if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + rt;
else sa->totrct.xmin = sa->v1->vec.x;
- if (sa->v4->vec.x < sizex - 1) sa->totrct.xmax = sa->v4->vec.x - 1 - rt;
+ if (sa->v4->vec.x < sizex - 1) sa->totrct.xmax = sa->v4->vec.x - rt;
else sa->totrct.xmax = sa->v4->vec.x;
- if (sa->v1->vec.y > 0) sa->totrct.ymin = sa->v1->vec.y + 1 + rt;
+ if (sa->v1->vec.y > 0) sa->totrct.ymin = sa->v1->vec.y + rt;
else sa->totrct.ymin = sa->v1->vec.y;
- if (sa->v2->vec.y < sizey - 1) sa->totrct.ymax = sa->v2->vec.y - 1 - rt;
+ if (sa->v2->vec.y < sizey - 1) sa->totrct.ymax = sa->v2->vec.y - rt;
else sa->totrct.ymax = sa->v2->vec.y;
/* for speedup */
}
if (sl) {
-
/* swap regions */
slold->regionbase = sa->regionbase;
sa->regionbase = sl->regionbase;
Panel *panel;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
- int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
+ int x, y, xco, yco, w, em, triangle;
+ bool is_context_new = 0;
int redo;
int scroll;
+ bool use_category_tabs = (ar->regiontype == RGN_TYPE_TOOLS); /* XXX, should use some better check? */
+ /* offset panels for small vertical tab area */
+ const char *category = NULL;
+ const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
+ int margin_x = 0;
+
+ BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
+
if (contextnr >= 0)
- newcontext = UI_view2d_tab_set(v2d, contextnr);
+ is_context_new = UI_view2d_tab_set(v2d, contextnr);
/* before setting the view */
if (vertical) {
}
scroll = v2d->scroll;
-
+
+
+ /* collect panels to draw */
+ for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
+ /* verify context */
+ if (context && pt->context[0] && !STREQ(context, pt->context)) {
+ continue;
+ }
+
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ BLI_SMALLSTACK_PUSH(pt_stack, pt);
+ }
+ }
+
+
+ /* collect categories */
+ if (use_category_tabs) {
+ UI_panel_category_clear_all(ar);
+
+ /* gather unique categories */
+ BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
+ {
+ if (pt->category[0]) {
+ if (!UI_panel_category_find(ar, pt->category)) {
+ UI_panel_category_add(ar, pt->category);
+ }
+ }
+ }
+ BLI_SMALLSTACK_ITER_END;
+
+ if (!UI_panel_category_is_visible(ar)) {
+ use_category_tabs = false;
+ }
+ else {
+ category = UI_panel_category_active_get(ar, true);
+ margin_x = category_tabs_width;
+ }
+ }
+
+
/* 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 */
if (vertical) {
w = BLI_rctf_size_x(&v2d->cur);
- em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ 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) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ em = (ar->type->prefsizex) ? 10 : 20;
}
+
+ w -= margin_x;
/* create panels */
uiBeginPanels(C, ar);
/* set view2d view matrix - uiBeginBlock() stores it */
UI_view2d_view_ortho(v2d);
- for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
- /* verify context */
- if (context)
- if (pt->context[0] && strcmp(context, pt->context) != 0)
+ BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
+ {
+ bool open;
+
+ panel = uiPanelFindByType(ar, pt);
+
+ if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
+ if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
continue;
+ }
+ }
/* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
- panel = uiBeginPanel(sa, ar, block, pt, &open);
+ block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+ panel = uiBeginPanel(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 = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
+ if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for enabled buttons */
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
- pt->draw_header(C, panel);
+ pt->draw_header(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->labelofs = xco - triangle;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
+ uiBlockLayoutResolve(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 = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
- style->panelspace, 0, w - 2 * style->panelspace, em, style);
-
- pt->draw(C, panel);
-
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->layout = NULL;
-
- yco -= 2 * style->panelspace;
- uiEndPanel(block, w, -yco);
- }
- else {
- yco = 0;
- uiEndPanel(block, w, 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 = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 0, w - 2 * style->panelspace, em, style);
+
+ pt->draw(C, panel);
- uiEndBlock(C, block);
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->layout = NULL;
+
+ yco -= 2 * style->panelspace;
+ uiEndPanel(block, w, -yco);
+ }
+ else {
+ yco = 0;
+ uiEndPanel(block, w, 0);
}
+
+ uiEndBlock(C, block);
}
+ BLI_SMALLSTACK_ITER_END;
/* align panels and return size */
uiEndPanels(C, ar, &x, &y);
}
else {
/* don't jump back when panels close or hide */
- if (!newcontext)
+ if (!is_context_new)
x = max_ii(x, v2d->cur.xmax);
y = -y;
}
/* 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 */
- /* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
- break; */
+#if 0
+ uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+ break;
+#endif
}
else {
break;
}
}
+ BLI_SMALLSTACK_FREE(pt_stack);
/* clear */
if (ar->overlap) {
/* restore view matrix */
UI_view2d_view_restore(C);
+ if (use_category_tabs) {
+ UI_panel_category_draw_all(ar, category);
+ }
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{
- return (int)(1.3f * UI_UNIT_Y);
+ return (int)(HEADERY * UI_DPI_FAC);
}
void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4])
/* box fill entire width or just around text */
if (!block)
- rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text) + 1.2f * U.widget_unit);
+ rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit);
rect.ymax = BLI_rcti_size_y(&ar->winrct);