diff options
author | Severin <eiseljulian@gmail.com> | 2018-06-30 22:12:19 +0300 |
---|---|---|
committer | Severin <eiseljulian@gmail.com> | 2018-06-30 22:12:19 +0300 |
commit | e5f49598b037ef8476efd458d060d3db348b9b60 (patch) | |
tree | b3a3fe2796ad1ad2ba831e53b944e98013df0648 /source/blender/editors/screen | |
parent | b088a387915950c9419d5326e7269bea3869d140 (diff) | |
parent | 7d48a342d66cc7664b008ff512bd00e740eb7629 (diff) |
Merge branch 'blender2.8' into temp-tab_drag_drop
Diffstat (limited to 'source/blender/editors/screen')
-rw-r--r-- | source/blender/editors/screen/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 718 | ||||
-rw-r--r-- | source/blender/editors/screen/glutil.c | 23 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_context.c | 51 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_draw.c | 31 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 716 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_geometry.c | 462 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_intern.h | 32 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 1328 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_user_menu.c | 196 | ||||
-rw-r--r-- | source/blender/editors/screen/screendump.c | 286 | ||||
-rw-r--r-- | source/blender/editors/screen/workspace_edit.c | 26 | ||||
-rw-r--r-- | source/blender/editors/screen/workspace_layout_edit.c | 14 |
13 files changed, 2212 insertions, 1673 deletions
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index 29b9971eabb..4be65f60b21 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -46,7 +46,9 @@ set(SRC screen_context.c screen_draw.c screen_edit.c + screen_geometry.c screen_ops.c + screen_user_menu.c screendump.c workspace_edit.c workspace_layout_edit.c diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index ad4f6b0179d..207047c2ad3 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,7 +18,7 @@ * The Original Code is Copyright (C) 2008 Blender Foundation. * All rights reserved. * - * + * * Contributor(s): Blender Foundation * * ***** END GPL LICENSE BLOCK ***** @@ -52,6 +52,7 @@ #include "WM_api.h" #include "WM_types.h" #include "WM_message.h" +#include "WM_toolsystem.h" #include "ED_screen.h" #include "ED_screen_types.h" @@ -61,6 +62,8 @@ #include "GPU_immediate_util.h" #include "GPU_matrix.h" #include "GPU_draw.h" +#include "GPU_state.h" +#include "GPU_framebuffer.h" #include "BLF_api.h" @@ -96,8 +99,8 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides) rect.ymax = scirct->ymax - ar->winrct.ymin; /* set transp line */ - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); float color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; UI_GetThemeColor3fv(TH_EDITOR_OUTLINE, color); @@ -136,7 +139,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides) immEnd(); immUnbindProgram(); - glDisable(GL_BLEND); + GPU_blend(false); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } @@ -225,7 +228,7 @@ void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2]) if (changed) { sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE; - ED_area_tag_redraw(sa); + ED_area_tag_redraw_no_rebuild(sa); } } @@ -295,7 +298,7 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2) Gwn_VertFormat *format = immVertexFormat(); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - glEnable(GL_BLEND); + GPU_blend(true); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f); @@ -304,13 +307,13 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2) immRectf(pos, (x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f); immUnbindProgram(); - glDisable(GL_BLEND); + GPU_blend(false); } static void region_draw_azone_tab_plus(AZone *az) { - glEnable(GL_BLEND); - + GPU_blend(true); + /* add code to draw region hidden as 'too small' */ switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: @@ -345,13 +348,13 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) if (!sa) return; - glLineWidth(1.0f); - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_line_width(1.0f); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); gpuPushMatrix(); gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin); - + for (az = sa->actionzones.first; az; az = az->next) { /* test if action zone is over this region */ rcti azrct; @@ -387,7 +390,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) gpuPopMatrix(); - glDisable(GL_BLEND); + GPU_blend(false); } /* Follow wmMsgNotifyFn spec */ @@ -418,6 +421,17 @@ void ED_area_do_msg_notify_tag_refresh( ED_area_tag_refresh(sa); } +/** + * Although there's no general support for minimizing areas, the status-bar can + * be snapped to be only a few pixels high. A few pixels rather than 0 so it + * can be un-minimized again. We consider it pseudo-minimalized and don't draw + * it then. + */ +static bool area_is_pseudo_minimized(const ScrArea *area) +{ + return (area->winx < 3) || (area->winy < 3); +} + /* only exported for WM */ void ED_region_do_layout(bContext *C, ARegion *ar) { @@ -429,7 +443,7 @@ void ED_region_do_layout(bContext *C, ARegion *ar) return; } - if (at->do_lock) { + if (at->do_lock || (sa && area_is_pseudo_minimized(sa))) { return; } @@ -451,19 +465,24 @@ void ED_region_do_draw(bContext *C, ARegion *ar) return; ar->do_draw |= RGN_DRAWING; - + /* Set viewport, scissor, ortho and ar->drawrct. */ wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct); wmOrtho2_region_pixelspace(ar); - + UI_SetTheme(sa ? sa->spacetype : 0, at->regionid); - + + if (sa && area_is_pseudo_minimized(sa)) { + UI_ThemeClearColor(TH_EDITOR_OUTLINE); + glClear(GL_COLOR_BUFFER_BIT); + return; + } /* optional header info instead? */ - if (ar->headerstr) { + else if (ar->headerstr) { UI_ThemeClearColor(TH_HEADER); glClear(GL_COLOR_BUFFER_BIT); - + UI_FontThemeColor(BLF_default(), TH_TEXT); BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); } @@ -480,7 +499,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar) /* for debugging unneeded area redraws and partial redraw */ #if 0 - glEnable(GL_BLEND); + GPU_blend(true); Gwn_VertFormat *format = immVertexFormat(); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -488,11 +507,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar) immRectf(pos, ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin, ar->drawrct.xmax - ar->winrct.xmin, ar->drawrct.ymax - ar->winrct.ymin); immUnbindProgram(); - glDisable(GL_BLEND); + GPU_blend(false); #endif memset(&ar->drawrct, 0, sizeof(ar->drawrct)); - + UI_blocklist_free_inactive(C, &ar->uiblocks); if (sa) { @@ -550,7 +569,7 @@ void ED_region_tag_redraw(ARegion *ar) * 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_PARTIAL; + ar->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD); ar->do_draw |= RGN_DRAW; memset(&ar->drawrct, 0, sizeof(ar->drawrct)); } @@ -562,6 +581,15 @@ void ED_region_tag_redraw_overlay(ARegion *ar) ar->do_draw_overlay = RGN_DRAW; } +void ED_region_tag_redraw_no_rebuild(ARegion *ar) +{ + if (ar && !(ar->do_draw & (RGN_DRAWING | RGN_DRAW))) { + ar->do_draw &= ~RGN_DRAW_PARTIAL; + ar->do_draw |= RGN_DRAW_NO_REBUILD; + memset(&ar->drawrct, 0, sizeof(ar->drawrct)); + } +} + void ED_region_tag_refresh_ui(ARegion *ar) { if (ar) { @@ -572,7 +600,7 @@ void ED_region_tag_refresh_ui(ARegion *ar) void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct) { if (ar && !(ar->do_draw & RGN_DRAWING)) { - if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_PARTIAL))) { + if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD | RGN_DRAW_PARTIAL))) { /* no redraw set yet, set partial region */ ar->do_draw |= RGN_DRAW_PARTIAL; ar->drawrct = *rct; @@ -583,7 +611,7 @@ void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct) BLI_rcti_union(&ar->drawrct, rct); } else { - BLI_assert((ar->do_draw & RGN_DRAW) != 0); + BLI_assert((ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) != 0); /* Else, full redraw is already requested, nothing to do here. */ } } @@ -592,16 +620,25 @@ void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct) void ED_area_tag_redraw(ScrArea *sa) { ARegion *ar; - + if (sa) for (ar = sa->regionbase.first; ar; ar = ar->next) ED_region_tag_redraw(ar); } +void ED_area_tag_redraw_no_rebuild(ScrArea *sa) +{ + ARegion *ar; + + if (sa) + for (ar = sa->regionbase.first; ar; ar = ar->next) + ED_region_tag_redraw_no_rebuild(ar); +} + void ED_area_tag_redraw_regiontype(ScrArea *sa, int regiontype) { ARegion *ar; - + if (sa) { for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == regiontype) { @@ -620,7 +657,7 @@ void ED_area_tag_refresh(ScrArea *sa) /* *************************************************************** */ /* use NULL to disable it */ -void ED_area_headerprint(ScrArea *sa, const char *str) +void ED_area_status_text(ScrArea *sa, const char *str) { ARegion *ar; @@ -644,13 +681,41 @@ void ED_area_headerprint(ScrArea *sa, const char *str) } } +void ED_workspace_status_text(bContext *C, const char *str) +{ + wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = CTX_wm_workspace(C); + + /* Can be NULL when running operators in background mode. */ + if (workspace == NULL) + return; + + if (str) { + if (workspace->status_text == NULL) + workspace->status_text = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint"); + BLI_strncpy(workspace->status_text, str, UI_MAX_DRAW_STR); + } + else if (workspace->status_text) { + MEM_freeN(workspace->status_text); + workspace->status_text = NULL; + } + + /* Redraw status bar. */ + for (ScrArea *sa = win->global_areas.areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_STATUSBAR) { + ED_area_tag_redraw(sa); + break; + } + } +} + /* ************************************************************ */ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa) { AZone *az; - + /* reinitalize entirely, regions and fullscreen add azones too */ BLI_freelistN(&sa->actionzones); @@ -775,11 +840,11 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar) { AZone *azt; int tot = 0, add; - + for (azt = sa->actionzones.first; azt; azt = azt->next) { if (azt->edge == az->edge) tot++; } - + switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0; @@ -809,7 +874,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar) } /* rect needed for mouse pointer test */ BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2); -} +} static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen) { @@ -829,7 +894,7 @@ static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, if (is_hidden) { region_azone_tab_plus(sa, az, ar); } - else { + else if (!is_hidden && (ar->regiontype != RGN_TYPE_HEADER)) { region_azone_edge(az, ar); } } @@ -934,6 +999,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) } if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) { + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } align1 = ar1->alignment; if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { if (align1 != align) { @@ -975,6 +1043,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) if (ar1->flag & (RGN_FLAG_HIDDEN)) { continue; } + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) { if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { @@ -987,19 +1058,22 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) } /* overlapping regions only in the following restricted cases */ -static bool region_is_overlap(ScrArea *sa, ARegion *ar) +bool ED_region_is_overlap(int spacetype, int regiontype) { + if (regiontype == RGN_TYPE_HUD) { + return 1; + } if (U.uiflag2 & USER_REGION_OVERLAP) { - if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) { - if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) + if (ELEM(spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) { + if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) return 1; - if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { - if (ar->regiontype == RGN_TYPE_HEADER) + if (ELEM(spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { + if (regiontype == RGN_TYPE_HEADER) return 1; } - else if (sa->spacetype == SPACE_SEQ) { - if (ar->regiontype == RGN_TYPE_PREVIEW) + else if (spacetype == SPACE_SEQ) { + if (regiontype == RGN_TYPE_PREVIEW) return 1; } } @@ -1008,33 +1082,34 @@ static bool region_is_overlap(ScrArea *sa, ARegion *ar) return 0; } -static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad) +static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad) { rcti *remainder_prev = remainder; int prefsizex, prefsizey; int alignment; - + if (ar == NULL) return; - + /* no returns in function, winrct gets set in the end again */ BLI_rcti_init(&ar->winrct, 0, 0, 0, 0); - + /* for test; allow split of previously defined region */ if (ar->alignment & RGN_SPLIT_PREV) if (ar->prev) remainder = &ar->prev->winrct; - + alignment = ar->alignment & ~RGN_SPLIT_PREV; - + /* set here, assuming userpref switching forces to call this again */ - ar->overlap = region_is_overlap(sa, ar); + ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype); /* clear state flags first */ ar->flag &= ~RGN_FLAG_TOO_SMALL; /* user errors */ - if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT) + if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) { alignment = RGN_ALIGN_NONE; + } /* prefsize, taking into account DPI */ prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex); @@ -1057,7 +1132,28 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti /* hidden is user flag */ } else if (alignment == RGN_ALIGN_FLOAT) { - /* XXX floating area region, not handled yet here */ + /** + * \note Currently this window type is only used for #RGN_TYPE_HUD, + * We expect the panel to resize it's self to be larger. + * + * This aligns to the lower left of the area. + */ + rcti overlap_remainder_margin = *overlap_remainder; + BLI_rcti_resize( + &overlap_remainder_margin, + max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2), + max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2)); + ar->winrct.xmin = overlap_remainder_margin.xmin; + ar->winrct.ymin = overlap_remainder_margin.ymin; + ar->winrct.xmax = ar->winrct.xmin + ar->sizex - 1; + ar->winrct.ymax = ar->winrct.ymin + ar->sizey - 1; + + BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct); + if (BLI_rcti_size_x(&ar->winrct) < UI_UNIT_X || + BLI_rcti_size_y(&ar->winrct) < UI_UNIT_Y) + { + ar->flag |= RGN_FLAG_TOO_SMALL; + } } else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) { /* remainder is too small for any usage */ @@ -1070,7 +1166,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti } else if (alignment == RGN_ALIGN_TOP || alignment == RGN_ALIGN_BOTTOM) { rcti *winrct = (ar->overlap) ? overlap_remainder : remainder; - + if (rct_fits(winrct, 'v', prefsizey) < 0) { ar->flag |= RGN_FLAG_TOO_SMALL; } @@ -1079,9 +1175,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (fac < 0) prefsizey += fac; - + ar->winrct = *winrct; - + if (alignment == RGN_ALIGN_TOP) { ar->winrct.ymin = ar->winrct.ymax - prefsizey + 1; winrct->ymax = ar->winrct.ymin - 1; @@ -1094,18 +1190,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti } else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) { rcti *winrct = (ar->overlap) ? overlap_remainder : remainder; - + if (rct_fits(winrct, 'h', prefsizex) < 0) { ar->flag |= RGN_FLAG_TOO_SMALL; } else { int fac = rct_fits(winrct, 'h', prefsizex); - + if (fac < 0) prefsizex += fac; - + ar->winrct = *winrct; - + if (alignment == RGN_ALIGN_RIGHT) { ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1; winrct->xmax = ar->winrct.xmin - 1; @@ -1119,7 +1215,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti else if (alignment == RGN_ALIGN_VSPLIT || alignment == RGN_ALIGN_HSPLIT) { /* percentage subdiv*/ ar->winrct = *remainder; - + if (alignment == RGN_ALIGN_HSPLIT) { if (rct_fits(remainder, 'h', prefsizex) > 4) { ar->winrct.xmax = BLI_rcti_cent_x(remainder); @@ -1141,18 +1237,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti } else if (alignment == RGN_ALIGN_QSPLIT) { ar->winrct = *remainder; - + /* test if there's still 4 regions left */ if (quad == 0) { ARegion *artest = ar->next; int count = 1; - + while (artest) { artest->alignment = RGN_ALIGN_QSPLIT; artest = artest->next; count++; } - + if (count != 4) { /* let's stop adding regions */ BLI_rcti_init(remainder, 0, 0, 0, 0); @@ -1185,25 +1281,25 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti quad++; } } - + /* for speedup */ ar->winx = BLI_rcti_size_x(&ar->winrct) + 1; ar->winy = BLI_rcti_size_y(&ar->winrct) + 1; - + /* if region opened normally, we store this for hide/reveal usage */ /* prevent rounding errors for UI_DPI_FAC mult and divide */ if (ar->winx > 1) ar->sizex = (ar->winx + 0.5f) / UI_DPI_FAC; if (ar->winy > 1) ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC; - + /* exception for multiple overlapping regions on same spot */ - if (ar->overlap) { + if (ar->overlap & (alignment != RGN_ALIGN_FLOAT)) { region_overlap_fix(sa, ar); } /* set winrect for azones */ if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) { ar->winrct = (ar->overlap) ? *overlap_remainder : *remainder; - + switch (alignment) { case RGN_ALIGN_TOP: ar->winrct.ymin = ar->winrct.ymax; @@ -1237,10 +1333,10 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *overlap_remainder = *remainder; } - region_rect_recursive(win, sa, ar->next, remainder, overlap_remainder, quad); + region_rect_recursive(sa, ar->next, remainder, overlap_remainder, quad); } -static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y) +static void area_calc_totrct(ScrArea *sa, const rcti *window_rect) { short px = (short)U.pixelsize; @@ -1250,16 +1346,16 @@ static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y) sa->totrct.ymax = sa->v2->vec.y; /* scale down totrct by 1 pixel on all sides not matching window borders */ - if (sa->totrct.xmin > 0) { + if (sa->totrct.xmin > window_rect->xmin) { sa->totrct.xmin += px; } - if (sa->totrct.xmax < (window_size_x - 1)) { + if (sa->totrct.xmax < (window_rect->xmax - 1)) { sa->totrct.xmax -= px; } - if (sa->totrct.ymin > 0) { + if (sa->totrct.ymin > window_rect->ymin) { sa->totrct.ymin += px; } - if (sa->totrct.ymax < (window_size_y - 1)) { + if (sa->totrct.ymax < (window_rect->ymax - 1)) { sa->totrct.ymax -= px; } /* Although the following asserts are correct they lead to a very unstable Blender. @@ -1309,7 +1405,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand if (flag & ED_KEYMAP_MARKERS) { /* time-markers */ wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Markers", 0, 0); - + /* use a boundbox restricted map */ ARegion *ar; /* same local check for all areas */ @@ -1332,16 +1428,16 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand } if (flag & ED_KEYMAP_GPENCIL) { /* grease pencil */ - /* NOTE: This is now 2 keymaps - One for basic functionality, - * and one that only applies when "Edit Mode" is enabled + /* NOTE: This is now 2 keymaps - One for basic functionality, + * and one that only applies when "Edit Mode" is enabled * for strokes. * - * For now, it's easier to just include both, + * For now, it's easier to just include both, * since you hardly want one without the other. */ wmKeyMap *keymap_general = WM_keymap_find(wm->defaultconf, "Grease Pencil", 0, 0); wmKeyMap *keymap_edit = WM_keymap_find(wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0); - + WM_event_add_keymap_handler(handlers, keymap_general); WM_event_add_keymap_handler(handlers, keymap_edit); } @@ -1354,20 +1450,20 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area) { + rcti rect, overlap_rect; + rcti window_rect; + if (!(area->flag & AREA_FLAG_REGION_SIZE_UPDATE)) { return; } - const int size_x = WM_window_pixels_x(win); - const int size_y = WM_window_pixels_y(win); - rcti rect, overlap_rect; - - area_calc_totrct(area, size_x, size_y); + WM_window_rect_calc(win, &window_rect); + area_calc_totrct(area, &window_rect); /* region rect sizes */ rect = area->totrct; overlap_rect = rect; - region_rect_recursive(win, area, area->regionbase.first, &rect, &overlap_rect, 0); + region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0); for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) { region_subwindow(ar); @@ -1384,36 +1480,38 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar /* called in screen_refresh, or screens_init, also area size changes */ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) { - const bScreen *screen = WM_window_get_active_screen(win); - const int window_size_x = WM_window_pixels_x(win); - const int window_size_y = WM_window_pixels_y(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + Scene *scene = WM_window_get_active_scene(win); ARegion *ar; rcti rect, overlap_rect; + rcti window_rect; if (ED_area_is_global(sa) && (sa->global->flag & GLOBAL_AREA_IS_HIDDEN)) { return; } + WM_window_rect_calc(win, &window_rect); /* set typedefinitions */ sa->type = BKE_spacetype_from_id(sa->spacetype); - + if (sa->type == NULL) { sa->spacetype = SPACE_VIEW3D; sa->type = BKE_spacetype_from_id(sa->spacetype); } for (ar = sa->regionbase.first; ar; ar = ar->next) - ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype); + ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype); /* area sizes */ - area_calc_totrct(sa, window_size_x, window_size_y); + area_calc_totrct(sa, &window_rect); /* region rect sizes */ rect = sa->totrct; overlap_rect = rect; - region_rect_recursive(win, sa, sa->regionbase.first, &rect, &overlap_rect, 0); + region_rect_recursive(sa, sa->regionbase.first, &rect, &overlap_rect, 0); sa->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE; - + /* default area handlers */ ed_default_handlers(wm, sa, &sa->handlers, sa->type->keymapflag); /* checks spacedata, adds own handlers */ @@ -1426,7 +1524,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* region windows, default and own handlers */ for (ar = sa->regionbase.first; ar; ar = ar->next) { region_subwindow(ar); - + if (ar->visible) { /* default region handlers */ ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag); @@ -1443,6 +1541,8 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* Some AZones use View2D data which is only updated in region init, so call that first! */ region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV); } + + WM_toolsystem_refresh_screen_area(workspace, scene, sa); } static void region_update_rect(ARegion *ar) @@ -1457,13 +1557,13 @@ static void region_update_rect(ARegion *ar) /** * Call to move a popup window (keep OpenGL context free!) */ -void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar) +void ED_region_update_rect(ARegion *ar) { region_update_rect(ar); } /* externally called for floating regions like menus */ -void ED_region_init(bContext *UNUSED(C), ARegion *ar) +void ED_region_init(ARegion *ar) { /* refresh can be called before window opened */ region_subwindow(ar); @@ -1477,6 +1577,9 @@ void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar) ar->type->cursor(win, sa, ar); } else { + if (WM_cursor_set_from_tool(win, sa, ar)) { + return; + } WM_cursor_set(win, CURSOR_STD); } } @@ -1485,10 +1588,10 @@ void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar) void ED_region_visibility_change_update(bContext *C, ARegion *ar) { ScrArea *sa = CTX_wm_area(C); - + if (ar->flag & RGN_FLAG_HIDDEN) WM_event_remove_handlers(C, &ar->handlers); - + ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); ED_area_tag_redraw(sa); } @@ -1497,9 +1600,9 @@ void ED_region_visibility_change_update(bContext *C, ARegion *ar) void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade) { ScrArea *sa = CTX_wm_area(C); - + ar->flag ^= RGN_FLAG_HIDDEN; - + if (do_fade && ar->overlap) { /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */ region_blend_start(C, sa, ar); @@ -1524,7 +1627,7 @@ void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free) ARegion *ar; const char spacetype = sa_dst->spacetype; const short flag_copy = HEADER_NO_PULLDOWN; - + sa_dst->spacetype = sa_src->spacetype; sa_dst->type = sa_src->type; @@ -1582,7 +1685,7 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2) /* tell WM to refresh, cursor types etc */ WM_event_add_mousemove(C); - + ED_area_tag_redraw(sa1); ED_area_tag_refresh(sa1); ED_area_tag_redraw(sa2); @@ -1631,7 +1734,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi for (sl = sa->spacedata.first; sl; sl = sl->next) if (sl->spacetype == type) break; - + /* old spacedata... happened during work on 2.50, remove */ if (sl && BLI_listbase_is_empty(&sl->regionbase)) { st->free(sl); @@ -1647,7 +1750,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi slold->regionbase = sa->regionbase; sa->regionbase = sl->regionbase; BLI_listbase_clear(&sl->regionbase); - + /* put in front of list */ BLI_remlink(&sa->spacedata, sl); BLI_addhead(&sa->spacedata, sl); @@ -1668,7 +1771,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi Scene *scene = WM_window_get_active_scene(win); sl = st->new(sa, scene); BLI_addhead(&sa->spacedata, sl); - + /* swap regions */ if (slold) slold->regionbase = sa->regionbase; @@ -1676,18 +1779,18 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi BLI_listbase_clear(&sl->regionbase); } } - + ED_area_initialize(CTX_wm_manager(C), win, sa); - + /* tell WM to refresh, cursor types etc */ WM_event_add_mousemove(C); - + /* send space change notifier */ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa); - + ED_area_tag_refresh(sa); } - + /* also redraw when re-used */ ED_area_tag_redraw(sa); } @@ -1727,7 +1830,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco) RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr); uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.6 * U.widget_unit, U.widget_unit, - &areaptr, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, ""); + &areaptr, "ui_type", 0, 0.0f, 0.0f, 0.0f, 0.0f, ""); return xco + 1.7 * U.widget_unit; } @@ -1755,46 +1858,162 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid) { - if (ar->overlap) { + if (ar->alignment == RGN_ALIGN_FLOAT) { + /* handle our own drawing. */ + } + else if (ar->overlap) { /* view should be in pixelspace */ UI_view2d_view_restore(C); float back[4]; UI_GetThemeColor4fv(colorid, back); - glClearColor(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]); - glClear(GL_COLOR_BUFFER_BIT); + GPU_clear_color(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]); + GPU_clear(GPU_COLOR_BIT); } else { UI_ThemeClearColor(colorid); - glClear(GL_COLOR_BUFFER_BIT); + GPU_clear(GPU_COLOR_BIT); } } -void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical) +BLI_INLINE bool streq_array_any(const char *s, const char *arr[]) { + for (uint i = 0; arr[i]; i++) { + if (STREQ(arr[i], s)) { + return true; + } + } + return false; +} + +static void ed_panel_draw( + const bContext *C, + ScrArea *sa, + ARegion *ar, + ListBase *lb, + PanelType *pt, + Panel *panel, + int w, + int em, + bool vertical) +{ + uiStyle *style = UI_style_get_dpi(); + + /* draw panel */ + uiBlock *block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS); + + bool open; + panel = UI_panel_begin(sa, ar, lb, block, pt, panel, &open); + + /* bad fixed values */ + int xco, yco, h = 0; + + if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + /* for preset menu */ + panel->layout = UI_block_layout( + block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, + 0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style); + + pt->draw_header_preset(C, panel); + + int headerend = w - UI_UNIT_X; + + UI_block_layout_resolve(block, &xco, &yco); + UI_block_translate(block, headerend - xco, 0); + panel->layout = NULL; + } + + if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + int labelx, labely; + UI_panel_label_offset(block, &labelx, &labely); + + /* for enabled buttons */ + panel->layout = UI_block_layout( + block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, + labelx, labely, UI_UNIT_Y, 1, 0, style); + + pt->draw_header(C, panel); + + UI_block_layout_resolve(block, &xco, &yco); + panel->labelofs = xco - labelx; + 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; + + if (yco != 0) { + h = -yco + 2 * style->panelspace; + } + } + + UI_block_end(C, block); + + /* Draw child panels. */ + if (open) { + for (LinkData *link = pt->children.first; link; link = link->next) { + PanelType *child_pt = link->data; + Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt); + + if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) { + ed_panel_draw(C, sa, ar, &panel->children, child_pt, child_panel, w, em, vertical); + } + } + } + + UI_panel_end(block, w, h); +} + +/** + * \param contexts: A NULL terminated array of context strings to match against. + * Matching against any of these strings will draw the panel. + * Can be NULL to skip context checks. + */ +void ED_region_panels_layout_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) +{ + ar->runtime.category = NULL; + const WorkSpace *workspace = CTX_wm_workspace(C); ScrArea *sa = CTX_wm_area(C); - uiStyle *style = UI_style_get_dpi(); - uiBlock *block; PanelType *pt; - Panel *panel; View2D *v2d = &ar->v2d; - View2DScrollers *scrollers; - int x, y, xco, yco, w, em, triangle; + int x, y, w, em; bool is_context_new = 0; int scroll; - bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)); /* XXX, should use some better check? */ + /* XXX, should use some better check? */ + bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)); /* 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; + const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *); if (contextnr != -1) is_context_new = UI_view2d_tab_set(v2d, contextnr); - + /* before setting the view */ if (vertical) { /* only allow scrolling in vertical direction */ @@ -1817,8 +2036,13 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c /* collect panels to draw */ for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) { + /* Only draw top level panels. */ + if (pt->parent) { + continue; + } + /* verify context */ - if (context && pt->context[0] && !STREQ(context, pt->context)) { + if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) { continue; } @@ -1878,9 +2102,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt) { - bool open; - - panel = UI_panel_find_by_type(ar, pt); + Panel *panel = UI_panel_find_by_type(&ar->panels, pt); if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) { if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) { @@ -1888,56 +2110,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c } } - /* 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); + ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical); } BLI_SMALLSTACK_ITER_END; @@ -1945,7 +2118,28 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c UI_panels_end(C, ar, &x, &y); /* before setting the view */ - if (vertical) { + if (region_layout_based) { + /* XXX, only single panel support atm. + * Can't use x/y values calculated above because they're not using the real height of panels, + * instead they calculate offsets for the next panel to start drawing. */ + Panel *panel = ar->panels.last; + if (panel != NULL) { + int size_dyn[2] = { + UI_UNIT_X * ((panel->flag & PNL_CLOSED) ? 8 : 14), + UI_panel_size_y(panel), + }; + /* region size is layout based and needs to be updated */ + if ((ar->sizex != size_dyn[0]) || + (ar->sizey != size_dyn[1])) + { + ar->sizex = size_dyn[0]; + ar->sizey = size_dyn[1]; + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + y = ABS(ar->sizey - 1); + } + } + else 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 */ @@ -1986,10 +2180,25 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c #endif } - region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); - + if (use_category_tabs) { + ar->runtime.category = category; + } +} +void ED_region_panels_layout(const bContext *C, ARegion *ar) +{ + ED_region_panels_layout_ex(C, ar, NULL, -1, true); +} + +void ED_region_panels_draw(const bContext *C, ARegion *ar) +{ + View2D *v2d = &ar->v2d; + + if (ar->alignment != RGN_ALIGN_FLOAT) { + region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + } + /* reset line width for drawing tabs */ - glLineWidth(1.0f); + GPU_line_width(1.0f); /* set the view */ UI_view2d_view_ortho(v2d); @@ -1999,17 +2208,35 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c /* restore view matrix */ UI_view2d_view_restore(C); - - if (use_category_tabs) { - UI_panel_category_draw_all(ar, category); + + /* Set in layout. */ + if (ar->runtime.category) { + UI_panel_category_draw_all(ar, ar->runtime.category); } /* scrollers */ - scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + View2DScrollers *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_view2d_scrollers_free(scrollers); } +void ED_region_panels_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) +{ + /* TODO: remove? */ + ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical); + ED_region_panels_draw(C, ar); +} + +void ED_region_panels(const bContext *C, ARegion *ar) +{ + /* TODO: remove? */ + ED_region_panels_layout(C, ar); + ED_region_panels_draw(C, ar); +} + void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) { wmKeyMap *keymap; @@ -2027,33 +2254,39 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) uiLayout *layout; HeaderType *ht; Header header = {NULL}; - int maxco, xco, yco; - int headery = ED_area_headersize(); - const int start_ofs = 0.4f * UI_UNIT_X; bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(&ar->v2d); + /* Height of buttons and scaling needed to achieve it. */ + const int buttony = min_ii(UI_UNIT_Y, ar->winy - 2 * UI_DPI_FAC); + const float buttony_scale = buttony / (float)UI_UNIT_Y; - xco = maxco = start_ofs; - yco = headery + (ar->winy - headery) / 2 - floor(0.2f * UI_UNIT_Y); + /* Vertically center buttons. */ + int xco = UI_HEADER_OFFSET; + int yco = buttony + (ar->winy - buttony) / 2; + int maxco = xco; /* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */ - if (CTX_wm_area(C)->spacetype == SPACE_TOPBAR) { - xco += 1; - yco += 1; + if (!ELEM(CTX_wm_area(C)->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR)) { + yco -= 1; } + /* set view2d view matrix for scrolling (without scrollers) */ + UI_view2d_view_ortho(&ar->v2d); + /* draw all headers types */ for (ht = ar->type->headertypes.first; ht; ht = ht->next) { block = UI_block_begin(C, ar, ht->idname, UI_EMBOSS); - layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, 0, style); + layout = UI_block_layout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, buttony, 1, 0, style); + + if (buttony_scale != 1.0f) { + uiLayoutSetScaleY(layout, buttony_scale); + } if (ht->draw) { header.type = ht; header.layout = layout; ht->draw(C, &header); - + /* for view2d */ xco = uiLayoutGetWidth(layout); if (xco > maxco) @@ -2061,12 +2294,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) } UI_block_layout_resolve(block, &xco, &yco); - + /* for view2d */ if (xco > maxco) maxco = xco; - int new_sizex = (maxco + start_ofs) / UI_DPI_FAC; + int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC; if (region_layout_based && (ar->sizex != new_sizex)) { /* region size is layout based and needs to be updated */ @@ -2079,8 +2312,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) UI_block_end(C, block); } + if (!region_layout_based) { + maxco += UI_HEADER_OFFSET; + } + /* always as last */ - UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery); + UI_view2d_totRect_set(&ar->v2d, maxco, ar->winy); /* restore view matrix */ UI_view2d_view_restore(C); @@ -2088,11 +2325,11 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) void ED_region_header_draw(const bContext *C, ARegion *ar) { - UI_view2d_view_ortho(&ar->v2d); - /* clear */ region_clear_color(C, ar, region_background_color_id(C, ar)); + UI_view2d_view_ortho(&ar->v2d); + /* View2D matrix might have changed due to dynamic sized regions. */ UI_blocklist_update_window_matrix(C, &ar->uiblocks); @@ -2141,6 +2378,16 @@ int ED_area_global_size_y(const ScrArea *area) BLI_assert(ED_area_is_global(area)); return round_fl_to_int(area->global->cur_fixed_height * UI_DPI_FAC); } +int ED_area_global_min_size_y(const ScrArea *area) +{ + BLI_assert(ED_area_is_global(area)); + return round_fl_to_int(area->global->size_min * UI_DPI_FAC); +} +int ED_area_global_max_size_y(const ScrArea *area) +{ + BLI_assert(ED_area_is_global(area)); + return round_fl_to_int(area->global->size_max * UI_DPI_FAC); +} bool ED_area_is_global(const ScrArea *area) { @@ -2191,7 +2438,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float const int header_height = UI_UNIT_Y; uiStyle *style = UI_style_get_dpi(); int fontid = style->widget.uifont_id; - GLint scissor[4]; + int scissor[4]; rcti rect; int num_lines = 0; @@ -2216,23 +2463,22 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float } } - rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height * num_lines; - rect.ymax = BLI_rcti_size_y(&ar->winrct); + rect.ymin = rect.ymax - header_height * num_lines; /* setup scissor */ - glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(rect.xmin, rect.ymin, + GPU_scissor_geti(scissor); + GPU_scissor(rect.xmin, rect.ymin, BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1); - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); 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); immUniformColor4fv(fill_color); immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1); immUnbindProgram(); - glDisable(GL_BLEND); + GPU_blend(false); /* text */ UI_FontThemeColor(fontid, TH_TEXT_HI); @@ -2252,7 +2498,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float BLF_disable(fontid, BLF_CLIPPING); /* restore scissor as it was before */ - glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); } void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw) @@ -2361,7 +2607,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const if (metadata_is_valid(ibuf, temp_str, i, len)) { BLF_position(fontid, xmin + ofs_x, ymin, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - + ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X; } } @@ -2501,7 +2747,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) Gwn_VertFormat *format = immVertexFormat(); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, 20); immRectf(pos, x1, y1, x2, y2); @@ -2535,14 +2781,14 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) GWN_vertformat_clear(format); pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); immBegin(GWN_PRIM_LINES, 4 * count_fine + 4 * count_large); - + float theme_color[3]; UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color); fac = 0.0f; - + /* the fine resolution level */ for (int i = 0; i < count_fine; i++) { immAttrib3fv(color, theme_color); @@ -2559,7 +2805,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) if (count_large > 0) { UI_GetThemeColor3fv(TH_BACK, theme_color); fac = 0.0f; - + /* the large resolution level */ for (int i = 0; i < count_large; i++) { immAttrib3fv(color, theme_color); @@ -2584,25 +2830,43 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) void ED_region_visible_rect(ARegion *ar, rcti *rect) { ARegion *arn = ar; - + /* allow function to be called without area */ while (arn->prev) arn = arn->prev; - + *rect = ar->winrct; - + /* check if a region overlaps with the current one */ for (; arn; arn = arn->next) { if (ar != arn && arn->overlap) { if (BLI_rcti_isect(rect, &arn->winrct, NULL)) { - - /* overlap left, also check 1 pixel offset (2 regions on one side) */ - if (ABS(rect->xmin - arn->winrct.xmin) < 2) - rect->xmin = arn->winrct.xmax; - - /* overlap right */ - if (ABS(rect->xmax - arn->winrct.xmax) < 2) - rect->xmax = arn->winrct.xmin; + if (ELEM(arn->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) { + /* Overlap left, also check 1 pixel offset (2 regions on one side). */ + if (ABS(rect->xmin - arn->winrct.xmin) < 2) { + rect->xmin = arn->winrct.xmax; + } + + /* Overlap right. */ + if (ABS(rect->xmax - arn->winrct.xmax) < 2) { + rect->xmax = arn->winrct.xmin; + } + } + else if (ELEM(arn->alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) { + /* Same logic as above for vertical regions. */ + if (ABS(rect->ymin - arn->winrct.ymin) < 2) { + rect->ymin = arn->winrct.ymax; + } + if (ABS(rect->ymax - arn->winrct.ymax) < 2) { + rect->ymax = arn->winrct.ymin; + } + } + else if (arn->alignment == RGN_ALIGN_FLOAT) { + /* Skip floating. */ + } + else { + BLI_assert(!"Region overlap with unknown alignment"); + } } } } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 39178af9e4e..6cff82295f0 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -51,6 +51,7 @@ #include "GPU_basic_shader.h" #include "GPU_immediate.h" #include "GPU_matrix.h" +#include "GPU_state.h" #include "UI_interface.h" @@ -59,11 +60,11 @@ void setlinestyle(int nr) { if (nr == 0) { - glDisable(GL_LINE_STIPPLE); + GPU_line_stipple(false); } else { - - glEnable(GL_LINE_STIPPLE); + + GPU_line_stipple(true); if (U.pixelsize > 1.0f) glLineStipple(nr, 0xCCCC); else @@ -72,10 +73,10 @@ void setlinestyle(int nr) } /* Invert line handling */ - + #define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode)) -void set_inverted_drawing(int enable) +void set_inverted_drawing(int enable) { glLogicOp(enable ? GL_INVERT : GL_COPY); GL_TOGGLE(GL_COLOR_LOGIC_OP, enable); @@ -355,18 +356,18 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, void bglPolygonOffset(float viewdist, float dist) { static float winmat[16], offset = 0.0f; - + if (dist != 0.0f) { float offs; - + // glEnable(GL_POLYGON_OFFSET_FILL); // glPolygonOffset(-1.0, -1.0); /* hack below is to mimic polygon offset */ gpuGetProjectionMatrix(winmat); - + /* dist is from camera to center point */ - + if (winmat[15] > 0.5f) { #if 1 offs = 0.00001f * dist * viewdist; // ortho tweaking @@ -391,7 +392,7 @@ void bglPolygonOffset(float viewdist, float dist) */ offs = winmat[14] * -0.0025f * dist; } - + winmat[14] -= offs; offset += offs; } diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 85087d58276..fa18826005e 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -80,7 +80,7 @@ const char *screen_context_dir[] = { "sequences", "selected_sequences", "selected_editable_sequences", /* sequencer */ "gpencil_data", "gpencil_data_owner", /* grease pencil data */ "visible_gpencil_layers", "editable_gpencil_layers", "editable_gpencil_strokes", - "active_gpencil_layer", "active_gpencil_frame", "active_gpencil_palette", + "active_gpencil_layer", "active_gpencil_frame", "active_gpencil_palette", "active_gpencil_palettecolor", "active_gpencil_brush", "active_operator", "selected_editable_fcurves", NULL}; @@ -115,7 +115,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selectable_objects")) { for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + if (((base->flag & BASE_VISIBLE) != 0) && ((base->flag & BASE_SELECTABLE) != 0)) { CTX_data_id_list_add(result, &base->object->id); } } @@ -165,7 +165,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "selectable_bases")) { for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_SELECTABLED) != 0) { + if ((base->flag & BASE_SELECTABLE) != 0) { CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } @@ -195,7 +195,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "editable_bases")) { /* Visible + Editable, but not necessarily selected */ for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_VISIBLED) != 0) { + if ((base->flag & BASE_VISIBLE) != 0) { if (0 == BKE_object_is_libdata(base->object)) { CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } @@ -208,7 +208,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *ebone, *flipbone = NULL; const bool editable_bones = CTX_data_equals(member, "editable_bones"); - + if (arm && arm->edbo) { uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len); @@ -259,7 +259,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL; EditBone *ebone, *flipbone = NULL; const bool selected_editable_bones = CTX_data_equals(member, "selected_editable_bones"); - + if (arm && arm->edbo) { uint objects_len; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len); @@ -364,7 +364,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "active_pose_bone")) { bPoseChannel *pchan; Object *obpose = BKE_object_pose_armature_get(obact); - + pchan = BKE_pose_channel_active(obpose); if (pchan) { CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan); @@ -393,7 +393,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult /* convenience for now, 1 object per scene in editmode */ if (obedit) CTX_data_id_pointer_set(result, &obedit->id); - + return 1; } else if (CTX_data_equals(member, "sculpt_object")) { @@ -465,11 +465,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "gpencil_data")) { /* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these situations - * (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when + * (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when * called from context. For that reason, we end up using an alternative where we pass everything in! */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { CTX_data_id_pointer_set(result, &gpd->id); return 1; @@ -477,14 +477,14 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } else if (CTX_data_equals(member, "gpencil_data_owner")) { /* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data) - * XXX: see comment for gpencil_data case... + * XXX: see comment for gpencil_data case... */ bGPdata **gpd_ptr = NULL; PointerRNA ptr; - + /* get pointer to Grease Pencil Data */ gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, scene, sa, obact, &ptr); - + if (gpd_ptr) { CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data); return 1; @@ -493,10 +493,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "active_gpencil_layer")) { /* XXX: see comment for gpencil_data case... */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + if (gpl) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl); return 1; @@ -544,10 +544,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "active_gpencil_frame")) { /* XXX: see comment for gpencil_data case... */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + if (gpl) { CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe); return 1; @@ -557,10 +557,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "visible_gpencil_layers")) { /* XXX: see comment for gpencil_data case... */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { bGPDlayer *gpl; - + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if ((gpl->flag & GP_LAYER_HIDE) == 0) { CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl); @@ -573,10 +573,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "editable_gpencil_layers")) { /* XXX: see comment for gpencil_data case... */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { bGPDlayer *gpl; - + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpencil_layer_is_editable(gpl)) { CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl); @@ -589,15 +589,15 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult else if (CTX_data_equals(member, "editable_gpencil_strokes")) { /* XXX: see comment for gpencil_data case... */ bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact); - + if (gpd) { bGPDlayer *gpl; - + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; - + for (gps = gpf->strokes.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use_direct(sa, gps)) { /* check if the color is editable */ @@ -665,4 +665,3 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return -1; /* found but not available */ } - diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index fec39ade110..b5b0d16f6a7 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -27,6 +27,7 @@ #include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_matrix.h" +#include "GPU_state.h" #include "BLI_math.h" @@ -43,11 +44,11 @@ */ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos) { + const float width = screen_geom_area_width(sa) - 1; + const float height = screen_geom_area_height(sa) - 1; vec2f points[10]; short i; float w, h; - float width = sa->v3->vec.x - sa->v1->vec.x; - float height = sa->v3->vec.y - sa->v1->vec.y; if (height < width) { h = height / 8; @@ -124,11 +125,11 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos) */ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos) { + const float width = screen_geom_area_width(sa) - 1; + const float height = screen_geom_area_height(sa) - 1; vec2f points[10]; short i; float w, h; - float width = sa->v3->vec.x - sa->v1->vec.x; - float height = sa->v3->vec.y - sa->v1->vec.y; if (height < width) { h = height / 4; @@ -353,7 +354,7 @@ static void drawscredge_corner(ScrArea *sa, int sizex, int sizey) */ static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos) { - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); immUniformColor4ub(0, 0, 0, 50); draw_join_shape(sa, dir, pos); @@ -364,7 +365,7 @@ static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos) */ static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos) { - glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); + GPU_blend_set_func(GPU_DST_COLOR, GPU_SRC_ALPHA); /* value 181 was hardly computed: 181~105 */ immUniformColor4ub(255, 255, 255, 50); /* draw_join_shape(sa, dir); */ @@ -444,7 +445,7 @@ void ED_screen_draw_edges(wmWindow *win) /* Note: first loop only draws if U.pixelsize > 1, skip otherwise */ if (U.pixelsize > 1.0f) { /* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */ - glLineWidth((2.0f * U.pixelsize) - 1); + GPU_line_width((2.0f * U.pixelsize) - 1); immUniformThemeColor(TH_EDITOR_OUTLINE); for (sa = screen->areabase.first; sa; sa = sa->next) { @@ -452,7 +453,7 @@ void ED_screen_draw_edges(wmWindow *win) } } - glLineWidth(1); + GPU_line_width(1); immUniformThemeColor(TH_EDITOR_OUTLINE); for (sa = screen->areabase.first; sa; sa = sa->next) { @@ -479,7 +480,7 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2) unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glLineWidth(1); + GPU_line_width(1); /* blended join arrow */ int dir = area_getorientation(sa1, sa2); @@ -504,12 +505,12 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2) break; } - glEnable(GL_BLEND); + GPU_blend(true); scrarea_draw_shape_dark(sa2, dir, pos); scrarea_draw_shape_light(sa1, dira, pos); - glDisable(GL_BLEND); + GPU_blend(false); } immUnbindProgram(); @@ -521,7 +522,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac) immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* splitpoint */ - glEnable(GL_BLEND); + GPU_blend(true); immUniformColor4ub(255, 255, 255, 100); immBegin(GWN_PRIM_LINES, 2); @@ -562,7 +563,7 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac) immEnd(); } - glDisable(GL_BLEND); + GPU_blend(false); immUnbindProgram(); } @@ -645,8 +646,8 @@ void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uns GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out); GPU_offscreen_bind(offscreen, true); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GPU_clear_color(0.0, 0.0, 0.0, 0.0); + GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT); screen_preview_draw(screen, size_x, size_y); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 8ebdb5f32b8..6bc8a6c10cf 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -74,98 +74,6 @@ #include "screen_intern.h" /* own module include */ -/* ******************* screen vert, edge, area managing *********************** */ - -static ScrVert *screen_addvert_ex(ScrAreaMap *area_map, short x, short y) -{ - ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert"); - sv->vec.x = x; - sv->vec.y = y; - - BLI_addtail(&area_map->vertbase, sv); - return sv; -} -static ScrVert *screen_addvert(bScreen *sc, short x, short y) -{ - return screen_addvert_ex(AREAMAP_FROM_SCREEN(sc), x, y); -} - -static ScrEdge *screen_addedge_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2) -{ - ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge"); - - BKE_screen_sort_scrvert(&v1, &v2); - se->v1 = v1; - se->v2 = v2; - - BLI_addtail(&area_map->edgebase, se); - return se; -} -static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2) -{ - return screen_addedge_ex(AREAMAP_FROM_SCREEN(sc), v1, v2); -} - -bool scredge_is_horizontal(ScrEdge *se) -{ - return (se->v1->vec.y == se->v2->vec.y); -} - -/* need win size to make sure not to include edges along screen edge */ -ScrEdge *screen_area_map_find_active_scredge( - const ScrAreaMap *area_map, - const int winsize_x, const int winsize_y, - const int mx, const int my) -{ - int safety = U.widget_unit / 10; - - CLAMP_MIN(safety, 2); - - for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) { - if (scredge_is_horizontal(se)) { - if (se->v1->vec.y > 0 && se->v1->vec.y < winsize_y - 1) { - short min, max; - min = MIN2(se->v1->vec.x, se->v2->vec.x); - max = MAX2(se->v1->vec.x, se->v2->vec.x); - - if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max) - return se; - } - } - else { - if (se->v1->vec.x > 0 && se->v1->vec.x < winsize_x - 1) { - short min, max; - min = MIN2(se->v1->vec.y, se->v2->vec.y); - max = MAX2(se->v1->vec.y, se->v2->vec.y); - - if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max) - return se; - } - } - } - - return NULL; -} - -/* need win size to make sure not to include edges along screen edge */ -ScrEdge *screen_find_active_scredge( - const wmWindow *win, const bScreen *screen, - const int mx, const int my) -{ - /* Use layout size (screen excluding global areas) for screen-layout area edges */ - const int screen_x = WM_window_screen_pixels_x(win), screen_y = WM_window_screen_pixels_y(win); - ScrEdge *se = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), screen_x, screen_y, mx, my); - - if (!se) { - /* Use entire window size (screen including global areas) for global area edges */ - const int win_x = WM_window_pixels_x(win), win_y = WM_window_pixels_y(win); - se = screen_area_map_find_active_scredge(&win->global_areas, win_x, win_y, mx, my); - } - return se; -} - - - /* adds no space data */ static ScrArea *screen_addarea_ex( ScrAreaMap *area_map, @@ -195,81 +103,45 @@ static ScrArea *screen_addarea( static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa) { - + ED_area_exit(C, sa); - + BKE_screen_area_free(sa); - + BLI_remlink(&sc->areabase, sa); MEM_freeN(sa); } -/* return 0: no split possible */ -/* else return (integer) screencoordinate split point */ -static short testsplitpoint(ScrArea *sa, char dir, float fac) -{ - short x, y; - const short area_min_x = AREAMINX; - const short area_min_y = ED_area_headersize(); - - // area big enough? - if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0; - if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0; - - // to be sure - CLAMP(fac, 0.0f, 1.0f); - - if (dir == 'h') { - y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y); - - if (y - sa->v1->vec.y < area_min_y) - y = sa->v1->vec.y + area_min_y; - else if (sa->v2->vec.y - y < area_min_y) - y = sa->v2->vec.y - area_min_y; - else y -= (y % AREAGRID); - - return y; - } - else { - x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x); - - if (x - sa->v1->vec.x < area_min_x) - x = sa->v1->vec.x + area_min_x; - else if (sa->v4->vec.x - x < area_min_x) - x = sa->v4->vec.x - area_min_x; - else x -= (x % AREAGRID); - - return x; - } -} - -ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) +ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge) { ScrArea *newa = NULL; ScrVert *sv1, *sv2; short split; - + rcti window_rect; + if (sa == NULL) return NULL; - - split = testsplitpoint(sa, dir, fac); + + WM_window_rect_calc(win, &window_rect); + + split = screen_geom_find_area_split_point(sa, &window_rect, dir, fac); if (split == 0) return NULL; - + /* note regarding (fac > 0.5f) checks below. * normally it shouldn't matter which is used since the copy should match the original * however with viewport rendering and python console this isn't the case. - campbell */ if (dir == 'h') { /* new vertices */ - sv1 = screen_addvert(sc, sa->v1->vec.x, split); - sv2 = screen_addvert(sc, sa->v4->vec.x, split); - + sv1 = screen_geom_vertex_add(sc, sa->v1->vec.x, split); + sv2 = screen_geom_vertex_add(sc, sa->v4->vec.x, split); + /* new edges */ - screen_addedge(sc, sa->v1, sv1); - screen_addedge(sc, sv1, sa->v2); - screen_addedge(sc, sa->v3, sv2); - screen_addedge(sc, sv2, sa->v4); - screen_addedge(sc, sv1, sv2); - + screen_geom_edge_add(sc, sa->v1, sv1); + screen_geom_edge_add(sc, sv1, sa->v2); + screen_geom_edge_add(sc, sa->v3, sv2); + screen_geom_edge_add(sc, sv2, sa->v4); + screen_geom_edge_add(sc, sv1, sv2); + if (fac > 0.5f) { /* new areas: top */ newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype); @@ -288,20 +160,20 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) } ED_area_data_copy(newa, sa, true); - + } else { /* new vertices */ - sv1 = screen_addvert(sc, split, sa->v1->vec.y); - sv2 = screen_addvert(sc, split, sa->v2->vec.y); - + sv1 = screen_geom_vertex_add(sc, split, sa->v1->vec.y); + sv2 = screen_geom_vertex_add(sc, split, sa->v2->vec.y); + /* new edges */ - screen_addedge(sc, sa->v1, sv1); - screen_addedge(sc, sv1, sa->v4); - screen_addedge(sc, sa->v2, sv2); - screen_addedge(sc, sv2, sa->v3); - screen_addedge(sc, sv1, sv2); - + screen_geom_edge_add(sc, sa->v1, sv1); + screen_geom_edge_add(sc, sv1, sa->v4); + screen_geom_edge_add(sc, sa->v2, sv2); + screen_geom_edge_add(sc, sv2, sa->v3); + screen_geom_edge_add(sc, sv1, sv2); + if (fac > 0.5f) { /* new areas: right */ newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype); @@ -321,41 +193,41 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) ED_area_data_copy(newa, sa, true); } - + /* remove double vertices en edges */ if (merge) BKE_screen_remove_double_scrverts(sc); BKE_screen_remove_double_scredges(sc); BKE_screen_remove_unused_scredges(sc); - + return newa; } /** * Empty screen, with 1 dummy area without spacedata. Uses window size. */ -bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y) +bScreen *screen_add(Main *bmain, const char *name, const rcti *rect) { bScreen *sc; ScrVert *sv1, *sv2, *sv3, *sv4; - - sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0); + + sc = BKE_libblock_alloc(bmain, ID_SCR, name, 0); sc->do_refresh = true; sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN; - sv1 = screen_addvert(sc, 0, 0); - sv2 = screen_addvert(sc, 0, winsize_y - 1); - sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1); - sv4 = screen_addvert(sc, winsize_x - 1, 0); - - screen_addedge(sc, sv1, sv2); - screen_addedge(sc, sv2, sv3); - screen_addedge(sc, sv3, sv4); - screen_addedge(sc, sv4, sv1); - + sv1 = screen_geom_vertex_add(sc, rect->xmin, rect->ymin); + sv2 = screen_geom_vertex_add(sc, rect->xmin, rect->ymax - 1); + sv3 = screen_geom_vertex_add(sc, rect->xmax - 1, rect->ymax - 1); + sv4 = screen_geom_vertex_add(sc, rect->xmax - 1, rect->ymin); + + screen_geom_edge_add(sc, sv1, sv2); + screen_geom_edge_add(sc, sv2, sv3); + screen_geom_edge_add(sc, sv3, sv4); + screen_geom_edge_add(sc, sv4, sv1); + /* dummy type, no spacedata */ screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY); - + return sc; } @@ -364,26 +236,26 @@ void screen_data_copy(bScreen *to, bScreen *from) ScrVert *s1, *s2; ScrEdge *se; ScrArea *sa, *saf; - + /* free contents of 'to', is from blenkernel screen.c */ BKE_screen_free(to); - + BLI_duplicatelist(&to->vertbase, &from->vertbase); BLI_duplicatelist(&to->edgebase, &from->edgebase); BLI_duplicatelist(&to->areabase, &from->areabase); BLI_listbase_clear(&to->regionbase); - + s2 = to->vertbase.first; for (s1 = from->vertbase.first; s1; s1 = s1->next, s2 = s2->next) { s1->newv = s2; } - + for (se = to->edgebase.first; se; se = se->next) { se->v1 = se->v1->newv; se->v2 = se->v2->newv; BKE_screen_sort_scrvert(&(se->v1), &(se->v2)); } - + saf = from->areabase.first; for (sa = to->areabase.first; sa; sa = sa->next, saf = saf->next) { sa->v1 = sa->v1->newv; @@ -395,10 +267,10 @@ void screen_data_copy(bScreen *to, bScreen *from) BLI_listbase_clear(&sa->regionbase); BLI_listbase_clear(&sa->actionzones); BLI_listbase_clear(&sa->handlers); - + ED_area_data_copy(sa, saf, true); } - + /* put at zero (needed?) */ for (s1 = from->vertbase.first; s1; s1 = s1->next) s1->newv = NULL; @@ -433,7 +305,7 @@ int area_getorientation(ScrArea *sa, ScrArea *sb) sbv2 = sb->v2; sbv3 = sb->v3; sbv4 = sb->v4; - + if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */ return 0; } @@ -446,7 +318,7 @@ int area_getorientation(ScrArea *sa, ScrArea *sb) else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/ return 3; } - + return -1; } @@ -456,39 +328,39 @@ int area_getorientation(ScrArea *sa, ScrArea *sb) int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2) { int dir; - + dir = area_getorientation(sa1, sa2); /*printf("dir is : %i\n", dir);*/ - + if (dir == -1) { return 0; } - + if (dir == 0) { sa1->v1 = sa2->v1; sa1->v2 = sa2->v2; - screen_addedge(scr, sa1->v2, sa1->v3); - screen_addedge(scr, sa1->v1, sa1->v4); + screen_geom_edge_add(scr, sa1->v2, sa1->v3); + screen_geom_edge_add(scr, sa1->v1, sa1->v4); } else if (dir == 1) { sa1->v2 = sa2->v2; sa1->v3 = sa2->v3; - screen_addedge(scr, sa1->v1, sa1->v2); - screen_addedge(scr, sa1->v3, sa1->v4); + screen_geom_edge_add(scr, sa1->v1, sa1->v2); + screen_geom_edge_add(scr, sa1->v3, sa1->v4); } else if (dir == 2) { sa1->v3 = sa2->v3; sa1->v4 = sa2->v4; - screen_addedge(scr, sa1->v2, sa1->v3); - screen_addedge(scr, sa1->v1, sa1->v4); + screen_geom_edge_add(scr, sa1->v2, sa1->v3); + screen_geom_edge_add(scr, sa1->v1, sa1->v4); } else if (dir == 3) { sa1->v1 = sa2->v1; sa1->v4 = sa2->v4; - screen_addedge(scr, sa1->v1, sa1->v2); - screen_addedge(scr, sa1->v3, sa1->v4); + screen_geom_edge_add(scr, sa1->v1, sa1->v2); + screen_geom_edge_add(scr, sa1->v3, sa1->v4); } - + screen_delarea(C, scr, sa2); BKE_screen_remove_double_scrverts(scr); /* Update preview thumbnail */ @@ -497,241 +369,6 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2) return 1; } -void select_connected_scredge(const wmWindow *win, ScrEdge *edge) -{ - bScreen *sc = WM_window_get_active_screen(win); - ScrEdge *se; - int oneselected; - char dir; - - /* select connected, only in the right direction */ - /* 'dir' is the direction of EDGE */ - - if (edge->v1->vec.x == edge->v2->vec.x) dir = 'v'; - else dir = 'h'; - - ED_screen_verts_iter(win, sc, sv) { - sv->flag = 0; - } - - edge->v1->flag = 1; - edge->v2->flag = 1; - - oneselected = 1; - while (oneselected) { - se = sc->edgebase.first; - oneselected = 0; - while (se) { - if (se->v1->flag + se->v2->flag == 1) { - if (dir == 'h') { - if (se->v1->vec.y == se->v2->vec.y) { - se->v1->flag = se->v2->flag = 1; - oneselected = 1; - } - } - if (dir == 'v') { - if (se->v1->vec.x == se->v2->vec.x) { - se->v1->flag = se->v2->flag = 1; - oneselected = 1; - } - } - } - se = se->next; - } - } -} - -/** - * Test if screen vertices should be scaled and do if needed. - */ -static void screen_vertices_scale( - const wmWindow *win, bScreen *sc, - int window_size_x, int window_size_y, - int screen_size_x, int screen_size_y) -{ - /* clamp Y size of header sized areas when expanding windows - * avoids annoying empty space around file menu */ -#define USE_HEADER_SIZE_CLAMP - - const int headery_init = ED_area_headersize(); - ScrVert *sv = NULL; - ScrArea *sa; - int screen_size_x_prev, screen_size_y_prev; - float facx, facy, tempf, min[2], max[2]; - - /* calculate size */ - min[0] = min[1] = 20000.0f; - max[0] = max[1] = 0.0f; - - for (sv = sc->vertbase.first; sv; sv = sv->next) { - const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y}; - minmax_v2v2_v2(min, max, fv); - } - - /* always make 0.0 left under */ - for (sv = sc->vertbase.first; sv; sv = sv->next) { - sv->vec.x -= min[0]; - sv->vec.y -= min[1]; - } - - screen_size_x_prev = (max[0] - min[0]) + 1; - screen_size_y_prev = (max[1] - min[1]) + 1; - - -#ifdef USE_HEADER_SIZE_CLAMP -#define TEMP_BOTTOM 1 -#define TEMP_TOP 2 - - /* if the window's Y axis grows, clamp header sized areas */ - if (screen_size_y_prev < screen_size_y) { /* growing? */ - const int headery_margin_max = headery_init + 4; - for (sa = sc->areabase.first; sa; sa = sa->next) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); - sa->temp = 0; - - if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) { - if (sa->v2->vec.y == screen_size_y_prev) { - if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) { - sa->temp = TEMP_TOP; - } - } - else if (sa->v1->vec.y == 0) { - if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) { - sa->temp = TEMP_BOTTOM; - } - } - } - } - } -#endif - - - if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) { - facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1); - facy = ((float)screen_size_y) / ((float)screen_size_y_prev); - - /* make sure it fits! */ - for (sv = sc->vertbase.first; sv; sv = sv->next) { - /* FIXME, this re-sizing logic is no good when re-sizing the window + redrawing [#24428] - * need some way to store these as floats internally and re-apply from there. */ - tempf = ((float)sv->vec.x) * facx; - sv->vec.x = (short)(tempf + 0.5f); - //sv->vec.x += AREAGRID - 1; - //sv->vec.x -= (sv->vec.x % AREAGRID); - - CLAMP(sv->vec.x, 0, screen_size_x - 1); - - tempf = ((float)sv->vec.y) * facy; - sv->vec.y = (short)(tempf + 0.5f); - //sv->vec.y += AREAGRID - 1; - //sv->vec.y -= (sv->vec.y % AREAGRID); - - CLAMP(sv->vec.y, 0, screen_size_y); - } - } - - -#ifdef USE_HEADER_SIZE_CLAMP - if (screen_size_y_prev < screen_size_y) { /* growing? */ - for (sa = sc->areabase.first; sa; sa = sa->next) { - ScrEdge *se = NULL; - - if (sa->temp == 0) - continue; - - if (sa->v1 == sa->v2) - continue; - - /* adjust headery if verts are along the edge of window */ - if (sa->temp == TEMP_TOP) { - /* lower edge */ - const int yval = sa->v2->vec.y - headery_init; - se = BKE_screen_find_edge(sc, sa->v4, sa->v1); - if (se != NULL) { - select_connected_scredge(win, se); - } - for (sv = sc->vertbase.first; sv; sv = sv->next) { - if (sv != sa->v2 && sv != sa->v3) { - if (sv->flag) { - sv->vec.y = yval; - } - } - } - } - else { - /* upper edge */ - const int yval = sa->v1->vec.y + headery_init; - se = BKE_screen_find_edge(sc, sa->v2, sa->v3); - if (se != NULL) { - select_connected_scredge(win, se); - } - for (sv = sc->vertbase.first; sv; sv = sv->next) { - if (sv != sa->v1 && sv != sa->v4) { - if (sv->flag) { - sv->vec.y = yval; - } - } - } - } - } - } - -#undef USE_HEADER_SIZE_CLAMP -#undef TEMP_BOTTOM -#undef TEMP_TOP -#endif - - - /* test for collapsed areas. This could happen in some blender version... */ - /* ton: removed option now, it needs Context... */ - - /* make each window at least ED_area_headersize() high */ - for (sa = sc->areabase.first; sa; sa = sa->next) { - int headery = headery_init; - - /* adjust headery if verts are along the edge of window */ - if (sa->v1->vec.y > 0) - headery += U.pixelsize; - if (sa->v2->vec.y < screen_size_y) - headery += U.pixelsize; - - if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) { - /* lower edge */ - ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1); - if (se && sa->v1 != sa->v2) { - int yval; - - select_connected_scredge(win, se); - - /* all selected vertices get the right offset */ - yval = sa->v2->vec.y - headery + 1; - for (sv = sc->vertbase.first; sv; sv = sv->next) { - /* if is a collapsed area */ - if (sv != sa->v2 && sv != sa->v3) { - if (sv->flag) { - sv->vec.y = yval; - } - } - } - } - } - } - - /* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. - * TODO Assumes global area to be top-aligned. Should be made more generic */ - for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { - if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) { - continue; - } - /* width */ - area->v1->vec.x = area->v2->vec.x = 0; - area->v3->vec.x = area->v4->vec.x = window_size_x - 1; - /* height */ - area->v2->vec.y = area->v3->vec.y = window_size_y - 1; - area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - ED_area_global_size_y(area); - } -} - /* ****************** EXPORTED API TO OTHER MODULES *************************** */ @@ -787,7 +424,7 @@ static void screen_refresh_headersizes(void) { const ListBase *lb = BKE_spacetypes_list(); SpaceType *st; - + for (st = lb->first; st; st = st->next) { ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER); if (art) art->prefsizey = ED_area_headersize(); @@ -802,23 +439,23 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) /* exception for bg mode, we only need the screen context */ if (!G.background) { - const int window_size_x = WM_window_pixels_x(win); - const int window_size_y = WM_window_pixels_y(win); - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti window_rect, screen_rect; /* header size depends on DPI, let's verify */ WM_window_set_dpi(win); screen_refresh_headersizes(); - screen_vertices_scale(win, screen, window_size_x, window_size_y, screen_size_x, screen_size_y); + WM_window_rect_calc(win, &window_rect); + WM_window_screen_rect_calc(win, &screen_rect); /* Get screen bounds __after__ updating window DPI! */ + + screen_geom_vertices_scale(win, screen); ED_screen_areas_iter(win, screen, area) { /* set spacetype and region callbacks, calls init() */ /* sets subwindows for regions, adds handlers */ ED_area_initialize(wm, win, area); } - + /* wake up animtimer */ if (screen->animtimer) WM_event_timer_sleep(wm, win, screen->animtimer, false); @@ -835,19 +472,22 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) } /* file read, set all screens, ... */ -void ED_screens_initialize(wmWindowManager *wm) +void ED_screens_initialize(Main *bmain, wmWindowManager *wm) { wmWindow *win; - + for (win = wm->windows.first; win; win = win->next) { if (WM_window_get_active_workspace(win) == NULL) { - WM_window_set_active_workspace(win, G.main->workspaces.first); + WM_window_set_active_workspace(win, bmain->workspaces.first); } if (BLI_listbase_is_empty(&win->global_areas.areabase)) { ED_screen_global_areas_create(win); } ED_screen_refresh(wm, win); + if (win->eventstate) { + ED_screen_set_active_region(NULL, win, &win->eventstate->x); + } } } @@ -875,12 +515,12 @@ void ED_region_exit(bContext *C, ARegion *ar) WM_event_remove_handlers(C, &ar->handlers); WM_event_modal_handler_region_replace(win, ar, NULL); WM_draw_region_free(ar); - + if (ar->headerstr) { MEM_freeN(ar->headerstr); ar->headerstr = NULL; } - + if (ar->regiontimer) { WM_event_remove_timer(wm, win, ar->regiontimer); ar->regiontimer = NULL; @@ -916,31 +556,30 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *prevwin = CTX_wm_window(C); - ScrArea *sa; - ARegion *ar; CTX_wm_window_set(C, window); - + if (screen->animtimer) WM_event_remove_timer(wm, window, screen->animtimer); screen->animtimer = NULL; screen->scrubbing = false; screen->active_region = NULL; - - for (ar = screen->regionbase.first; ar; ar = ar->next) { + + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { ED_region_exit(C, ar); } - for (sa = screen->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { ED_area_exit(C, sa); } - for (sa = window->global_areas.areabase.first; sa; sa = sa->next) { + /* Don't use ED_screen_areas_iter here, it skips hidden areas. */ + for (ScrArea *sa = window->global_areas.areabase.first; sa; sa = sa->next) { ED_area_exit(C, sa); } /* mark it available for use for other windows */ screen->winid = 0; - + if (!WM_window_is_temp_screen(prevwin)) { /* use previous window if possible */ CTX_wm_window_set(C, prevwin); @@ -949,7 +588,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) /* none otherwise */ CTX_wm_window_set(C, NULL); } - + } /* *********************************** */ @@ -960,11 +599,11 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) const bScreen *screen = WM_window_get_active_screen(win); AZone *az = NULL; ScrArea *sa; - + for (sa = screen->areabase.first; sa; sa = sa->next) - if ((az = is_in_area_actionzone(sa, xy))) + if ((az = ED_area_actionzone_find_xy(sa, xy))) break; - + if (sa) { if (az->type == AZONE_AREA) WM_cursor_set(win, CURSOR_EDIT); @@ -976,10 +615,10 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) } } else { - ScrEdge *actedge = screen_find_active_scredge(win, screen, xy[0], xy[1]); + ScrEdge *actedge = screen_geom_find_active_scredge(win, screen, xy[0], xy[1]); if (actedge) { - if (scredge_is_horizontal(actedge)) + if (screen_geom_edge_is_horizontal(actedge)) WM_cursor_set(win, CURSOR_Y_MOVE); else WM_cursor_set(win, CURSOR_X_MOVE); @@ -992,9 +631,8 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) /* called in wm_event_system.c. sets state vars in screen, cursors */ /* event type is mouse move */ -void ED_screen_set_active_region(bContext *C, const int xy[2]) +void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) { - wmWindow *win = CTX_wm_window(C); bScreen *scr = WM_window_get_active_screen(win); if (scr) { @@ -1005,7 +643,7 @@ void ED_screen_set_active_region(bContext *C, const int xy[2]) ED_screen_areas_iter(win, scr, area_iter) { if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { - if (is_in_area_actionzone(area_iter, xy) == NULL) { + if (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) { sa = area_iter; break; } @@ -1023,29 +661,29 @@ void ED_screen_set_active_region(bContext *C, const int xy[2]) } else scr->active_region = NULL; - + /* check for redraw headers */ if (old_ar != scr->active_region) { ED_screen_areas_iter(win, scr, area_iter) { bool do_draw = false; - + for (ar = area_iter->regionbase.first; ar; ar = ar->next) { if (ar == old_ar || ar == scr->active_region) { do_draw = true; } } - + if (do_draw) { for (ar = area_iter->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_HEADER) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw_no_rebuild(ar); } } } } } - + /* cursors, for time being set always on edges, otherwise aregion doesnt switch */ if (scr->active_region == NULL) { screen_cursor_set(win, xy); @@ -1058,7 +696,9 @@ void ED_screen_set_active_region(bContext *C, const int xy[2]) /* this used to be a notifier, but needs to be done immediate * because it can undo setting the right button as active due * to delayed notifier handling */ - UI_screen_free_active_but(C, scr); + if (C) { + UI_screen_free_active_but(C, scr); + } } else region_cursor_set(win, false); @@ -1073,12 +713,12 @@ int ED_screen_area_active(const bContext *C) ScrArea *sa = CTX_wm_area(C); if (win && sc && sa) { - AZone *az = is_in_area_actionzone(sa, &win->eventstate->x); + AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x); ARegion *ar; - + if (az && az->type == AZONE_REGION) return 1; - + for (ar = sa->regionbase.first; ar; ar = ar->next) if (ar == sc->active_region) return 1; @@ -1094,52 +734,69 @@ static ScrArea *screen_area_create_with_geometry( ScrAreaMap *area_map, const rcti *rect, short spacetype) { - ScrVert *bottom_left = screen_addvert_ex(area_map, rect->xmin, rect->ymin); - ScrVert *top_left = screen_addvert_ex(area_map, rect->xmin, rect->ymax); - ScrVert *top_right = screen_addvert_ex(area_map, rect->xmax, rect->ymax); - ScrVert *bottom_right = screen_addvert_ex(area_map, rect->xmax, rect->ymin); + ScrVert *bottom_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymin); + ScrVert *top_left = screen_geom_vertex_add_ex(area_map, rect->xmin, rect->ymax); + ScrVert *top_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymax); + ScrVert *bottom_right = screen_geom_vertex_add_ex(area_map, rect->xmax, rect->ymin); - screen_addedge_ex(area_map, bottom_left, top_left); - screen_addedge_ex(area_map, top_left, top_right); - screen_addedge_ex(area_map, top_right, bottom_right); - screen_addedge_ex(area_map, bottom_right, bottom_left); + screen_geom_edge_add_ex(area_map, bottom_left, top_left); + screen_geom_edge_add_ex(area_map, top_left, top_right); + screen_geom_edge_add_ex(area_map, top_right, bottom_right); + screen_geom_edge_add_ex(area_map, bottom_right, bottom_left); return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype); } -void ED_screen_global_topbar_area_create(wmWindow *win, const bScreen *screen) +static void screen_global_area_create( + wmWindow *win, eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect, + const short height_cur, const short height_min, const short height_max) { - if (screen->temp == 0) { - const short size_y = 2.25 * HEADERY; - SpaceType *st; - SpaceLink *sl; - ScrArea *sa; - rcti rect; - - BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); - rect.ymin = rect.ymax - size_y; - - sa = screen_area_create_with_geometry(&win->global_areas, &rect, SPACE_TOPBAR); - st = BKE_spacetype_from_id(SPACE_TOPBAR); - sl = st->new(sa, WM_window_get_active_scene(win)); - sa->regionbase = sl->regionbase; - - /* Data specific to global areas. */ - sa->global = MEM_callocN(sizeof(*sa->global), __func__); - sa->global->cur_fixed_height = size_y; - sa->global->size_max = size_y; - sa->global->size_min = HEADERY; - - BLI_addhead(&sa->spacedata, sl); - BLI_listbase_clear(&sl->regionbase); - } - /* Do not create more area types here! Function is called on file load (wm_window_ghostwindows_ensure). TODO */ + ScrArea *area = screen_area_create_with_geometry(&win->global_areas, rect, space_type); + SpaceType *stype = BKE_spacetype_from_id(space_type); + SpaceLink *slink = stype->new(area, WM_window_get_active_scene(win)); + + area->regionbase = slink->regionbase; + + /* Data specific to global areas. */ + area->global = MEM_callocN(sizeof(*area->global), __func__); + area->global->cur_fixed_height = height_cur; + area->global->size_max = height_max; + area->global->size_min = height_min; + area->global->align = align; + + BLI_addhead(&area->spacedata, slink); + BLI_listbase_clear(&slink->regionbase); +} + +static void screen_global_topbar_area_create(wmWindow *win) +{ + const short size_y = 2.25 * HEADERY; + rcti rect; + + BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); + rect.ymin = rect.ymax - size_y; + + screen_global_area_create(win, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size_y, HEADERY, size_y); +} + +static void screen_global_statusbar_area_create(wmWindow *win) +{ + const short size_y = 0.8f * HEADERY; + rcti rect; + + BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); + rect.ymax = rect.ymin + size_y; + + screen_global_area_create(win, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size_y, 0, size_y); } void ED_screen_global_areas_create(wmWindow *win) { - const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - ED_screen_global_topbar_area_create(win, screen); + bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + if (screen->temp == 0) { + screen_global_topbar_area_create(win); + screen_global_statusbar_area_create(win); + } } @@ -1260,13 +917,13 @@ static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrAre if (!v3d->camera) { ARegion *ar; ListBase *regionbase; - + /* regionbase is in different place depending if space is active */ if (v3d == sa->spacedata.first) regionbase = &sa->regionbase; else regionbase = &v3d->regionbase; - + for (ar = regionbase->first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = ar->regiondata; @@ -1299,7 +956,7 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) if (!sa || sa->full == NULL) { newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED); } - + if (!newsa) { newsa = sa; } @@ -1356,10 +1013,10 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) SpaceLink *sl = sa->spacedata.first; bScreen *screen = CTX_wm_screen(C); short state = (screen ? screen->state : SCREENMAXIMIZED); - + /* if fullscreen area has a temporary space (such as a file browser or fullscreen render * overlaid on top of an existing setup) then return to the previous space */ - + if (sl->next) { if (sa->flag & AREA_FLAG_TEMP_TYPE) { ED_screen_full_prevspace(C, sa); @@ -1382,6 +1039,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) */ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state) { + Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); WorkSpace *workspace = WM_window_get_active_workspace(win); bScreen *sc, *oldscreen; @@ -1400,8 +1058,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s } } - /* prevent hanging header prints */ - ED_area_headerprint(sa, NULL); + /* prevent hanging status prints */ + ED_area_status_text(sa, NULL); + ED_workspace_status_text(C, NULL); } if (sa && sa->full) { @@ -1472,7 +1131,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s oldscreen->state = state; BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal"); - layout_new = ED_workspace_layout_add(workspace, win, newname); + layout_new = ED_workspace_layout_add(bmain, workspace, win, newname); sc = BKE_workspace_layout_screen_get(layout_new); sc->state = state; @@ -1485,7 +1144,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s /* use random area when we have no active one, e.g. when the * mouse is outside of the window and we open a file browser */ - if (!sa) { + if (!sa || sa->global) { sa = oldscreen->areabase.first; } @@ -1527,15 +1186,15 @@ void ED_refresh_viewport_fps(bContext *C) { wmTimer *animtimer = CTX_wm_screen(C)->animtimer; Scene *scene = CTX_data_scene(C); - + /* is anim playback running? */ if (animtimer && (U.uiflag & USER_SHOW_FPS)) { ScreenFrameRateInfo *fpsi = scene->fps_info; - + /* if there isn't any info, init it first */ if (fpsi == NULL) fpsi = scene->fps_info = MEM_callocN(sizeof(ScreenFrameRateInfo), "refresh_viewport_fps fps_info"); - + /* update the values */ fpsi->redrawtime = fpsi->lredrawtime; fpsi->lredrawtime = animtimer->ltime; @@ -1548,7 +1207,7 @@ void ED_refresh_viewport_fps(bContext *C) } } -/* redraws: uses defines from stime->redraws +/* redraws: uses defines from stime->redraws * enable: 1 - forward on, -1 - backwards on, 0 - off */ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable) @@ -1558,17 +1217,17 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); bScreen *stopscreen = ED_screen_animation_playing(wm); - + if (stopscreen) { WM_event_remove_timer(wm, win, stopscreen->animtimer); stopscreen->animtimer = NULL; } - + if (enable) { ScreenAnimData *sad = MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData"); - + screen->animtimer = WM_event_add_timer(wm, win, TIMER0, (1.0 / FPS)); - + sad->ar = CTX_wm_region(C); /* if startframe is larger than current frame, we put currentframe on startframe. * note: first frame then is not drawn! (ton) */ @@ -1603,7 +1262,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, sad->from_anim_edit = (ELEM(spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA)); screen->animtimer->customdata = sad; - + } /* notifier catched by top header, for button */ @@ -1616,7 +1275,7 @@ static ARegion *time_top_left_3dwindow(bScreen *screen) ARegion *aret = NULL; ScrArea *sa; int min = 10000; - + for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar; @@ -1639,7 +1298,7 @@ void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh) if (screen && screen->animtimer) { wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; - + sad->redraws = redraws; sad->refresh = refresh; sad->ar = NULL; @@ -1662,9 +1321,10 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) for (sc = bmain->screen.first; sc; sc = sc->id.next) { BKE_screen_view3d_scene_sync(sc, scene); } + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); } #endif - + ED_clip_update_frame(bmain, scene->r.cfra); /* this function applies the changes too */ @@ -1673,7 +1333,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) /* composite */ if (scene->use_nodes && scene->nodetree) ntreeCompositTagAnimated(scene->nodetree); - + /* update animated texture nodes */ { Tex *tex; @@ -1683,7 +1343,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) } } } - + } /* diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c new file mode 100644 index 00000000000..5d87479e371 --- /dev/null +++ b/source/blender/editors/screen/screen_geometry.c @@ -0,0 +1,462 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/screen_geometry.c + * \ingroup edscr + * \brief Functions for screen vertices and edges + * + * Screen geometry refers to the vertices (ScrVert) and edges (ScrEdge) through + * which the flexible screen-layout system of Blender is established. + */ + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_rect.h" + +#include "BKE_screen.h" + +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "ED_screen.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" + +#include "screen_intern.h" + + +int screen_geom_area_height(const ScrArea *area) +{ + return area->v2->vec.y - area->v1->vec.y + 1; +} +int screen_geom_area_width(const ScrArea *area) +{ + return area->v4->vec.x - area->v1->vec.x + 1; +} + +ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y) +{ + ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert"); + sv->vec.x = x; + sv->vec.y = y; + + BLI_addtail(&area_map->vertbase, sv); + return sv; +} +ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y) +{ + return screen_geom_vertex_add_ex(AREAMAP_FROM_SCREEN(sc), x, y); +} + +ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2) +{ + ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge"); + + BKE_screen_sort_scrvert(&v1, &v2); + se->v1 = v1; + se->v2 = v2; + + BLI_addtail(&area_map->edgebase, se); + return se; +} +ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2) +{ + return screen_geom_edge_add_ex(AREAMAP_FROM_SCREEN(sc), v1, v2); +} + +bool screen_geom_edge_is_horizontal(ScrEdge *se) +{ + return (se->v1->vec.y == se->v2->vec.y); +} + +/** + * \param bounds_rect: Either window or screen bounds. Used to exclude edges along window/screen edges. + */ +ScrEdge *screen_geom_area_map_find_active_scredge( + const ScrAreaMap *area_map, + const rcti *bounds_rect, + const int mx, const int my) +{ + int safety = U.widget_unit / 10; + + CLAMP_MIN(safety, 2); + + for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) { + if (screen_geom_edge_is_horizontal(se)) { + if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) { + short min, max; + min = MIN2(se->v1->vec.x, se->v2->vec.x); + max = MAX2(se->v1->vec.x, se->v2->vec.x); + + if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max) + return se; + } + } + else { + if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) { + short min, max; + min = MIN2(se->v1->vec.y, se->v2->vec.y); + max = MAX2(se->v1->vec.y, se->v2->vec.y); + + if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max) + return se; + } + } + } + + return NULL; +} + +/* need win size to make sure not to include edges along screen edge */ +ScrEdge *screen_geom_find_active_scredge( + const wmWindow *win, const bScreen *screen, + const int mx, const int my) +{ + /* Use layout size (screen excluding global areas) for screen-layout area edges */ + rcti screen_rect; + ScrEdge *se; + + WM_window_screen_rect_calc(win, &screen_rect); + se = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(screen), &screen_rect, mx, my); + + if (!se) { + /* Use entire window size (screen including global areas) for global area edges */ + rcti win_rect; + WM_window_rect_calc(win, &win_rect); + se = screen_geom_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my); + } + return se; +} + +/** + * \brief Main screen-layout calculation function. + * + * * Scale areas nicely on window size and DPI changes. + * * Ensure areas have a minimum height. + * * Correctly set global areas to their fixed height. + */ +void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc) +{ + /* clamp Y size of header sized areas when expanding windows + * avoids annoying empty space around file menu */ +#define USE_HEADER_SIZE_CLAMP + + rcti window_rect, screen_rect; + + WM_window_rect_calc(win, &window_rect); + WM_window_screen_rect_calc(win, &screen_rect); + + const int headery_init = ED_area_headersize(); + const int screen_size_x = BLI_rcti_size_x(&screen_rect); + const int screen_size_y = BLI_rcti_size_y(&screen_rect); + ScrVert *sv = NULL; + ScrArea *sa; + int screen_size_x_prev, screen_size_y_prev; + float min[2], max[2]; + + /* calculate size */ + min[0] = min[1] = 20000.0f; + max[0] = max[1] = 0.0f; + + for (sv = sc->vertbase.first; sv; sv = sv->next) { + const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y}; + minmax_v2v2_v2(min, max, fv); + } + + screen_size_x_prev = (max[0] - min[0]) + 1; + screen_size_y_prev = (max[1] - min[1]) + 1; + + +#ifdef USE_HEADER_SIZE_CLAMP +#define TEMP_BOTTOM 1 +#define TEMP_TOP 2 + + /* if the window's Y axis grows, clamp header sized areas */ + if (screen_size_y_prev < screen_size_y) { /* growing? */ + const int headery_margin_max = headery_init + 5; + for (sa = sc->areabase.first; sa; sa = sa->next) { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + sa->temp = 0; + + if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) { + if (sa->v2->vec.y == max[1]) { + if (screen_geom_area_height(sa) < headery_margin_max) { + sa->temp = TEMP_TOP; + } + } + else if (sa->v1->vec.y == min[1]) { + if (screen_geom_area_height(sa) < headery_margin_max) { + sa->temp = TEMP_BOTTOM; + } + } + } + } + } +#endif + + + if (screen_size_x_prev != screen_size_x || screen_size_y_prev != screen_size_y) { + const float facx = ((float)screen_size_x - 1) / ((float)screen_size_x_prev - 1); + const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1); + + /* make sure it fits! */ + for (sv = sc->vertbase.first; sv; sv = sv->next) { + sv->vec.x = screen_rect.xmin + round_fl_to_short((sv->vec.x - min[0]) * facx); + CLAMP(sv->vec.x, screen_rect.xmin, screen_rect.xmax - 1); + + sv->vec.y = screen_rect.ymin + round_fl_to_short((sv->vec.y - min[1]) * facy); + CLAMP(sv->vec.y, screen_rect.ymin, screen_rect.ymax - 1); + } + } + + +#ifdef USE_HEADER_SIZE_CLAMP + if (screen_size_y_prev < screen_size_y) { /* growing? */ + for (sa = sc->areabase.first; sa; sa = sa->next) { + ScrEdge *se = NULL; + + if (sa->temp == 0) + continue; + + if (sa->v1 == sa->v2) + continue; + + /* adjust headery if verts are along the edge of window */ + if (sa->temp == TEMP_TOP) { + /* lower edge */ + const int yval = sa->v2->vec.y - headery_init; + se = BKE_screen_find_edge(sc, sa->v4, sa->v1); + if (se != NULL) { + screen_geom_select_connected_edge(win, se); + } + for (sv = sc->vertbase.first; sv; sv = sv->next) { + if (sv != sa->v2 && sv != sa->v3) { + if (sv->flag) { + sv->vec.y = yval; + } + } + } + } + else { + /* upper edge */ + const int yval = sa->v1->vec.y + headery_init; + se = BKE_screen_find_edge(sc, sa->v2, sa->v3); + if (se != NULL) { + screen_geom_select_connected_edge(win, se); + } + for (sv = sc->vertbase.first; sv; sv = sv->next) { + if (sv != sa->v1 && sv != sa->v4) { + if (sv->flag) { + sv->vec.y = yval; + } + } + } + } + } + } + +#undef USE_HEADER_SIZE_CLAMP +#undef TEMP_BOTTOM +#undef TEMP_TOP +#endif + + + /* test for collapsed areas. This could happen in some blender version... */ + /* ton: removed option now, it needs Context... */ + + /* make each window at least ED_area_headersize() high */ + for (sa = sc->areabase.first; sa; sa = sa->next) { + int headery = headery_init; + + /* adjust headery if verts are along the edge of window */ + if (sa->v1->vec.y > window_rect.ymin) + headery += U.pixelsize; + if (sa->v2->vec.y < (window_rect.ymax - 1)) + headery += U.pixelsize; + + if (screen_geom_area_height(sa) < headery) { + /* lower edge */ + ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1); + if (se && sa->v1 != sa->v2) { + const int yval = sa->v2->vec.y - headery + 1; + + screen_geom_select_connected_edge(win, se); + + /* all selected vertices get the right offset */ + for (sv = sc->vertbase.first; sv; sv = sv->next) { + /* if is a collapsed area */ + if (sv != sa->v2 && sv != sa->v3) { + if (sv->flag) { + sv->vec.y = yval; + } + } + } + } + } + } + + /* Global areas have a fixed size that only changes with the DPI. Here we ensure that exactly this size is set. */ + for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { + if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) { + continue; + } + + int height = ED_area_global_size_y(area) - 1; + + if (area->v1->vec.y > window_rect.ymin) { + height += U.pixelsize; + } + if (area->v2->vec.y < (window_rect.ymax - 1)) { + height += U.pixelsize; + } + + /* width */ + area->v1->vec.x = area->v2->vec.x = window_rect.xmin; + area->v3->vec.x = area->v4->vec.x = window_rect.xmax - 1; + /* height */ + area->v1->vec.y = area->v4->vec.y = window_rect.ymin; + area->v2->vec.y = area->v3->vec.y = window_rect.ymax - 1; + + switch (area->global->align) { + case GLOBAL_AREA_ALIGN_TOP: + area->v1->vec.y = area->v4->vec.y = area->v2->vec.y - height; + break; + case GLOBAL_AREA_ALIGN_BOTTOM: + area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + height; + break; + } + } +} + +/** + * \return 0 if no split is possible, otherwise the screen-coordinate at which to split. + */ +short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_rect, char dir, float fac) +{ + short x, y; + const int cur_area_width = screen_geom_area_width(sa); + const int cur_area_height = screen_geom_area_height(sa); + const short area_min_x = AREAMINX; + const short area_min_y = ED_area_headersize(); + int area_min; + + // area big enough? + if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) { + return 0; + } + if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) { + return 0; + } + + // to be sure + CLAMP(fac, 0.0f, 1.0f); + + if (dir == 'h') { + y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height); + + area_min = area_min_y; + + if (sa->v1->vec.y > window_rect->ymin) { + area_min += U.pixelsize; + } + if (sa->v2->vec.y < (window_rect->ymax - 1)) { + area_min += U.pixelsize; + } + + if (y - sa->v1->vec.y < area_min) { + y = sa->v1->vec.y + area_min; + } + else if (sa->v2->vec.y - y < area_min) { + y = sa->v2->vec.y - area_min; + } + + return y; + } + else { + x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width); + + area_min = area_min_x; + + if (sa->v1->vec.x > window_rect->xmin) { + area_min += U.pixelsize; + } + if (sa->v4->vec.x < (window_rect->xmax - 1)) { + area_min += U.pixelsize; + } + + if (x - sa->v1->vec.x < area_min) { + x = sa->v1->vec.x + area_min; + } + else if (sa->v4->vec.x - x < area_min) { + x = sa->v4->vec.x - area_min; + } + + return x; + } +} + +/** + * Select all edges that are directly or indirectly connected to \a edge. + */ +void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge) +{ + bScreen *sc = WM_window_get_active_screen(win); + bool oneselected = true; + char dir; + + /* select connected, only in the right direction */ + /* 'dir' is the direction of EDGE */ + + if (edge->v1->vec.x == edge->v2->vec.x) { + dir = 'v'; + } + else { + dir = 'h'; + } + + ED_screen_verts_iter(win, sc, sv) { + sv->flag = 0; + } + + edge->v1->flag = 1; + edge->v2->flag = 1; + + while (oneselected) { + oneselected = false; + for (ScrEdge *se = sc->edgebase.first; se; se = se->next) { + if (se->v1->flag + se->v2->flag == 1) { + if (dir == 'h') { + if (se->v1->vec.y == se->v2->vec.y) { + se->v1->flag = se->v2->flag = 1; + oneselected = true; + } + } + if (dir == 'v') { + if (se->v1->vec.x == se->v2->vec.x) { + se->v1->flag = se->v2->flag = 1; + oneselected = true; + } + } + } + } + } +} diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 045e5ee6b48..cd71c07a3c0 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,7 +18,7 @@ * The Original Code is Copyright (C) 2008 Blender Foundation. * All rights reserved. * - * + * * Contributor(s): Blender Foundation * * ***** END GPL LICENSE BLOCK ***** @@ -48,26 +48,37 @@ void screen_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade); /* screen_edit.c */ -bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y); +bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect); void screen_data_copy(bScreen *to, bScreen *from); void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new); void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc); bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win); -ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge); +ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge); int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2); int area_getorientation(ScrArea *sa, ScrArea *sb); -void select_connected_scredge(const wmWindow *win, ScrEdge *edge); -bool scredge_is_horizontal(ScrEdge *se); -ScrEdge *screen_area_map_find_active_scredge( +struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]); +struct AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]); + +/* screen_geometry.c */ +int screen_geom_area_height(const ScrArea *area); +int screen_geom_area_width(const ScrArea *area); +ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y); +ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y); +ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2); +ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2); +bool screen_geom_edge_is_horizontal(ScrEdge *se); +ScrEdge *screen_geom_area_map_find_active_scredge( const struct ScrAreaMap *area_map, - const int winsize_x, const int winsize_y, + const rcti *bounds_rect, const int mx, const int my); -ScrEdge *screen_find_active_scredge( +ScrEdge *screen_geom_find_active_scredge( const wmWindow *win, const bScreen *screen, const int mx, const int my); +void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc); +short screen_geom_find_area_split_point(const ScrArea *sa, const rcti *window_rect, char dir, float fac); +void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge); -struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]); /* screen_context.c */ int ed_screen_context( @@ -77,7 +88,6 @@ extern const char *screen_context_dir[]; /* doc access */ /* screendump.c */ void SCREEN_OT_screenshot(struct wmOperatorType *ot); -void SCREEN_OT_screencast(struct wmOperatorType *ot); /* screen_ops.c */ void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6f422a39584..2776bd98a43 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4,7 +4,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -39,6 +39,7 @@ #include "BLT_translation.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_lattice_types.h" #include "DNA_object_types.h" @@ -53,6 +54,7 @@ #include "BKE_context.h" #include "BKE_customdata.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_main.h" @@ -70,6 +72,7 @@ #include "DEG_depsgraph.h" +#include "ED_anim_api.h" #include "ED_armature.h" #include "ED_clip.h" #include "ED_image.h" @@ -143,6 +146,14 @@ int ED_operator_screen_mainwinactive(bContext *C) return 1; } +int ED_operator_scene(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + if (scene) + return 1; + return 0; +} + int ED_operator_scene_editable(bContext *C) { Scene *scene = CTX_data_scene(C); @@ -160,11 +171,11 @@ int ED_operator_objectmode(bContext *C) return 0; if (CTX_data_edit_object(C)) return 0; - + /* add a check for ob->mode too? */ if (obact && (obact->mode != OB_MODE_OBJECT)) return 0; - + return 1; } @@ -241,20 +252,20 @@ int ED_operator_buttons_active(bContext *C) int ED_operator_node_active(bContext *C) { SpaceNode *snode = CTX_wm_space_node(C); - + if (snode && snode->edittree) return 1; - + return 0; } int ED_operator_node_editable(bContext *C) { SpaceNode *snode = CTX_wm_space_node(C); - + if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree)) return 1; - + return 0; } @@ -440,15 +451,15 @@ int ED_operator_uvmap(bContext *C) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = NULL; - + if (obedit && obedit->type == OB_MESH) { em = BKE_editmesh_from_object(obedit); } - + if (em && (em->bm->totface)) { return true; } - + return false; } @@ -595,23 +606,23 @@ static ARegion *screen_find_region_type(bContext *C, int type) /** \name Action Zone Operator * \{ */ -/* operator state vars used: +/* operator state vars used: * none - * + * * functions: - * + * * apply() set actionzone event - * + * * exit() free customdata - * + * * callbacks: - * + * * exec() never used - * - * invoke() check if in zone + * + * invoke() check if in zone * add customdata, put mouseco and area in it * add modal handler - * + * * modal() accept modal events while doing it * call apply() with gesture info, active window, nonactive window * call exit() and remove handler when LMB confirm @@ -628,11 +639,11 @@ static int actionzone_area_poll(bContext *C) { wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); - + if (sa && win && win->eventstate) { const int *xy = &win->eventstate->x; AZone *az; - + for (az = sa->actionzones.first; az; az = az->next) if (BLI_rcti_isect_pt_v(&az->rect, xy)) return 1; @@ -658,117 +669,141 @@ static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size); } -AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]) +static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only) { AZone *az = NULL; - + for (az = sa->actionzones.first; az; az = az->next) { if (BLI_rcti_isect_pt_v(&az->rect, xy)) { if (az->type == AZONE_AREA) { /* no triangle intersect but a hotspot circle based on corner */ - int radius = (xy[0] - az->x1) * (xy[0] - az->x1) + (xy[1] - az->y1) * (xy[1] - az->y1); - - if (radius <= AZONESPOT * AZONESPOT) + int radius_sq = SQUARE(xy[0] - az->x1) + SQUARE(xy[1] - az->y1); + if (radius_sq <= SQUARE(AZONESPOT)) { break; + } } else if (az->type == AZONE_REGION) { break; } else if (az->type == AZONE_FULLSCREEN) { - int mouse_radius, spot_radius, fadein_radius, fadeout_radius; rcti click_rect; - fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2); + const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy); - if (BLI_rcti_isect_pt_v(&click_rect, xy)) { - az->alpha = 1.0f; + if (test_only) { + if (click_isect) { + break; + } } else { - mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2); - spot_radius = AZONESPOT * AZONESPOT; - fadein_radius = AZONEFADEIN * AZONEFADEIN; - fadeout_radius = AZONEFADEOUT * AZONEFADEOUT; - - if (mouse_radius < spot_radius) { + if (click_isect) { az->alpha = 1.0f; } - else if (mouse_radius < fadein_radius) { - az->alpha = 1.0f; - } - else if (mouse_radius < fadeout_radius) { - az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius)); - } else { - az->alpha = 0.0f; + const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2); + const int spot_sq = SQUARE(AZONESPOT); + const int fadein_sq = SQUARE(AZONEFADEIN); + const int fadeout_sq = SQUARE(AZONEFADEOUT); + + if (mouse_sq < spot_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadein_sq) { + az->alpha = 1.0f; + } + else if (mouse_sq < fadeout_sq) { + az->alpha = 1.0f - ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq)); + } + else { + az->alpha = 0.0f; + } + + /* fade in/out but no click */ + az = NULL; } - /* fade in/out but no click */ - az = NULL; + /* XXX force redraw to show/hide the action zone */ + ED_area_tag_redraw(sa); + break; } - - /* XXX force redraw to show/hide the action zone */ - ED_area_tag_redraw(sa); - break; } else if (az->type == AZONE_REGION_SCROLL) { ARegion *ar = az->ar; View2D *v2d = &ar->v2d; const short isect_value = UI_view2d_mouse_in_scrollers(ar, v2d, xy[0], xy[1]); - bool redraw = false; - - if (isect_value == 'h') { - if (az->direction == AZ_SCROLL_HOR) { - az->alpha = 1.0f; - v2d->alpha_hor = 255; - v2d->size_hor = V2D_SCROLL_HEIGHT; - redraw = true; - } - } - else if (isect_value == 'v') { - if (az->direction == AZ_SCROLL_VERT) { - az->alpha = 1.0f; - v2d->alpha_vert = 255; - v2d->size_vert = V2D_SCROLL_WIDTH; - redraw = true; + if (test_only) { + if (isect_value != 0) { + break; } } else { - const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; - float dist_fac = 0.0f, alpha = 0.0f; - - if (az->direction == AZ_SCROLL_HOR) { - dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; + bool redraw = false; - v2d->alpha_hor = alpha * 255; - v2d->size_hor = round_fl_to_int(V2D_SCROLL_HEIGHT - - ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + if (isect_value == 'h') { + if (az->direction == AZ_SCROLL_HOR) { + az->alpha = 1.0f; + v2d->alpha_hor = 255; + v2d->size_hor = V2D_SCROLL_HEIGHT; + redraw = true; + } } - else if (az->direction == AZ_SCROLL_VERT) { - dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; - CLAMP(dist_fac, 0.0f, 1.0f); - alpha = 1.0f - dist_fac; - - v2d->alpha_vert = alpha * 255; - v2d->size_vert = round_fl_to_int(V2D_SCROLL_WIDTH - - ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + else if (isect_value == 'v') { + if (az->direction == AZ_SCROLL_VERT) { + az->alpha = 1.0f; + v2d->alpha_vert = 255; + v2d->size_vert = V2D_SCROLL_WIDTH; + redraw = true; + } + } + else { + const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin}; + float dist_fac = 0.0f, alpha = 0.0f; + + if (az->direction == AZ_SCROLL_HOR) { + dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_hor = alpha * 255; + v2d->size_hor = round_fl_to_int( + V2D_SCROLL_HEIGHT - + ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac)); + } + else if (az->direction == AZ_SCROLL_VERT) { + dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN; + CLAMP(dist_fac, 0.0f, 1.0f); + alpha = 1.0f - dist_fac; + + v2d->alpha_vert = alpha * 255; + v2d->size_vert = round_fl_to_int( + V2D_SCROLL_WIDTH - + ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac)); + } + az->alpha = alpha; + redraw = true; } - az->alpha = alpha; - redraw = true; - } - if (redraw) { - ED_area_tag_redraw(sa); + if (redraw) { + ED_area_tag_redraw_no_rebuild(sa); + } + /* Don't return! */ } - /* Don't return! */ } } } - + return az; } +AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, true); +} + +AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]) +{ + return area_actionzone_refresh_xy(sa, xy, false); +} static void actionzone_exit(wmOperator *op) { @@ -783,9 +818,9 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) wmEvent event; wmWindow *win = CTX_wm_window(C); sActionzoneData *sad = op->customdata; - + sad->modifier = RNA_int_get(op->ptr, "modifier"); - + wm_event_init_from_window(win, &event); if (type == AZONE_AREA) @@ -799,39 +834,36 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) event.customdata = op->customdata; event.customdatafree = true; op->customdata = NULL; - + wm_event_add(win, &event); } static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); - AZone *az = is_in_area_actionzone(sa, &event->x); + AZone *az = ED_area_actionzone_find_xy(sa, &event->x); sActionzoneData *sad; - - /* quick escape */ - if (az == NULL) + + /* quick escape - Scroll azones only hide/unhide the scroll-bars, they have their own handling. */ + if (az == NULL || ELEM(az->type, AZONE_REGION_SCROLL)) return OPERATOR_PASS_THROUGH; - + /* ok we do the actionzone */ sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData"); sad->sa1 = sa; sad->az = az; sad->x = event->x; sad->y = event->y; - + /* region azone directly reacts on mouse clicks */ if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) { actionzone_apply(C, op, sad->az->type); actionzone_exit(op); return OPERATOR_FINISHED; } - else if (ELEM(sad->az->type, AZONE_REGION_SCROLL)) { - return OPERATOR_PASS_THROUGH; - } else { /* add modal handler */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } } @@ -839,11 +871,8 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sActionzoneData *sad = op->customdata; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); switch (event->type) { case MOUSEMOVE: @@ -862,13 +891,17 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) sad->gesture_dir = 's'; else sad->gesture_dir = 'w'; - + if (sad->az->type == AZONE_AREA) { + const wmWindow *win = CTX_wm_window(C); + rcti screen_rect; + + WM_window_screen_rect_calc(win, &screen_rect); /* once we drag outside the actionzone, register a gesture * check we're not on an edge so join finds the other area */ - is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && - (screen_area_map_find_active_scredge( - AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y) == NULL)); + is_gesture = ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) && + (screen_geom_area_map_find_active_scredge( + AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL)); } else { const int delta_min = 1; @@ -882,7 +915,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) /* apply sends event */ actionzone_apply(C, op, sad->az->type); actionzone_exit(op); - + return OPERATOR_FINISHED; } break; @@ -893,9 +926,9 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: actionzone_exit(op); return OPERATOR_CANCELLED; - + } - + return OPERATOR_RUNNING_MODAL; } @@ -910,15 +943,15 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot) ot->name = "Handle Area Action Zones"; ot->description = "Handle area action zones for mouse actions/gestures"; ot->idname = "SCREEN_OT_actionzone"; - + ot->invoke = actionzone_invoke; ot->modal = actionzone_modal; ot->poll = actionzone_area_poll; ot->cancel = actionzone_cancel; - + /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; - + RNA_def_int(ot->srna, "modifier", 0, 0, 2, "Modifier", "Modifier state", 0, 2); } @@ -956,15 +989,15 @@ static int area_swap_init(wmOperator *op, const wmEvent *event) { sAreaSwapData *sd = NULL; sActionzoneData *sad = event->customdata; - + if (sad == NULL || sad->sa1 == NULL) return 0; - + sd = MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData"); sd->sa1 = sad->sa1; sd->sa2 = sad->sa2; op->customdata = sd; - + return 1; } @@ -984,22 +1017,22 @@ static void area_swap_cancel(bContext *C, wmOperator *op) static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - + if (!area_swap_init(op, event)) return OPERATOR_PASS_THROUGH; - + /* add modal handler */ WM_cursor_modal_set(CTX_wm_window(C), BC_SWAPAREA_CURSOR); WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; - + } static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = op->customdata; - + switch (event->type) { case MOUSEMOVE: /* second area, for join */ @@ -1016,15 +1049,15 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_area_tag_redraw(sad->sa2); ED_area_swapspace(C, sad->sa1, sad->sa2); - + area_swap_exit(C, op); - + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } break; - + case ESCKEY: area_swap_cancel(C, op); return OPERATOR_CANCELLED; @@ -1037,12 +1070,12 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) ot->name = "Swap Areas"; ot->description = "Swap selected areas screen positions"; ot->idname = "SCREEN_OT_area_swap"; - + ot->invoke = area_swap_invoke; ot->modal = area_swap_modal; ot->poll = ED_operator_areaactive; ot->cancel = area_swap_cancel; - + ot->flag = OPTYPE_BLOCKING; } @@ -1057,6 +1090,7 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) /* operator callback */ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); wmWindow *newwin, *win = CTX_wm_window(C); Scene *scene; WorkSpace *workspace = WM_window_get_active_workspace(win); @@ -1065,18 +1099,18 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) bScreen *newsc; ScrArea *sa; rcti rect; - + win = CTX_wm_window(C); scene = CTX_data_scene(C); sa = CTX_wm_area(C); - + /* XXX hrmf! */ if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; - + if (sad == NULL) return OPERATOR_PASS_THROUGH; - + sa = sad->sa1; } @@ -1098,7 +1132,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) WM_window_set_active_workspace(newwin, workspace); /* allocs new screen and adds to newly created window, using window size */ - layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old)); + layout_new = ED_workspace_layout_add(bmain, workspace, newwin, BKE_workspace_layout_name_get(layout_old)); newsc = BKE_workspace_layout_screen_get(layout_new); WM_window_set_active_layout(newwin, workspace, layout_new); ED_screen_global_areas_create(newwin); @@ -1115,7 +1149,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) finally: if (event->type == EVT_ACTIONZONE_AREA) actionzone_exit(op); - + if (newwin) { return OPERATOR_FINISHED; } @@ -1129,7 +1163,7 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot) ot->name = "Duplicate Area into New Window"; ot->description = "Duplicate selected area into new window"; ot->idname = "SCREEN_OT_area_dupli"; - + ot->invoke = area_dupli_invoke; ot->poll = ED_operator_areaactive; } @@ -1140,29 +1174,29 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot) /** \name Move Area Edge Operator * \{ */ -/* operator state vars used: +/* operator state vars used: * x, y mouse coord near edge * delta movement of edge - * + * * functions: - * + * * init() set default property values, find edge based on mouse coords, test * if the edge can be moved, select edges, calculate min and max movement - * + * * apply() apply delta on selection - * + * * exit() cleanup, send notifier - * + * * cancel() cancel moving - * + * * callbacks: - * + * * exec() execute without any user interaction, based on properties * call init(), apply(), exit() - * + * * invoke() gets called on mouse click near edge * call init(), add handler - * + * * modal() accept modal events while doing it * call apply() with delta motion * call exit() and remove handler @@ -1174,6 +1208,8 @@ typedef struct sAreaMoveData { enum AreaMoveSnapType { /* Snapping disabled */ SNAP_NONE = 0, + /* Snap to an invisible grid with a unit defined in AREAGRID */ + SNAP_AREAGRID, /* Snap to mid-point and adjacent edges. */ SNAP_MIDPOINT_AND_ADJACENT, /* Snap to either bigger or smaller, nothing in-between (used for @@ -1184,13 +1220,13 @@ typedef struct sAreaMoveData { } sAreaMoveData; /* helper call to move area-edge, sets limits - * need window size in order to get correct limits */ + * need window bounds in order to get correct limits */ static void area_move_set_limits( wmWindow *win, bScreen *sc, int dir, - const int winsize_x, const int winsize_y, int *bigger, int *smaller, bool *use_bigger_smaller_snap) { + rcti window_rect; int areaminy = ED_area_headersize(); int areamin; @@ -1200,8 +1236,11 @@ static void area_move_set_limits( if (use_bigger_smaller_snap != NULL) { *use_bigger_smaller_snap = false; for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { - const int size_min = round_fl_to_int(area->global->size_min * UI_DPI_FAC); - const int size_max = round_fl_to_int(area->global->size_max * UI_DPI_FAC); + int size_min = ED_area_global_min_size_y(area) - 1; + int size_max = ED_area_global_max_size_y(area) - 1; + + size_min = MAX2(size_min, 0); + BLI_assert(size_min < size_max); /* logic here is only tested for lower edge :) */ /* left edge */ @@ -1235,18 +1274,20 @@ static void area_move_set_limits( } } + WM_window_rect_calc(win, &window_rect); + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { if (dir == 'h') { int y1; areamin = areaminy; - - if (sa->v1->vec.y > 0) + + if (sa->v1->vec.y > window_rect.ymin) areamin += U.pixelsize; - if (sa->v2->vec.y < winsize_y - 1) + if (sa->v2->vec.y < (window_rect.ymax - 1)) areamin += U.pixelsize; - - y1 = sa->v2->vec.y - sa->v1->vec.y + 1 - areamin; - + + y1 = screen_geom_area_height(sa) - areamin; + /* if top or down edge selected, test height */ if (sa->v1->editflag && sa->v4->editflag) *bigger = min_ii(*bigger, y1); @@ -1256,14 +1297,14 @@ static void area_move_set_limits( else { int x1; areamin = AREAMINX; - - if (sa->v1->vec.x > 0) + + if (sa->v1->vec.x > window_rect.xmin) areamin += U.pixelsize; - if (sa->v4->vec.x < winsize_x - 1) + if (sa->v4->vec.x < (window_rect.xmax - 1)) areamin += U.pixelsize; - - x1 = sa->v4->vec.x - sa->v1->vec.x + 1 - areamin; - + + x1 = screen_geom_area_width(sa) - areamin; + /* if left or right edge selected, test width */ if (sa->v1->editflag && sa->v2->editflag) *bigger = min_ii(*bigger, x1); @@ -1281,37 +1322,33 @@ static int area_move_init(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); ScrEdge *actedge; sAreaMoveData *md; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); int x, y; - + /* required properties */ x = RNA_int_get(op->ptr, "x"); y = RNA_int_get(op->ptr, "y"); - + /* setup */ - actedge = screen_find_active_scredge(win, sc, x, y); + actedge = screen_geom_find_active_scredge(win, sc, x, y); if (actedge == NULL) return 0; - + md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData"); op->customdata = md; - - md->dir = scredge_is_horizontal(actedge) ? 'h' : 'v'; + + md->dir = screen_geom_edge_is_horizontal(actedge) ? 'h' : 'v'; if (md->dir == 'h') md->origval = actedge->v1->vec.y; else md->origval = actedge->v1->vec.x; - - select_connected_scredge(win, actedge); + + screen_geom_select_connected_edge(win, actedge); /* now all vertices with 'flag == 1' are the ones that can be moved. Move this to editflag */ ED_screen_verts_iter(win, sc, v1) { v1->editflag = v1->flag; } bool use_bigger_smaller_snap = false; - area_move_set_limits(win, sc, md->dir, screen_size_x, screen_size_y, - &md->bigger, &md->smaller, - &use_bigger_smaller_snap); + area_move_set_limits(win, sc, md->dir, &md->bigger, &md->smaller, &use_bigger_smaller_snap); - md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_NONE; + md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID; return 1; } @@ -1322,30 +1359,44 @@ static int area_snap_calc_location( const int bigger, const int smaller) { BLI_assert(snap_type != SNAP_NONE); - if (snap_type == SNAP_BIGGER_SMALLER_ONLY) { - return ((origval + delta) >= bigger) ? bigger : smaller; - } - int final_loc = -1; const int m_loc = origval + delta; - const int axis = (dir == 'v') ? 0 : 1; - int snap_dist; - int dist; - { - /* Test the snap to middle. */ - int middle = origval + (bigger - smaller) / 2; - middle -= (middle % AREAGRID); - snap_dist = abs(m_loc - middle); - final_loc = middle; - } + switch (snap_type) { + case SNAP_AREAGRID: + final_loc = m_loc; + if (delta != bigger && delta != -smaller) { + final_loc -= (m_loc % AREAGRID); + CLAMP(final_loc, origval - smaller, origval + bigger); + } + break; - for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) { - if (v1->editflag) { - const int v_loc = (&v1->vec.x)[!axis]; + case SNAP_BIGGER_SMALLER_ONLY: + final_loc = (m_loc >= bigger) ? bigger : smaller; + break; - for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) { - if (!v2->editflag) { + case SNAP_MIDPOINT_AND_ADJACENT: + { + const int axis = (dir == 'v') ? 0 : 1; + int snap_dist; + int dist; + { + /* Test the snap to middle. */ + int middle = origval + (bigger - smaller) / 2; + snap_dist = abs(m_loc - middle); + final_loc = middle; + } + + for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) { + if (!v1->editflag) { + continue; + } + const int v_loc = (&v1->vec.x)[!axis]; + + for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) { + if (v2->editflag) { + continue; + } if (v_loc == (&v2->vec.x)[!axis]) { const int v_loc2 = (&v2->vec.x)[axis]; /* Do not snap to the vertices at the ends. */ @@ -1359,9 +1410,15 @@ static int area_snap_calc_location( } } } + break; } + case SNAP_NONE: + break; } + BLI_assert(ELEM(snap_type, SNAP_BIGGER_SMALLER_ONLY) || + IN_RANGE_INCL(final_loc, origval - smaller, origval + bigger)); + return final_loc; } @@ -1374,16 +1431,15 @@ static void area_move_apply_do( { wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); + short final_loc = -1; bool doredraw = false; - CLAMP(delta, -smaller, bigger); - short final_loc = -1; + if (snap_type != SNAP_BIGGER_SMALLER_ONLY) { + CLAMP(delta, -smaller, bigger); + } if (snap_type == SNAP_NONE) { final_loc = origval + delta; - if (delta != bigger && delta != -smaller) { - final_loc -= (final_loc % AREAGRID); - } } else { final_loc = area_snap_calc_location(sc, snap_type, delta, origval, dir, bigger, smaller); @@ -1411,7 +1467,7 @@ static void area_move_apply_do( ED_screen_areas_iter(win, sc, sa) { if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag) { if (ED_area_is_global(sa)) { - sa->global->cur_fixed_height = round_fl_to_int((sa->v2->vec.y - sa->v1->vec.y) / UI_DPI_FAC); + sa->global->cur_fixed_height = round_fl_to_int(screen_geom_area_height(sa) / UI_DPI_FAC); sc->do_refresh = true; redraw_all = true; } @@ -1443,7 +1499,7 @@ static void area_move_exit(bContext *C, wmOperator *op) if (op->customdata) MEM_freeN(op->customdata); op->customdata = NULL; - + /* this makes sure aligned edges will result in aligned grabbing */ BKE_screen_remove_double_scrverts(CTX_wm_screen(C)); BKE_screen_remove_double_scredges(CTX_wm_screen(C)); @@ -1453,10 +1509,10 @@ static int area_move_exec(bContext *C, wmOperator *op) { if (!area_move_init(C, op)) return OPERATOR_CANCELLED; - + area_move_apply(C, op); area_move_exit(C, op); - + return OPERATOR_FINISHED; } @@ -1465,19 +1521,19 @@ static int area_move_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_int_set(op->ptr, "x", event->x); RNA_int_set(op->ptr, "y", event->y); - - if (!area_move_init(C, op)) + + if (!area_move_init(C, op)) return OPERATOR_PASS_THROUGH; - + /* add temp handler */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } static void area_move_cancel(bContext *C, wmOperator *op) { - + RNA_int_set(op->ptr, "delta", 0); area_move_apply(C, op); area_move_exit(C, op); @@ -1488,17 +1544,17 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) { sAreaMoveData *md = op->customdata; int delta, x, y; - + /* execute the events */ switch (event->type) { case MOUSEMOVE: { x = RNA_int_get(op->ptr, "x"); y = RNA_int_get(op->ptr, "y"); - + delta = (md->dir == 'v') ? event->x - x : event->y - y; RNA_int_set(op->ptr, "delta", delta); - + area_move_apply(C, op); break; } @@ -1508,26 +1564,27 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) case KM_MODAL_APPLY: area_move_exit(C, op); return OPERATOR_FINISHED; - + case KM_MODAL_CANCEL: area_move_cancel(C, op); return OPERATOR_CANCELLED; case KM_MODAL_SNAP_ON: - if (md->snap_type == SNAP_NONE) { + if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) { md->snap_type = SNAP_MIDPOINT_AND_ADJACENT; } break; + case KM_MODAL_SNAP_OFF: - if (md->snap_type == SNAP_MIDPOINT_AND_ADJACENT) { - md->snap_type = SNAP_NONE; + if (md->snap_type != SNAP_BIGGER_SMALLER_ONLY) { + md->snap_type = SNAP_AREAGRID; } break; } break; } } - + return OPERATOR_RUNNING_MODAL; } @@ -1537,16 +1594,16 @@ static void SCREEN_OT_area_move(wmOperatorType *ot) ot->name = "Move Area Edges"; ot->description = "Move selected area edges"; ot->idname = "SCREEN_OT_area_move"; - + ot->exec = area_move_exec; ot->invoke = area_move_invoke; ot->cancel = area_move_cancel; ot->modal = area_move_modal; ot->poll = ED_operator_screen_mainwinactive; /* when mouse is over area-edge */ - + /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; - + /* rna */ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); @@ -1605,7 +1662,7 @@ typedef struct sAreaSplitData { ScrEdge *nedge; /* new edge */ ScrArea *sarea; /* start area */ ScrArea *narea; /* new area */ - + } sAreaSplitData; static void area_split_draw_cb(const struct wmWindow *UNUSED(win), void *userdata) @@ -1625,11 +1682,11 @@ static void area_split_draw_cb(const struct wmWindow *UNUSED(win), void *userdat static int area_split_menu_init(bContext *C, wmOperator *op) { sAreaSplitData *sd; - + /* custom data */ sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split"); op->customdata = sd; - + sd->sarea = CTX_wm_area(C); return 1; @@ -1640,27 +1697,33 @@ static int area_split_init(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); sAreaSplitData *sd; - int areaminy = ED_area_headersize() + 1; + int areaminy = ED_area_headersize(); int dir; - + /* required context */ if (sa == NULL) return 0; - + /* required properties */ dir = RNA_enum_get(op->ptr, "direction"); - + /* minimal size */ if (dir == 'v' && sa->winx < 2 * AREAMINX) return 0; if (dir == 'h' && sa->winy < 2 * areaminy) return 0; - + /* custom data */ sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split"); op->customdata = sd; - + sd->sarea = sa; - sd->origsize = dir == 'v' ? sa->winx : sa->winy; - sd->origmin = dir == 'v' ? sa->totrct.xmin : sa->totrct.ymin; - + if (dir == 'v') { + sd->origmin = sa->v1->vec.x; + sd->origsize = sa->v4->vec.x - sd->origmin; + } + else { + sd->origmin = sa->v1->vec.y; + sd->origsize = sa->v2->vec.y - sd->origmin; + } + return 1; } @@ -1676,7 +1739,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb) ScrVert *sbv2 = sb->v2; ScrVert *sbv3 = sb->v3; ScrVert *sbv4 = sb->v4; - + if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */ return BKE_screen_find_edge(screen, sav1, sav2); } @@ -1689,7 +1752,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb) else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/ return BKE_screen_find_edge(screen, sav1, sav4); } - + return NULL; } @@ -1697,28 +1760,28 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb) /* do the split, return success */ static int area_split_apply(bContext *C, wmOperator *op) { + const wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sAreaSplitData *sd = (sAreaSplitData *)op->customdata; float fac; int dir; - + fac = RNA_float_get(op->ptr, "factor"); dir = RNA_enum_get(op->ptr, "direction"); - - sd->narea = area_split(sc, sd->sarea, dir, fac, 0); /* 0 = no merge */ - + + sd->narea = area_split(win, sc, sd->sarea, dir, fac, 0); /* 0 = no merge */ + if (sd->narea) { - ScrVert *sv; - sd->nedge = area_findsharededge(sc, sd->sarea, sd->narea); - + /* select newly created edge, prepare for moving edge */ - for (sv = sc->vertbase.first; sv; sv = sv->next) + ED_screen_verts_iter(win, sc, sv) { sv->editflag = 0; - + } + sd->nedge->v1->editflag = 1; sd->nedge->v2->editflag = 1; - + if (dir == 'h') sd->origval = sd->nedge->v1->vec.y; else sd->origval = sd->nedge->v1->vec.x; @@ -1731,7 +1794,7 @@ static int area_split_apply(bContext *C, wmOperator *op) return 1; } - + return 0; } @@ -1748,10 +1811,10 @@ static void area_split_exit(bContext *C, wmOperator *op) MEM_freeN(op->customdata); op->customdata = NULL; } - + WM_cursor_modal_restore(CTX_wm_window(C)); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - + /* this makes sure aligned edges will result in aligned grabbing */ BKE_screen_remove_double_scrverts(CTX_wm_screen(C)); BKE_screen_remove_double_scredges(CTX_wm_screen(C)); @@ -1770,29 +1833,27 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sAreaSplitData *sd; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); int dir; - + /* no full window splitting allowed */ if (sc->state != SCREENNORMAL) return OPERATOR_CANCELLED; - + if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; - + if (sad == NULL || sad->modifier > 0) { return OPERATOR_PASS_THROUGH; } - + /* verify *sad itself */ if (sad->sa1 == NULL || sad->az == NULL) return OPERATOR_PASS_THROUGH; - + /* is this our *sad? if areas not equal it should be passed on */ if (CTX_wm_area(C) != sad->sa1 || sad->sa1 != sad->sa2) return OPERATOR_PASS_THROUGH; - + /* prepare operator state vars */ if (sad->gesture_dir == 'n' || sad->gesture_dir == 's') { dir = 'h'; @@ -1803,52 +1864,55 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy); } RNA_enum_set(op->ptr, "direction", dir); - + /* general init, also non-UI case, adds customdata, sets area and defaults */ if (!area_split_init(C, op)) return OPERATOR_PASS_THROUGH; - + } else { ScrEdge *actedge; + rcti screen_rect; int x, y; - + /* retrieve initial mouse coord, so we can find the active edge */ if (RNA_struct_property_is_set(op->ptr, "mouse_x")) x = RNA_int_get(op->ptr, "mouse_x"); else x = event->x; - + if (RNA_struct_property_is_set(op->ptr, "mouse_y")) y = RNA_int_get(op->ptr, "mouse_y"); else y = event->x; - - actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, x, y); + + WM_window_screen_rect_calc(win, &screen_rect); + + actedge = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, x, y); if (actedge == NULL) return OPERATOR_CANCELLED; - - dir = scredge_is_horizontal(actedge) ? 'v' : 'h'; - + + dir = screen_geom_edge_is_horizontal(actedge) ? 'v' : 'h'; + RNA_enum_set(op->ptr, "direction", dir); - + /* special case, adds customdata, sets defaults */ if (!area_split_menu_init(C, op)) return OPERATOR_CANCELLED; - + } - + sd = (sAreaSplitData *)op->customdata; - + if (event->type == EVT_ACTIONZONE_AREA) { - + /* do the split */ if (area_split_apply(C, op)) { - area_move_set_limits(win, sc, dir, screen_size_x, screen_size_y, &sd->bigger, &sd->smaller, NULL); - + area_move_set_limits(win, sc, dir, &sd->bigger, &sd->smaller, NULL); + /* add temp handler for edge move or cancel */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } } @@ -1860,22 +1924,22 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) area_split_preview_update_cursor(C, op); return OPERATOR_RUNNING_MODAL; - + } - + return OPERATOR_PASS_THROUGH; } /* function to be called outside UI context, or for redo */ static int area_split_exec(bContext *C, wmOperator *op) { - + if (!area_split_init(C, op)) return OPERATOR_CANCELLED; - + area_split_apply(C, op); area_split_exit(C, op); - + return OPERATOR_FINISHED; } @@ -1883,7 +1947,7 @@ static int area_split_exec(bContext *C, wmOperator *op) static void area_split_cancel(bContext *C, wmOperator *op) { sAreaSplitData *sd = (sAreaSplitData *)op->customdata; - + if (sd->previewmode) { /* pass */ } @@ -1924,7 +1988,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) } } break; - + case MIDDLEMOUSE: case TABKEY: if (sd->previewmode == 0) { @@ -1940,9 +2004,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) } } } - + break; - + case RIGHTMOUSE: /* cancel operation */ case ESCKEY: area_split_cancel(C, op); @@ -1978,12 +2042,12 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) if (sd->sarea) { ScrArea *sa = sd->sarea; if (dir == 'v') { - sd->origsize = sa->winx; - sd->origmin = sa->totrct.xmin; + sd->origmin = sa->v1->vec.x; + sd->origsize = sa->v4->vec.x - sd->origmin; } else { - sd->origsize = sa->winy; - sd->origmin = sa->totrct.ymin; + sd->origmin = sa->v1->vec.y; + sd->origsize = sa->v2->vec.y - sd->origmin; } if (sd->do_snap) { @@ -2021,17 +2085,17 @@ static void SCREEN_OT_area_split(wmOperatorType *ot) ot->name = "Split Area"; ot->description = "Split selected area into new windows"; ot->idname = "SCREEN_OT_area_split"; - + ot->exec = area_split_exec; ot->invoke = area_split_invoke; ot->modal = area_split_modal; ot->cancel = area_split_cancel; - + ot->poll = screen_active_editable; /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; - + /* rna */ RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", ""); RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0); @@ -2053,7 +2117,7 @@ typedef struct RegionMoveData { int origx, origy; int maxsize; AZEdge edge; - + } RegionMoveData; @@ -2061,20 +2125,20 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) { ARegion *ar; int dist; - + if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) { dist = BLI_rcti_size_x(&sa->totrct); } else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */ dist = BLI_rcti_size_y(&sa->totrct); } - - /* subtractwidth of regions on opposite side + + /* subtractwidth of regions on opposite side * prevents dragging regions into other opposite regions */ for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar == scalear) continue; - + if (scalear->alignment == RGN_ALIGN_TOP && ar->alignment == RGN_ALIGN_BOTTOM) dist -= ar->winy; else if (scalear->alignment == RGN_ALIGN_BOTTOM && ar->alignment == RGN_ALIGN_TOP) @@ -2083,7 +2147,7 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) dist -= ar->winx; else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT) dist -= ar->winx; - + /* case of regions in regions, like operator properties panel */ /* these can sit on top of other regions such as headers, so account for this */ else if (edge == AE_BOTTOM_TO_TOPLEFT && scalear->alignment & RGN_ALIGN_TOP && @@ -2105,20 +2169,20 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event { sActionzoneData *sad = event->customdata; AZone *az; - + if (event->type != EVT_ACTIONZONE_REGION) { BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone"); return OPERATOR_CANCELLED; } - + az = sad->az; - + if (az->ar) { RegionMoveData *rmd = MEM_callocN(sizeof(RegionMoveData), "RegionMoveData"); int maxsize; - + op->customdata = rmd; - + rmd->az = az; rmd->ar = az->ar; rmd->sa = sad->sa1; @@ -2126,13 +2190,13 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event rmd->origx = event->x; rmd->origy = event->y; rmd->maxsize = area_max_regionsize(rmd->sa, rmd->ar, rmd->edge); - + /* if not set we do now, otherwise it uses type */ if (rmd->ar->sizex == 0) rmd->ar->sizex = rmd->ar->winx; if (rmd->ar->sizey == 0) rmd->ar->sizey = rmd->ar->winy; - + /* now copy to regionmovedata */ if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) { rmd->origval = rmd->ar->sizex; @@ -2140,21 +2204,21 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event else { rmd->origval = rmd->ar->sizey; } - + /* limit headers to standard height for now */ if (rmd->ar->regiontype == RGN_TYPE_HEADER) maxsize = ED_area_headersize(); else maxsize = 1000; - + CLAMP(rmd->maxsize, 0, maxsize); - + /* add temp handler */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } - + return OPERATOR_FINISHED; } @@ -2210,20 +2274,20 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) { RegionMoveData *rmd = op->customdata; int delta; - + /* execute the events */ switch (event->type) { case MOUSEMOVE: { const float aspect = BLI_rctf_size_x(&rmd->ar->v2d.cur) / (BLI_rcti_size_x(&rmd->ar->v2d.mask) + 1); - const int snap_size_threshold = (U.widget_unit * 3) / aspect; + const int snap_size_threshold = (U.widget_unit * 2) / aspect; if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) { delta = event->x - rmd->origx; if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta; - + /* region sizes now get multiplied */ delta /= UI_DPI_FAC; - + rmd->ar->sizex = rmd->origval + delta; if (rmd->ar->type->snap_size) { @@ -2246,7 +2310,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) int maxsize = region_scale_get_maxsize(rmd); delta = event->y - rmd->origy; if (rmd->edge == AE_BOTTOM_TO_TOPLEFT) delta = -delta; - + /* region sizes now get multiplied */ delta /= UI_DPI_FAC; @@ -2268,19 +2332,19 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) if (!(rmd->ar->flag & RGN_FLAG_HIDDEN)) region_scale_toggle_hidden(C, rmd); } - else if (maxsize > 0 && (rmd->ar->sizey > maxsize)) + else if (maxsize > 0 && (rmd->ar->sizey > maxsize)) rmd->ar->sizey = maxsize; else if (rmd->ar->flag & RGN_FLAG_HIDDEN) region_scale_toggle_hidden(C, rmd); } ED_area_tag_redraw(rmd->sa); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - + break; } case LEFTMOUSE: if (event->val == KM_RELEASE) { - + if (ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) { if (rmd->ar->flag & RGN_FLAG_HIDDEN) { region_scale_toggle_hidden(C, rmd); @@ -2294,15 +2358,15 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) } MEM_freeN(op->customdata); op->customdata = NULL; - + return OPERATOR_FINISHED; } break; - + case ESCKEY: break; } - + return OPERATOR_RUNNING_MODAL; } @@ -2318,13 +2382,13 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot) ot->name = "Scale Region Size"; ot->description = "Scale selected area"; ot->idname = "SCREEN_OT_region_scale"; - + ot->invoke = region_scale_invoke; ot->modal = region_scale_modal; ot->cancel = region_scale_cancel; - + ot->poll = ED_operator_areaactive; - + /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; } @@ -2382,19 +2446,19 @@ static int frame_offset_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); int delta; - + delta = RNA_int_get(op->ptr, "delta"); CFRA += delta; FRAMENUMBER_MIN_CLAMP(CFRA); SUBFRA = 0.f; - + areas_do_frame_follow(C, false); BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); - + return OPERATOR_FINISHED; } @@ -2403,13 +2467,13 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot) ot->name = "Frame Offset"; ot->idname = "SCREEN_OT_frame_offset"; ot->description = "Move current frame forward/backward by a given number"; - + ot->exec = frame_offset_exec; - + ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; - + ot->undo_group = "Frame Change"; + /* rna */ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); } @@ -2433,9 +2497,9 @@ static int frame_jump_exec(bContext *C, wmOperator *op) */ if (animtimer) { ScreenAnimData *sad = animtimer->customdata; - + sad->flag |= ANIMPLAY_FLAG_USE_NEXT_FRAME; - + if (RNA_boolean_get(op->ptr, "end")) sad->nextfra = PEFRA; else @@ -2446,14 +2510,14 @@ static int frame_jump_exec(bContext *C, wmOperator *op) CFRA = PEFRA; else CFRA = PSFRA; - + areas_do_frame_follow(C, true); BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } - + return OPERATOR_FINISHED; } @@ -2462,13 +2526,13 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot) ot->name = "Jump to Endpoint"; ot->description = "Jump to first/last frame in frame range"; ot->idname = "SCREEN_OT_frame_jump"; - + ot->exec = frame_jump_exec; - + ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; - + ot->undo_group = "Frame Change"; + /* rna */ RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range"); } @@ -2491,7 +2555,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) float cfra; const bool next = RNA_boolean_get(op->ptr, "next"); bool done = false; - + /* sanity checks */ if (scene == NULL) return OPERATOR_CANCELLED; @@ -2500,13 +2564,13 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) /* init binarytree-list for getting keyframes */ BLI_dlrbTree_init(&keys); - + /* seed up dummy dopesheet context with flags to perform necessary filtering */ if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) { /* only selected channels are included */ ads.filterflag |= ADS_FILTER_ONLYSEL; } - + /* populate tree with keyframe nodes */ scene_to_keylist(&ads, scene, &keys, NULL); gpencil_to_keylist(&ads, scene->gpd, &keys); @@ -2515,7 +2579,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) ob_to_keylist(&ads, ob, &keys, NULL); gpencil_to_keylist(&ads, ob->gpd, &keys); } - + { Mask *mask = CTX_data_edit_mask(C); if (mask) { @@ -2526,13 +2590,13 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) /* build linked-list for searching */ BLI_dlrbTree_linkedlist_sync(&keys); - + /* find matching keyframe in the right direction */ if (next) ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); else ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); - + while ((ak != NULL) && (done == false)) { if (CFRA != (int)ak->cfra) { /* this changes the frame, so set the frame and we're done */ @@ -2549,7 +2613,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) } } } - + /* free temp stuff */ BLI_dlrbTree_free(&keys); @@ -2575,13 +2639,13 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) ot->name = "Jump to Keyframe"; ot->description = "Jump to previous/next keyframe"; ot->idname = "SCREEN_OT_keyframe_jump"; - + ot->exec = keyframe_jump_exec; - + ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; - + ot->undo_group = "Frame Change"; + /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", ""); } @@ -2647,7 +2711,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Marker", ""); @@ -2677,7 +2741,7 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot) ot->name = "Set Screen"; ot->description = "Cycle through available screens"; ot->idname = "SCREEN_OT_screen_set"; - + ot->exec = screen_set_exec; ot->poll = ED_operator_screenactive; @@ -2697,17 +2761,17 @@ static int screen_maximize_area_exec(bContext *C, wmOperator *op) bScreen *screen = CTX_wm_screen(C); ScrArea *sa = NULL; const bool hide_panels = RNA_boolean_get(op->ptr, "use_hide_panels"); - + /* search current screen for 'fullscreen' areas */ /* prevents restoring info header, when mouse is over it */ for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->full) break; } - + if (sa == NULL) { sa = CTX_wm_area(C); } - + if (hide_panels) { if (!ELEM(screen->state, SCREENNORMAL, SCREENFULL)) { return OPERATOR_CANCELLED; @@ -2729,7 +2793,8 @@ static int screen_maximize_area_poll(bContext *C) const bScreen *screen = CTX_wm_screen(C); const ScrArea *area = CTX_wm_area(C); return ED_operator_areaactive(C) && - ((screen->state != SCREENNORMAL) || (area->spacetype != SPACE_TOPBAR)); + /* Don't allow maximizing global areas but allow minimizing from them. */ + ((screen->state != SCREENNORMAL) || !ED_area_is_global(area)); } static void SCREEN_OT_screen_full_area(wmOperatorType *ot) @@ -2739,7 +2804,7 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot) ot->name = "Toggle Maximize Area"; ot->description = "Toggle display selected area as fullscreen/maximized"; ot->idname = "SCREEN_OT_screen_full_area"; - + ot->exec = screen_maximize_area_exec; ot->poll = screen_maximize_area_poll; ot->flag = 0; @@ -2754,28 +2819,28 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot) /** \name Screen Join-Area Operator * \{ */ -/* operator state vars used: +/* operator state vars used: * x1, y1 mouse coord in first area, which will disappear * x2, y2 mouse coord in 2nd area, which will become joined - * + * * functions: - * - * init() find edge based on state vars - * test if the edge divides two areas, + * + * init() find edge based on state vars + * test if the edge divides two areas, * store active and nonactive area, - * + * * apply() do the actual join - * + * * exit() cleanup, send notifier - * + * * callbacks: - * - * exec() calls init, apply, exit - * + * + * exec() calls init, apply, exit + * * invoke() sets mouse coords in x,y * call init() * add modal handler - * + * * modal() accept modal events while doing it * call apply() with active window and nonactive window * call exit() and remove handler when LMB confirm @@ -2809,18 +2874,18 @@ static int area_join_init(bContext *C, wmOperator *op) int x1, y1; int x2, y2; int shared = 0; - + /* required properties, make negative to get return 0 if not set by caller */ x1 = RNA_int_get(op->ptr, "min_x"); y1 = RNA_int_get(op->ptr, "min_y"); x2 = RNA_int_get(op->ptr, "max_x"); y2 = RNA_int_get(op->ptr, "max_y"); - + sa1 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x1, y1); sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x2, y2); if (sa1 == NULL || sa2 == NULL || sa1 == sa2) return 0; - + /* do areas share an edge? */ if (sa1->v1 == sa2->v1 || sa1->v1 == sa2->v2 || sa1->v1 == sa2->v3 || sa1->v1 == sa2->v4) shared++; if (sa1->v2 == sa2->v1 || sa1->v2 == sa2->v2 || sa1->v2 == sa2->v3 || sa1->v2 == sa2->v4) shared++; @@ -2830,7 +2895,7 @@ static int area_join_init(bContext *C, wmOperator *op) printf("areas don't share edge\n"); return 0; } - + jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join"); jd->sa1 = sa1; @@ -2848,7 +2913,7 @@ static int area_join_apply(bContext *C, wmOperator *op) { sAreaJoinData *jd = (sAreaJoinData *)op->customdata; if (!jd) return 0; - + if (!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)) { return 0; } @@ -2856,7 +2921,7 @@ static int area_join_apply(bContext *C, wmOperator *op) CTX_wm_area_set(C, NULL); CTX_wm_region_set(C, NULL); } - + return 1; } @@ -2872,7 +2937,7 @@ static void area_join_exit(bContext *C, wmOperator *op) MEM_freeN(jd); op->customdata = NULL; } - + /* this makes sure aligned edges will result in aligned grabbing */ BKE_screen_remove_double_scredges(CTX_wm_screen(C)); BKE_screen_remove_unused_scredges(CTX_wm_screen(C)); @@ -2881,55 +2946,55 @@ static void area_join_exit(bContext *C, wmOperator *op) static int area_join_exec(bContext *C, wmOperator *op) { - if (!area_join_init(C, op)) + if (!area_join_init(C, op)) return OPERATOR_CANCELLED; - + area_join_apply(C, op); area_join_exit(C, op); - + return OPERATOR_FINISHED; } /* interaction callback */ static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - + if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; - + if (sad == NULL || sad->modifier > 0) { return OPERATOR_PASS_THROUGH; } - + /* verify *sad itself */ if (sad->sa1 == NULL || sad->sa2 == NULL) return OPERATOR_PASS_THROUGH; - + /* is this our *sad? if areas equal it should be passed on */ if (sad->sa1 == sad->sa2) return OPERATOR_PASS_THROUGH; - + /* prepare operator state vars */ RNA_int_set(op->ptr, "min_x", sad->x); RNA_int_set(op->ptr, "min_y", sad->y); RNA_int_set(op->ptr, "max_x", event->x); RNA_int_set(op->ptr, "max_y", event->y); } - - - if (!area_join_init(C, op)) + + + if (!area_join_init(C, op)) return OPERATOR_PASS_THROUGH; - + /* add temp handler */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } static void area_join_cancel(bContext *C, wmOperator *op) { WM_event_add_notifier(C, NC_WINDOW, NULL); - + area_join_exit(C, op); } @@ -2938,15 +3003,15 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) { bScreen *sc = CTX_wm_screen(C); sAreaJoinData *jd = (sAreaJoinData *)op->customdata; - + /* execute the events */ switch (event->type) { - - case MOUSEMOVE: + + case MOUSEMOVE: { ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y); int dir; - + if (sa) { if (jd->sa1 != sa) { dir = area_getorientation(jd->sa1, sa); @@ -2954,7 +3019,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) jd->sa2 = sa; } else { - /* we are not bordering on the previously selected area + /* we are not bordering on the previously selected area * we check if area has common border with the one marked for removal * in this case we can swap areas. */ @@ -2970,7 +3035,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) WM_event_add_notifier(C, NC_WINDOW, NULL); } else { - /* we are back in the area previously selected for keeping + /* we are back in the area previously selected for keeping * we swap the areas if possible to allow user to choose */ if (jd->sa2 != NULL) { jd->sa1 = jd->sa2; @@ -3002,13 +3067,13 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } break; - + case RIGHTMOUSE: case ESCKEY: area_join_cancel(C, op); return OPERATOR_CANCELLED; } - + return OPERATOR_RUNNING_MODAL; } @@ -3019,17 +3084,17 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) ot->name = "Join Area"; ot->description = "Join selected areas into new window"; ot->idname = "SCREEN_OT_area_join"; - + /* api callbacks */ ot->exec = area_join_exec; ot->invoke = area_join_invoke; ot->modal = area_join_modal; ot->poll = screen_active_editable; ot->cancel = area_join_cancel; - + /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; - + /* rna */ RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX); @@ -3045,23 +3110,22 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - bScreen *sc = CTX_wm_screen(C); + const wmWindow *win = CTX_wm_window(C); + const bScreen *sc = CTX_wm_screen(C); uiPopupMenu *pup; uiLayout *layout; PointerRNA ptr; ScrEdge *actedge; - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + rcti screen_rect; + + WM_window_screen_rect_calc(win, &screen_rect); + actedge = screen_geom_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y); - actedge = screen_area_map_find_active_scredge( - AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y); - if (actedge == NULL) return OPERATOR_CANCELLED; - + pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = UI_popup_menu_layout(pup); - + uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr); /* store initial mouse cursor position */ RNA_int_set(&ptr, "mouse_x", event->x); @@ -3073,9 +3137,9 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent RNA_int_set(&ptr, "min_y", event->y + 4); RNA_int_set(&ptr, "max_x", event->x - 4); RNA_int_set(&ptr, "max_y", event->y - 4); - + UI_popup_menu_end(C, pup); - + return OPERATOR_INTERFACE; } @@ -3085,10 +3149,10 @@ static void SCREEN_OT_area_options(wmOperatorType *ot) ot->name = "Area Options"; ot->description = "Operations for splitting and merging"; ot->idname = "SCREEN_OT_area_options"; - + /* api callbacks */ ot->invoke = screen_area_options_invoke; - + ot->poll = ED_operator_screen_mainwinactive; /* flags */ @@ -3107,7 +3171,7 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op) bScreen *screen; ScrArea *sa; int tot = 0; - + for (screen = bmain->screen.first; screen; screen = screen->id.next) { for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacedata.first != sa->spacedata.last) { @@ -3121,7 +3185,7 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op) } } BKE_reportf(op->reports, RPT_INFO, "Removed amount of editors: %d", tot); - + return OPERATOR_FINISHED; } @@ -3131,11 +3195,11 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot) ot->name = "Clean-up Space-data"; ot->description = "Remove unused settings for invisible editors"; ot->idname = "SCREEN_OT_spacedata_cleanup"; - + /* api callbacks */ ot->exec = spacedata_cleanup_exec; ot->poll = WM_operator_winactive; - + } /** \} */ @@ -3163,7 +3227,7 @@ static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op)) WM_operator_free_all_after(wm, lastop); WM_operator_repeat(C, lastop); } - + return OPERATOR_CANCELLED; } @@ -3173,12 +3237,12 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot) ot->name = "Repeat Last"; ot->description = "Repeat last action"; ot->idname = "SCREEN_OT_repeat_last"; - + /* api callbacks */ ot->exec = repeat_last_exec; - + ot->poll = ED_operator_screenactive; - + } /** \} */ @@ -3194,37 +3258,37 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU uiPopupMenu *pup; uiLayout *layout; int items, i; - + items = BLI_listbase_count(&wm->operators); if (items == 0) return OPERATOR_CANCELLED; - + pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = UI_popup_menu_layout(pup); - + for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--) if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) { uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i); } - + UI_popup_menu_end(C, pup); - + return OPERATOR_INTERFACE; } static int repeat_history_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); - + op = BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index")); if (op) { /* let's put it as last operator in list */ BLI_remlink(&wm->operators, op); BLI_addtail(&wm->operators, op); - + WM_operator_repeat(C, op); } - + return OPERATOR_FINISHED; } @@ -3234,13 +3298,13 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot) ot->name = "Repeat History"; ot->description = "Display menu for previous actions performed"; ot->idname = "SCREEN_OT_repeat_history"; - + /* api callbacks */ ot->invoke = repeat_history_invoke; ot->exec = repeat_history_exec; - + ot->poll = ED_operator_screenactive; - + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); } @@ -3253,10 +3317,10 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot) static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { wmOperator *lastop = WM_operator_last_redo(C); - + if (lastop) WM_operator_redo_popup(C, lastop); - + return OPERATOR_CANCELLED; } @@ -3266,10 +3330,10 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot) ot->name = "Redo Last"; ot->description = "Display menu for last action performed"; ot->idname = "SCREEN_OT_redo_last"; - + /* api callbacks */ ot->invoke = redo_last_invoke; - + ot->poll = ED_operator_screenactive; } @@ -3312,7 +3376,7 @@ static void region_quadview_init_rv3d(ScrArea *sa, ARegion *ar, static int region_quadview_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); - + /* some rules... */ if (ar->regiontype != RGN_TYPE_WINDOW) { BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted"); @@ -3321,10 +3385,10 @@ static int region_quadview_exec(bContext *C, wmOperator *op) /* Exit quad-view */ ScrArea *sa = CTX_wm_area(C); ARegion *arn; - + /* keep current region */ ar->alignment = 0; - + if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar_iter; RegionView3D *rv3d = ar->regiondata; @@ -3354,7 +3418,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) } } } - + for (ar = sa->regionbase.first; ar; ar = arn) { arn = ar->next; if (ar->alignment == RGN_ALIGN_QSPLIT) { @@ -3375,14 +3439,14 @@ static int region_quadview_exec(bContext *C, wmOperator *op) ScrArea *sa = CTX_wm_area(C); ARegion *newar; int count; - + ar->alignment = RGN_ALIGN_QSPLIT; - + for (count = 0; count < 3; count++) { newar = BKE_area_region_copy(sa->type, ar); BLI_addtail(&sa->regionbase, newar); } - + /* lock views and set them */ if (sa->spacetype == SPACE_VIEW3D) { View3D *v3d = sa->spacedata.first; @@ -3412,8 +3476,8 @@ static int region_quadview_exec(bContext *C, wmOperator *op) ED_area_tag_redraw(sa); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); } - - + + return OPERATOR_FINISHED; } @@ -3423,7 +3487,7 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot) ot->name = "Toggle Quad View"; ot->description = "Split selected area into camera, front, right & top views"; ot->idname = "SCREEN_OT_region_quadview"; - + /* api callbacks */ ot->exec = region_quadview_exec; ot->poll = ED_operator_region_view3d_active; @@ -3440,10 +3504,10 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot) static int region_flip_exec(bContext *C, wmOperator *UNUSED(op)) { ARegion *ar = CTX_wm_region(C); - + if (!ar) return OPERATOR_CANCELLED; - + if (ar->alignment == RGN_ALIGN_TOP) ar->alignment = RGN_ALIGN_BOTTOM; else if (ar->alignment == RGN_ALIGN_BOTTOM) @@ -3455,7 +3519,7 @@ static int region_flip_exec(bContext *C, wmOperator *UNUSED(op)) ED_area_tag_redraw(CTX_wm_area(C)); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -3478,7 +3542,7 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot) ot->name = "Flip Region"; ot->idname = "SCREEN_OT_region_flip"; ot->description = "Toggle the region's alignment (left/right or top/bottom)"; - + /* api callbacks */ ot->exec = region_flip_exec; ot->poll = region_flip_poll; @@ -3545,7 +3609,7 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot) ot->name = "Expand/Collapse Header Menus"; ot->idname = "SCREEN_OT_header_toggle_menus"; ot->description = "Expand or collapse the header pulldown menus"; - + /* api callbacks */ ot->exec = header_toggle_menus_exec; ot->poll = ED_operator_areaactive; @@ -3564,6 +3628,8 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN ARegion *ar = CTX_wm_region(C); const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") : IFACE_("Flip to Top"); + uiItemO(layout, IFACE_("Toggle Header"), ICON_NONE, "SCREEN_OT_header"); + /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); @@ -3582,7 +3648,7 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN } } -static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +static int header_context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -3597,15 +3663,15 @@ static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv return OPERATOR_INTERFACE; } -static void SCREEN_OT_header_toolbox(wmOperatorType *ot) +static void SCREEN_OT_header_context_menu(wmOperatorType *ot) { /* identifiers */ - ot->name = "Header Toolbox"; - ot->description = "Display header region toolbox"; - ot->idname = "SCREEN_OT_header_toolbox"; - + ot->name = "Header Context Menu"; + ot->description = "Display header region context menu"; + ot->idname = "SCREEN_OT_header_context_menu"; + /* api callbacks */ - ot->invoke = header_toolbox_invoke; + ot->invoke = header_context_menu_invoke; } /** \} */ @@ -3624,14 +3690,14 @@ static int match_area_with_refresh(int spacetype, int refresh) return 1; break; } - + return 0; } static int match_region_with_redraws(int spacetype, int regiontype, int redraws, bool from_anim_edit) { if (regiontype == RGN_TYPE_WINDOW) { - + switch (spacetype) { case SPACE_VIEW3D: if ((redraws & TIME_ALL_3D_WIN) || from_anim_edit) @@ -3669,7 +3735,7 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws, if ((redraws & TIME_CLIPS) || from_anim_edit) return 1; break; - + } } else if (regiontype == RGN_TYPE_CHANNELS) { @@ -3734,12 +3800,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv ScrArea *sa; int sync; float time; - + /* sync, don't sync, or follow scene setting */ if (sad->flag & ANIMPLAY_FLAG_SYNC) sync = 1; else if (sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync = 0; else sync = (scene->flag & SCE_FRAME_DROP); - + if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && isfinite(time = BKE_sound_sync_scene(scene))) @@ -3785,12 +3851,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv scene->r.cfra++; } } - + sad->last_duration = wt->duration; /* reset 'jumped' flag before checking if we need to jump... */ sad->flag &= ~ANIMPLAY_FLAG_JUMPED; - + if (sad->flag & ANIMPLAY_FLAG_REVERSE) { /* jump back to end? */ if (PRVRANGEON) { @@ -3828,14 +3894,14 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv sad->flag &= ~ANIMPLAY_FLAG_USE_NEXT_FRAME; sad->flag |= ANIMPLAY_FLAG_JUMPED; } - + if (sad->flag & ANIMPLAY_FLAG_JUMPED) { BKE_sound_seek_scene(bmain, scene); #ifdef PROFILE_AUDIO_SYNCH old_frame = CFRA; #endif } - + /* since we follow drawflags, we can't send notifier but tag regions ourselves */ ED_update_for_newframe(bmain, depsgraph); @@ -3874,24 +3940,24 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } } } - + if (match_area_with_refresh(sa->spacetype, sad->refresh)) ED_area_tag_refresh(sa); } } - - /* update frame rate info too - * NOTE: this may not be accurate enough, since we might need this after modifiers/etc. + + /* update frame rate info too + * NOTE: this may not be accurate enough, since we might need this after modifiers/etc. * have been calculated instead of just before updates have been done? */ ED_refresh_viewport_fps(C); - + /* recalculate the timestep for the timer now that we've finished calculating this, * since the frames-per-second value may have been changed */ /* TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? */ wt->timestep = (1.0 / FPS); - + return OPERATOR_FINISHED; } return OPERATOR_PASS_THROUGH; @@ -3903,12 +3969,12 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot) ot->name = "Animation Step"; ot->description = "Step through animation by position"; ot->idname = "SCREEN_OT_animation_step"; - + /* api callbacks */ ot->invoke = screen_animation_step; - + ot->poll = ED_operator_screenactive_norender; - + } /** \} */ @@ -3962,16 +4028,16 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) } else { int refresh = SPACE_ACTION; /* these settings are currently only available from a menu in the TimeLine */ - + if (mode == 1) /* XXX only play audio forwards!? */ BKE_sound_play_scene(scene); - + ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); - + if (screen->animtimer) { wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; - + sad->ar = CTX_wm_region(C); } } @@ -3983,10 +4049,10 @@ static int screen_animation_play_exec(bContext *C, wmOperator *op) { int mode = (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1; int sync = -1; - + if (RNA_struct_property_is_set(op->ptr, "sync")) sync = (RNA_boolean_get(op->ptr, "sync")); - + return ED_screen_animation_play(C, sync, mode); } @@ -3998,12 +4064,12 @@ static void SCREEN_OT_animation_play(wmOperatorType *ot) ot->name = "Play Animation"; ot->description = "Play animation"; ot->idname = "SCREEN_OT_animation_play"; - + /* api callbacks */ ot->exec = screen_animation_play_exec; - + ot->poll = ED_operator_screenactive_norender; - + prop = RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate"); @@ -4046,10 +4112,10 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot) ot->name = "Cancel Animation"; ot->description = "Cancel animation, returning to the original frame"; ot->idname = "SCREEN_OT_animation_cancel"; - + /* api callbacks */ ot->exec = screen_animation_cancel_exec; - + ot->poll = ED_operator_screenactive; RNA_def_boolean(ot->srna, "restore_frame", true, "Restore Frame", "Restore the frame when animation was initialized"); @@ -4061,36 +4127,36 @@ static void SCREEN_OT_animation_cancel(wmOperatorType *ot) /** \name Border Select Operator (Template) * \{ */ -/* operator state vars used: (added by default WM callbacks) - * xmin, ymin - * xmax, ymax - * +/* operator state vars used: (added by default WM callbacks) + * xmin, ymin + * xmax, ymax + * * customdata: the wmGesture pointer - * + * * callbacks: - * + * * exec() has to be filled in by user - * + * * invoke() default WM function * adds modal handler - * - * modal() default WM function + * + * modal() default WM function * accept modal events while doing it, calls exec(), handles ESC and border drawing - * + * * poll() has to be filled in by user for context */ #if 0 static int border_select_exec(bContext *C, wmOperator *op) { int event_type = RNA_int_get(op->ptr, "event_type"); - + if (event_type == LEFTMOUSE) printf("border select do select\n"); else if (event_type == RIGHTMOUSE) printf("border select deselect\n"); - else + else printf("border select do something\n"); - + return 1; } @@ -4099,15 +4165,15 @@ static void SCREEN_OT_border_select(wmOperatorType *ot) /* identifiers */ ot->name = "Border Select"; ot->idname = "SCREEN_OT_border_select"; - + /* api callbacks */ ot->exec = border_select_exec; ot->invoke = WM_gesture_border_invoke; ot->modal = WM_gesture_border_modal; ot->cancel = WM_gesture_border_cancel; - + ot->poll = ED_operator_areaactive; - + /* rna */ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); WM_operator_properties_border(ot); @@ -4127,7 +4193,7 @@ static int fullscreen_back_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); ScrArea *sa = NULL; - + /* search current screen for 'fullscreen' areas */ for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->full) break; @@ -4148,7 +4214,7 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) ot->name = "Back to Previous Screen"; ot->description = "Revert back to the original screen layout, before fullscreen area overlay"; ot->idname = "SCREEN_OT_back_to_previous"; - + /* api callbacks */ ot->exec = fullscreen_back_exec; ot->poll = ED_operator_screenactive; @@ -4163,8 +4229,8 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int sizex = 800 * UI_DPI_FAC; - int sizey = 480 * UI_DPI_FAC; - + int sizey = 500 * UI_DPI_FAC; + /* changes context! */ if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) { return OPERATOR_FINISHED; @@ -4182,7 +4248,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) ot->name = "Show User Preferences"; ot->description = "Show user preferences"; ot->idname = "SCREEN_OT_userpref_show"; - + /* api callbacks */ ot->invoke = userpref_show_invoke; ot->poll = ED_operator_screenactive; @@ -4191,17 +4257,86 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Show Drivers Editor Operator + * \{ */ + +static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index = -1; + uiBut *but = NULL; + + int sizex = 900 * UI_DPI_FAC; + int sizey = 580 * UI_DPI_FAC; + + /* Get active property to show driver for + * - Need to grab it first, or else this info disappears + * after we've created the window + */ + but = UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + /* changes context! */ + if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_DRIVERS) != NULL) { + /* activate driver F-Curve for the property under the cursor */ + if (but) { + FCurve *fcu; + bool driven, special; + + fcu = rna_get_fcurve_context_ui(C, + &ptr, prop, index, + NULL, NULL, &driven, &special); + if (fcu) { + /* Isolate this F-Curve... */ + bAnimContext ac; + if (ANIM_animdata_get_context(C, &ac)) { + int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS; + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_CLEAR); + ANIM_set_active_channel(&ac, ac.data, ac.datatype, filter, fcu, ANIMTYPE_FCURVE); + } + else { + /* Just blindly isolate... This isn't the best, and shouldn't happen, but may be enough... */ + fcu->flag |= (FCURVE_ACTIVE | FCURVE_SELECTED); + } + } + } + + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "Failed to open window!"); + return OPERATOR_CANCELLED; + } +} + + +static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show Drivers Editor"; + ot->description = "Show drivers editor in a separate window"; + ot->idname = "SCREEN_OT_drivers_editor_show"; + + /* api callbacks */ + ot->invoke = drivers_editor_show_invoke; + ot->poll = ED_operator_screenactive; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name New Screen Operator * \{ */ static int screen_new_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); wmWindow *win = CTX_wm_window(C); WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook); WorkSpaceLayout *layout_new; - layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win); + layout_new = ED_workspace_layout_duplicate(bmain, workspace, layout_old, win); WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new); return OPERATOR_FINISHED; @@ -4213,7 +4348,7 @@ static void SCREEN_OT_new(wmOperatorType *ot) ot->name = "New Screen"; ot->description = "Add a new screen"; ot->idname = "SCREEN_OT_new"; - + /* api callbacks */ ot->exec = screen_new_exec; ot->poll = WM_operator_winactive; @@ -4242,7 +4377,7 @@ static void SCREEN_OT_delete(wmOperatorType *ot) ot->name = "Delete Screen"; ot->description = "Delete active screen"; ot->idname = "SCREEN_OT_delete"; - + /* api callbacks */ ot->exec = screen_delete_exec; } @@ -4280,7 +4415,7 @@ float ED_region_blend_alpha(ARegion *ar) alpha = (float)ar->regiontimer->duration / TIMEOUT; /* makes sure the blend out works 100% - without area redraws */ if (rgi->hidden) alpha = 0.9f - TIMESTEP - alpha; - + CLAMP(alpha, 0.0f, 1.0f); return alpha; } @@ -4291,12 +4426,12 @@ float ED_region_blend_alpha(ARegion *ar) static void region_blend_end(bContext *C, ARegion *ar, const bool is_running) { RegionAlphaInfo *rgi = ar->regiontimer->customdata; - + /* always send redraw */ ED_region_tag_redraw(ar); if (rgi->child_ar) ED_region_tag_redraw(rgi->child_ar); - + /* if running timer was hiding, the flag toggle went wrong */ if (is_running) { if (rgi->hidden) @@ -4320,14 +4455,14 @@ void region_blend_start(bContext *C, ScrArea *sa, ARegion *ar) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); RegionAlphaInfo *rgi; - + /* end running timer */ if (ar->regiontimer) { region_blend_end(C, ar, true); } rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo"); - + rgi->hidden = ar->flag & RGN_FLAG_HIDDEN; rgi->sa = sa; rgi->ar = ar; @@ -4356,18 +4491,18 @@ static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven { RegionAlphaInfo *rgi; wmTimer *timer = event->customdata; - + /* event type is TIMERREGION, but we better check */ if (event->type != TIMERREGION || timer == NULL) return OPERATOR_PASS_THROUGH; - + rgi = timer->customdata; - + /* always send redraws */ ED_region_tag_redraw(rgi->ar); if (rgi->child_ar) ED_region_tag_redraw(rgi->child_ar); - + /* end timer? */ if (rgi->ar->regiontimer->duration > (double)TIMEOUT) { region_blend_end(C, rgi->ar, false); @@ -4383,13 +4518,13 @@ static void SCREEN_OT_region_blend(wmOperatorType *ot) ot->name = "Region Alpha"; ot->idname = "SCREEN_OT_region_blend"; ot->description = "Blend in and out overlapping region"; - + /* api callbacks */ ot->invoke = region_blend_invoke; - + /* flags */ ot->flag = OPTYPE_INTERNAL; - + /* properties */ } @@ -4452,11 +4587,10 @@ static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent PointerRNA ptr; PropertyRNA *prop; context_cycle_prop_get(CTX_wm_screen(C), CTX_wm_area(C), &ptr, &prop); - const int old_context = RNA_property_enum_get(&ptr, prop); const int new_context = RNA_property_enum_step( - C, &ptr, prop, old_context, - direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1); + C, &ptr, prop, old_context, + direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1); RNA_property_enum_set(&ptr, prop, new_context); RNA_property_update(C, &ptr, prop); @@ -4483,6 +4617,51 @@ static void SCREEN_OT_space_context_cycle(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Workspace Cycle Operator + * \{ */ + +static int space_workspace_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + wmWindow *win = CTX_wm_window(C); + if (WM_window_is_temp_screen(win)) { + return OPERATOR_CANCELLED; + } + + Main *bmain = CTX_data_main(C); + const int direction = RNA_enum_get(op->ptr, "direction"); + WorkSpace *workspace_src = WM_window_get_active_workspace(win); + WorkSpace *workspace_dst = (direction == SPACE_CONTEXT_CYCLE_PREV) ? workspace_src->id.prev : workspace_src->id.next; + if (workspace_dst == NULL) { + workspace_dst = (direction == SPACE_CONTEXT_CYCLE_PREV) ? bmain->workspaces.last : bmain->workspaces.first; + } + if (workspace_src != workspace_dst) { + win->workspace_hook->temp_workspace_store = workspace_dst; + WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace_dst); + win->workspace_hook->temp_workspace_store = NULL; + } + return OPERATOR_FINISHED; +} + +static void SCREEN_OT_workspace_cycle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Workspace"; + ot->description = "Cycle through workspaces"; + ot->idname = "SCREEN_OT_workspace_cycle"; + + /* api callbacks */ + ot->invoke = space_workspace_cycle_invoke; + ot->poll = ED_operator_screenactive;; + + ot->flag = 0; + + RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction", + "Direction to cycle through"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Assigning Operator Types * \{ */ @@ -4494,7 +4673,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_repeat_last); WM_operatortype_append(SCREEN_OT_repeat_history); WM_operatortype_append(SCREEN_OT_redo_last); - + /* screen tools */ WM_operatortype_append(SCREEN_OT_area_move); WM_operatortype_append(SCREEN_OT_area_split); @@ -4507,23 +4686,24 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_region_flip); WM_operatortype_append(SCREEN_OT_header); WM_operatortype_append(SCREEN_OT_header_toggle_menus); - WM_operatortype_append(SCREEN_OT_header_toolbox); + WM_operatortype_append(SCREEN_OT_header_context_menu); WM_operatortype_append(SCREEN_OT_screen_set); WM_operatortype_append(SCREEN_OT_screen_full_area); WM_operatortype_append(SCREEN_OT_back_to_previous); WM_operatortype_append(SCREEN_OT_spacedata_cleanup); WM_operatortype_append(SCREEN_OT_screenshot); - WM_operatortype_append(SCREEN_OT_screencast); WM_operatortype_append(SCREEN_OT_userpref_show); + WM_operatortype_append(SCREEN_OT_drivers_editor_show); WM_operatortype_append(SCREEN_OT_region_blend); WM_operatortype_append(SCREEN_OT_space_context_cycle); - + WM_operatortype_append(SCREEN_OT_workspace_cycle); + /*frame changes*/ WM_operatortype_append(SCREEN_OT_frame_offset); WM_operatortype_append(SCREEN_OT_frame_jump); WM_operatortype_append(SCREEN_OT_keyframe_jump); WM_operatortype_append(SCREEN_OT_marker_jump); - + WM_operatortype_append(SCREEN_OT_animation_step); WM_operatortype_append(SCREEN_OT_animation_play); WM_operatortype_append(SCREEN_OT_animation_cancel); @@ -4540,7 +4720,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(ED_OT_undo_history); WM_operatortype_append(ED_OT_flush_edits); - + } /** \} */ @@ -4558,20 +4738,20 @@ static void keymap_modal_set(wmKeyConfig *keyconf) {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""}, {0, NULL, 0, NULL, NULL}}; wmKeyMap *keymap; - + /* Standard Modal keymap ------------------------------------------------ */ keymap = WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items); - + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_CANCEL); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KM_MODAL_APPLY); WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); - + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_SNAP_ON); WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_SNAP_OFF); - + WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move"); - + } static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) @@ -4597,14 +4777,14 @@ void ED_keymap_screen(wmKeyConfig *keyconf) ListBase *lb; wmKeyMap *keymap; wmKeyMapItem *kmi; - + /* Screen Editing ------------------------------------------------ */ keymap = WM_keymap_find(keyconf, "Screen Editing", 0, 0); - + RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "modifier", 2); - + /* screen tools */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0); @@ -4615,65 +4795,77 @@ void ED_keymap_screen(wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "use_hide_panels", true); /* area move after action zones */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); - + WM_keymap_verify_item(keymap, "SCREEN_OT_area_options", RIGHTMOUSE, KM_PRESS, 0, 0); +#ifdef USE_WM_KEYMAP_27X WM_keymap_add_item(keymap, "SCREEN_OT_header", F9KEY, KM_PRESS, KM_ALT, 0); +#endif /* Header Editing ------------------------------------------------ */ /* note: this is only used when the cursor is inside the header */ keymap = WM_keymap_find(keyconf, "Header", 0, 0); - WM_keymap_add_item(keymap, "SCREEN_OT_header_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "SCREEN_OT_header_context_menu", RIGHTMOUSE, KM_PRESS, 0, 0); /* Screen General ------------------------------------------------ */ keymap = WM_keymap_find(keyconf, "Screen", 0, 0); - + /* standard timers */ WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0); WM_keymap_add_item(keymap, "SCREEN_OT_region_blend", TIMERREGION, KM_ANY, KM_ANY, 0); - - + +#ifdef USE_WM_KEYMAP_27X RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0); +#endif WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); - kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "use_hide_panels", true); +#ifdef USE_WM_KEYMAP_27X WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0); +#endif kmi = WM_keymap_add_item(keymap, "SCREEN_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_workspace_cycle", TABKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_workspace_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV); + /* tests */ WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0); +#ifdef USE_WM_KEYMAP_27X + WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "SCREEN_OT_repeat_last", RKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "SCRIPT_OT_reload", F8KEY, KM_PRESS, 0, 0); - +#endif + /* files */ WM_keymap_add_item(keymap, "FILE_OT_execute", RETKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_execute", PADENTER, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0); - + /* undo */ #ifdef __APPLE__ WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0); +#ifdef USE_WM_KEYMAP_27X WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT | KM_OSKEY, 0); #endif +#endif WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); +#ifdef USE_WM_KEYMAP_27X WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); - - +#endif + /* render */ kmi = WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "use_viewport", true); @@ -4683,62 +4875,68 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "RENDER_OT_view_cancel", ESCKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "RENDER_OT_view_show", F11KEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "RENDER_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0); - + +#ifdef USE_WM_KEYMAP_27X /* user prefs */ #ifdef __APPLE__ WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", COMMAKEY, KM_PRESS, KM_OSKEY, 0); #endif WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", UKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); - - +#endif + + /* Anim Playback ------------------------------------------------ */ keymap = WM_keymap_find(keyconf, "Frames", 0, 0); - + /* frame offsets */ +#ifdef USE_WM_KEYMAP_27X RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "delta", 10); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "delta", -10); +#endif RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1); - + +#ifdef USE_WM_KEYMAP_27X RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1); - + RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "end", true); RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "end", false); +#endif RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", true); RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", false); - + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", UPARROWKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "next", true); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", DOWNARROWKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "next", false); - + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIALAST, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "next", true); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "next", false); - + /* play (forward and backwards) */ WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0)->ptr, "reverse", true); WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", ESCKEY, KM_PRESS, 0, 0); - + WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", MEDIAPLAY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", MEDIASTOP, KM_PRESS, 0, 0); - + /* Alternative keys for animation and sequencer playing */ #if 0 /* XXX: disabled for restoring later... bad implementation */ keymap = WM_keymap_find(keyconf, "Frames", 0, 0); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "cycle_speed", true); - + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", LEFTARROWKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "reverse", true); RNA_boolean_set(kmi->ptr, "cycle_speed", true); - + WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", DOWNARROWKEY, KM_PRESS, KM_ALT, 0); #endif diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c new file mode 100644 index 00000000000..c51227d7107 --- /dev/null +++ b/source/blender/editors/screen/screen_user_menu.c @@ -0,0 +1,196 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/screen/screen_user_menu.c + * \ingroup spview3d + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <float.h> + +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "BKE_blender_user_menu.h" +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_idprop.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +/* -------------------------------------------------------------------- */ +/** \name Menu Type + * \{ */ + +bUserMenu *ED_screen_user_menu_find(bContext *C) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + return BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context); +} + +bUserMenu *ED_screen_user_menu_ensure(bContext *C) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + return BKE_blender_user_menu_ensure(&U.user_menus, sl->spacetype, context); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Item + * \{ */ + +bUserMenuItem_Op *ED_screen_user_menu_item_find_operator( + ListBase *lb, + const wmOperatorType *ot, IDProperty *prop, short opcontext) +{ + for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) { + if (umi->type == USER_MENU_TYPE_OPERATOR) { + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; + if (STREQ(ot->idname, umi_op->op_idname) && + (opcontext == umi_op->opcontext) && + (IDP_EqualsProperties(prop, umi_op->prop))) + { + return umi_op; + } + } + } + return NULL; +} + +struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu( + struct ListBase *lb, + const struct MenuType *mt) +{ + for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) { + if (umi->type == USER_MENU_TYPE_MENU) { + bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi; + if (STREQ(mt->idname, umi_mt->mt_idname)) { + return umi_mt; + } + } + } + return NULL; +} + +void ED_screen_user_menu_item_add_operator( + ListBase *lb, const char *ui_name, + const wmOperatorType *ot, const IDProperty *prop, short opcontext) +{ + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_OPERATOR); + umi_op->opcontext = opcontext; + if (!STREQ(ui_name, ot->name)) { + STRNCPY(umi_op->item.ui_name, ui_name); + } + STRNCPY(umi_op->op_idname, ot->idname); + umi_op->prop = prop ? IDP_CopyProperty(prop) : NULL; +} + +void ED_screen_user_menu_item_add_menu( + ListBase *lb, const char *ui_name, + const MenuType *mt) +{ + bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)BKE_blender_user_menu_item_add(lb, USER_MENU_TYPE_MENU); + if (!STREQ(ui_name, mt->label)) { + STRNCPY(umi_mt->item.ui_name, ui_name); + } + STRNCPY(umi_mt->mt_idname, mt->idname); +} + +void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi) +{ + BLI_remlink(lb, umi); + BKE_blender_user_menu_item_free(umi); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Definition + * \{ */ + +static void screen_user_menu_draw(const bContext *C, Menu *menu) +{ + SpaceLink *sl = CTX_wm_space_data(C); + const char *context = CTX_data_mode_string(C); + bUserMenu *um_array[] = { + BKE_blender_user_menu_find(&U.user_menus, sl->spacetype, context), + (sl->spacetype != SPACE_TOPBAR) ? BKE_blender_user_menu_find(&U.user_menus, SPACE_TOPBAR, context) : NULL, + }; + for (int um_index = 0; um_index < ARRAY_SIZE(um_array); um_index++) { + bUserMenu *um = um_array[um_index]; + if (um == NULL) { + continue; + } + for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) { + const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL; + if (umi->type == USER_MENU_TYPE_OPERATOR) { + bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; + IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; + uiItemFullO( + menu->layout, umi_op->op_idname, ui_name, + ICON_NONE, prop, umi_op->opcontext, 0, NULL); + } + else if (umi->type == USER_MENU_TYPE_MENU) { + bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi; + uiItemM(menu->layout, umi_mt->mt_idname, ui_name, + ICON_NONE); + } + else if (umi->type == USER_MENU_TYPE_SEP) { + uiItemS(menu->layout); + } + } + } +} + +void ED_screen_user_menu_register(void) +{ + MenuType *mt = MEM_callocN(sizeof(MenuType), __func__); + strcpy(mt->idname, "SCREEN_MT_user_menu"); + strcpy(mt->label, "Quick Favorites"); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = screen_user_menu_draw; + WM_menutype_add(mt); +} + +/** \} */ diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 2c1cbc3d21d..387cd7df998 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -36,7 +36,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -44,20 +43,15 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "DNA_userdef_types.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_image.h" #include "BKE_report.h" -#include "BKE_writeavi.h" #include "BIF_gl.h" -#include "GPU_immediate.h" -#include "GPU_immediate_util.h" - #include "RNA_access.h" #include "RNA_define.h" @@ -66,9 +60,6 @@ #include "WM_types.h" #include "WM_api.h" -#include "PIL_time.h" - - #include "screen_intern.h" typedef struct ScreenshotData { @@ -104,7 +95,7 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy) *dumpsy = WM_window_pixels_y(win); if (*dumpsx && *dumpsy) { - + dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect"); glReadBuffer(GL_FRONT); screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect); @@ -122,13 +113,13 @@ static int screenshot_data_create(bContext *C, wmOperator *op) /* do redraw so we don't show popups/menus */ WM_redraw_windows(C); - + dumprect = screenshot(C, &dumpsx, &dumpsy); if (dumprect) { ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot"); ScrArea *sa = CTX_wm_area(C); - + scd->dumpsx = dumpsx; scd->dumpsy = dumpsy; scd->dumprect = dumprect; @@ -194,7 +185,7 @@ static int screenshot_exec(bContext *C, wmOperator *op) char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); - BLI_path_abs(path, G.main->name); + BLI_path_abs(path, BKE_main_blendfile_path_from_global()); /* operator ensures the extension */ ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0); @@ -233,13 +224,13 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( /* extension is added by 'screenshot_check' after */ char filepath[FILE_MAX] = "//screen"; if (G.relbase_valid) { - BLI_strncpy(filepath, G.main->name, sizeof(filepath)); - BLI_replace_extension(filepath, sizeof(filepath), ""); /* strip '.blend' */ + BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath)); + BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */ } RNA_string_set(op->ptr, "filepath", filepath); - + WM_event_add_fileselect(C, op); - + return OPERATOR_RUNNING_MODAL; } return OPERATOR_CANCELLED; @@ -291,274 +282,19 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) ot->name = "Save Screenshot"; /* weak: opname starting with 'save' makes filewindow give save-over */ ot->idname = "SCREEN_OT_screenshot"; ot->description = "Capture a picture of the active area or whole Blender window"; - + ot->invoke = screenshot_invoke; ot->check = screenshot_check; ot->exec = screenshot_exec; ot->cancel = screenshot_cancel; ot->ui = screenshot_draw; ot->poll = screenshot_poll; - + ot->flag = 0; - + WM_operator_properties_filesel( ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); RNA_def_boolean(ot->srna, "full", 1, "Full Screen", "Capture the whole window (otherwise only capture the active area)"); } - -/* *************** screenshot movie job ************************* */ - -typedef struct ScreenshotJob { - Main *bmain; - Scene *scene; - wmWindowManager *wm; - unsigned int *dumprect; - int x, y, dumpsx, dumpsy; - const short *stop; - const short *do_update; - ReportList reports; - - bMovieHandle *movie_handle; - void *movie_ctx; -} ScreenshotJob; - - -static void screenshot_freejob(void *sjv) -{ - ScreenshotJob *sj = sjv; - - if (sj->dumprect) - MEM_freeN(sj->dumprect); - - if (sj->movie_handle) { - bMovieHandle *mh = sj->movie_handle; - mh->end_movie(sj->movie_ctx); - mh->context_free(sj->movie_ctx); - } - - MEM_freeN(sj); -} - - -/* called before redraw notifiers, copies a new dumprect */ -static void screenshot_updatejob(void *sjv) -{ - ScreenshotJob *sj = sjv; - unsigned int *dumprect; - - if (sj->dumprect == NULL) { - dumprect = MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect"); - screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char *)dumprect); - - sj->dumprect = dumprect; - } -} - - -/* only this runs inside thread */ -static void screenshot_startjob(void *sjv, short *stop, short *do_update, float *UNUSED(progress)) -{ - ScreenshotJob *sj = sjv; - RenderData rd = sj->scene->r; - bMovieHandle *mh = NULL; - - /* we need this as local variables for renderdata */ - rd.frs_sec = U.scrcastfps; - rd.frs_sec_base = 1.0f; - - if (BKE_imtype_is_movie(rd.im_format.imtype)) { - mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype); - if (mh == NULL) { - printf("Movie format unsupported\n"); - return; - } - sj->movie_ctx = mh->context_create(); - sj->movie_handle = mh; - - if (!mh->start_movie(sj->movie_ctx, sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false, "")) { - printf("screencast job stopped\n"); - return; - } - } - - sj->stop = stop; - sj->do_update = do_update; - - *do_update = true; /* wait for opengl rect */ - - while (*stop == 0) { - - if (sj->dumprect) { - - if (mh) { - if (mh->append_movie(sj->movie_ctx, &rd, rd.sfra, rd.cfra, (int *)sj->dumprect, - sj->dumpsx, sj->dumpsy, "", &sj->reports)) - { - BKE_reportf(&sj->reports, RPT_INFO, "Appended frame: %d", rd.cfra); - printf("Appended frame %d\n", rd.cfra); - } - else { - break; - } - } - else { - ImBuf *ibuf = IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.im_format.planes, 0); - char name[FILE_MAX]; - int ok; - - BKE_image_path_from_imformat( - name, rd.pic, sj->bmain->name, rd.cfra, - &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true, NULL); - - ibuf->rect = sj->dumprect; - ok = BKE_imbuf_write(ibuf, name, &rd.im_format); - - if (ok == 0) { - printf("Write error: cannot save %s\n", name); - BKE_reportf(&sj->reports, RPT_INFO, "Write error: cannot save %s", name); - break; - } - else { - printf("Saved file: %s\n", name); - BKE_reportf(&sj->reports, RPT_INFO, "Saved file: %s", name); - } - - /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); - } - - MEM_freeN(sj->dumprect); - sj->dumprect = NULL; - - *do_update = true; - - rd.cfra++; - - } - else - PIL_sleep_ms(U.scrcastwait); - } - - if (mh) { - mh->end_movie(sj->movie_ctx); - mh->context_free(sj->movie_ctx); - sj->movie_handle = NULL; - } - - BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); -} - -/* Helper callback for drawing the cursor itself */ -static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) -{ - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformColor4ub(0, 0, 0, 32); - imm_draw_circle_fill_2d(pos, (float)x, (float)y, 20, 40); - - immUniformColor4ub(255, 255, 255, 128); - imm_draw_circle_wire_2d(pos, (float)x, (float)y, 20, 40); - - immUnbindProgram(); - - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); -} - -/* Turn brush cursor in 3D view on/off */ -static void screencast_cursor_toggle(wmWindowManager *wm, short enable) -{ - static void *cursor = NULL; - - if (cursor && !enable) { - /* clear cursor */ - WM_paint_cursor_end(wm, cursor); - cursor = NULL; - } - else if (enable) { - /* enable cursor */ - cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL); - } -} - -static void screenshot_endjob(void *sjv) -{ - ScreenshotJob *sj = sjv; - - screencast_cursor_toggle(sj->wm, 0); -} - - -static int screencast_exec(bContext *C, wmOperator *op) -{ - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - bScreen *screen = CTX_wm_screen(C); - wmJob *wm_job; - ScreenshotJob *sj; - - /* if called again, stop the running job */ - if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST)) - WM_jobs_stop(wm, screen, screenshot_startjob); - - wm_job = WM_jobs_get(wm, win, screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST); - sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job"); - - /* setup sj */ - if (RNA_boolean_get(op->ptr, "full")) { - sj->x = 0; - sj->y = 0; - sj->dumpsx = WM_window_pixels_x(win); - sj->dumpsy = WM_window_pixels_y(win); - } - else { - ScrArea *curarea = CTX_wm_area(C); - sj->x = curarea->totrct.xmin; - sj->y = curarea->totrct.ymin; - sj->dumpsx = curarea->totrct.xmax - sj->x; - sj->dumpsy = curarea->totrct.ymax - sj->y; - } - sj->bmain = CTX_data_main(C); - sj->scene = CTX_data_scene(C); - sj->wm = wm; - - BKE_reports_init(&sj->reports, RPT_PRINT); - - /* setup job */ - WM_jobs_customdata_set(wm_job, sj, screenshot_freejob); - WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST); - WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob); - - WM_jobs_start(sj->wm, wm_job); - - screencast_cursor_toggle(sj->wm, 1); - - WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen); - - return OPERATOR_FINISHED; -} - -void SCREEN_OT_screencast(wmOperatorType *ot) -{ - ot->name = "Make Screencast"; - ot->idname = "SCREEN_OT_screencast"; - ot->description = "Capture a video of the active area or whole Blender window"; - - ot->invoke = WM_operator_confirm; - ot->exec = screencast_exec; - ot->poll = screenshot_poll; /* shared poll */ - - ot->flag = 0; - - RNA_def_property(ot->srna, "filepath", PROP_STRING, PROP_FILEPATH); - RNA_def_boolean(ot->srna, "full", 1, "Full Screen", - "Capture the whole window (otherwise only capture the active area)"); -} diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 21dc4e0f923..800b1fbe51d 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -65,6 +65,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_toolsystem.h" #include "screen_intern.h" @@ -109,7 +110,7 @@ static void workspace_change_update_view_layer( WorkSpace *workspace_new, const WorkSpace *workspace_old, Scene *scene) { - if (!BKE_workspace_view_layer_get(workspace_new, scene)) { + if (!BKE_workspace_view_layer_exists(workspace_new, scene)) { BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene); } } @@ -130,7 +131,7 @@ static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, v } static WorkSpaceLayout *workspace_change_get_new_layout( - WorkSpace *workspace_new, wmWindow *win) + Main *bmain, WorkSpace *workspace_new, wmWindow *win) { /* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */ WorkSpaceLayout *layout_new; @@ -154,7 +155,7 @@ static WorkSpaceLayout *workspace_change_get_new_layout( NULL, false); if (!layout_temp) { /* fallback solution: duplicate layout */ - layout_temp = ED_workspace_layout_duplicate(workspace_new, layout_new, win); + layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_new, win); } layout_new = layout_temp; } @@ -176,7 +177,7 @@ bool ED_workspace_change( { Main *bmain = CTX_data_main(C); WorkSpace *workspace_old = WM_window_get_active_workspace(win); - WorkSpaceLayout *layout_new = workspace_change_get_new_layout(workspace_new, win); + WorkSpaceLayout *layout_new = workspace_change_get_new_layout(bmain, workspace_new, win); bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new); bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook); @@ -198,11 +199,11 @@ bool ED_workspace_change( screen_change_update(C, win, screen_new); workspace_change_update(workspace_new, workspace_old, C, wm); - BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL); + BLI_assert(BKE_workspace_view_layer_exists(workspace_new, CTX_data_scene(C)) != NULL); BLI_assert(CTX_wm_workspace(C) == workspace_new); - WM_toolsystem_unlink(C, workspace_old); - WM_toolsystem_link(C, workspace_new); + WM_toolsystem_unlink_all(C, workspace_old); + WM_toolsystem_reinit_all(C, win); return true; } @@ -224,10 +225,10 @@ WorkSpace *ED_workspace_duplicate( bmain, workspace_old->id.name + 2, scene, BKE_workspace_view_layer_get(workspace_old, scene)); - workspace_new->tool = workspace_old->tool; + /* TODO(campbell): tools */ for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) { - WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win); + WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win); if (layout_active_old == layout_old) { win->workspace_hook->temp_layout_store = layout_new; @@ -331,6 +332,12 @@ static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot) ot->exec = workspace_delete_exec; } +static int workspace_append_activate_poll(bContext *C) +{ + wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); + return WM_operator_poll(C, ot); +} + static int workspace_append(bContext *C, const char *directory, const char *idname) { wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); @@ -385,6 +392,7 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot) /* api callbacks */ ot->exec = workspace_append_activate_exec; + ot->poll = workspace_append_activate_poll; RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier", "Name of the workspace to append and activate"); diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c index a6f991d4bbe..6d504c05dd1 100644 --- a/source/blender/editors/screen/workspace_layout_edit.c +++ b/source/blender/editors/screen/workspace_layout_edit.c @@ -46,20 +46,22 @@ * Empty screen, with 1 dummy area without spacedata. Uses window size. */ WorkSpaceLayout *ED_workspace_layout_add( + Main *bmain, WorkSpace *workspace, wmWindow *win, const char *name) { - const int screen_size_x = WM_window_screen_pixels_x(win); - const int screen_size_y = WM_window_screen_pixels_y(win); + bScreen *screen; + rcti screen_rect; - bScreen *screen = screen_add(name, screen_size_x, screen_size_y); - WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name); + WM_window_screen_rect_calc(win, &screen_rect); + screen = screen_add(bmain, name, &screen_rect); - return layout; + return BKE_workspace_layout_add(bmain, workspace, screen, name); } WorkSpaceLayout *ED_workspace_layout_duplicate( + Main *bmain, WorkSpace *workspace, const WorkSpaceLayout *layout_old, wmWindow *win) { @@ -72,7 +74,7 @@ WorkSpaceLayout *ED_workspace_layout_duplicate( return NULL; /* XXX handle this case! */ } - layout_new = ED_workspace_layout_add(workspace, win, name); + layout_new = ED_workspace_layout_add(bmain, workspace, win, name); screen_new = BKE_workspace_layout_screen_get(layout_new); screen_data_copy(screen_new, screen_old); |