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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/screen/screen_edit.c')
-rw-r--r--source/blender/editors/screen/screen_edit.c1117
1 files changed, 485 insertions, 632 deletions
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 82552c35786..53abe3ed4ea 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -33,7 +33,9 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_userdef_types.h"
#include "BLI_math.h"
@@ -41,18 +43,17 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -66,198 +67,43 @@
#include "UI_interface.h"
-/* XXX actually should be not here... solve later */
-#include "wm_subwindow.h"
+#include "WM_message.h"
+
+#include "DEG_depsgraph_query.h"
#include "screen_intern.h" /* own module include */
/* ******************* screen vert, edge, area managing *********************** */
-static ScrVert *screen_addvert(bScreen *sc, short x, short y)
+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(&sc->vertbase, sv);
+ BLI_addtail(&area_map->vertbase, sv);
return sv;
}
-
-static void sortscrvert(ScrVert **v1, ScrVert **v2)
+static ScrVert *screen_addvert(bScreen *sc, short x, short y)
{
- ScrVert *tmp;
-
- if (*v1 > *v2) {
- tmp = *v1;
- *v1 = *v2;
- *v2 = tmp;
- }
+ return screen_addvert_ex(AREAMAP_FROM_SCREEN(sc), x, y);
}
-static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+static ScrEdge *screen_addedge_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
{
ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
- sortscrvert(&v1, &v2);
+ BKE_screen_sort_scrvert(&v1, &v2);
se->v1 = v1;
se->v2 = v2;
- BLI_addtail(&sc->edgebase, se);
+ BLI_addtail(&area_map->edgebase, se);
return se;
}
-
-
-ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
-{
- ScrEdge *se;
-
- sortscrvert(&v1, &v2);
- for (se = sc->edgebase.first; se; se = se->next)
- if (se->v1 == v1 && se->v2 == v2)
- return se;
-
- return NULL;
-}
-
-void removedouble_scrverts(bScreen *sc)
-{
- ScrVert *v1, *verg;
- ScrEdge *se;
- ScrArea *sa;
-
- verg = sc->vertbase.first;
- while (verg) {
- if (verg->newv == NULL) { /* !!! */
- v1 = verg->next;
- while (v1) {
- if (v1->newv == NULL) { /* !?! */
- if (v1->vec.x == verg->vec.x && v1->vec.y == verg->vec.y) {
- /* printf("doublevert\n"); */
- v1->newv = verg;
- }
- }
- v1 = v1->next;
- }
- }
- verg = verg->next;
- }
-
- /* replace pointers in edges and faces */
- se = sc->edgebase.first;
- while (se) {
- if (se->v1->newv) se->v1 = se->v1->newv;
- if (se->v2->newv) se->v2 = se->v2->newv;
- /* edges changed: so.... */
- sortscrvert(&(se->v1), &(se->v2));
- se = se->next;
- }
- sa = sc->areabase.first;
- while (sa) {
- if (sa->v1->newv) sa->v1 = sa->v1->newv;
- if (sa->v2->newv) sa->v2 = sa->v2->newv;
- if (sa->v3->newv) sa->v3 = sa->v3->newv;
- if (sa->v4->newv) sa->v4 = sa->v4->newv;
- sa = sa->next;
- }
-
- /* remove */
- verg = sc->vertbase.first;
- while (verg) {
- v1 = verg->next;
- if (verg->newv) {
- BLI_remlink(&sc->vertbase, verg);
- MEM_freeN(verg);
- }
- verg = v1;
- }
-
-}
-
-void removenotused_scrverts(bScreen *sc)
-{
- ScrVert *sv, *svn;
- ScrEdge *se;
-
- /* we assume edges are ok */
-
- se = sc->edgebase.first;
- while (se) {
- se->v1->flag = 1;
- se->v2->flag = 1;
- se = se->next;
- }
-
- sv = sc->vertbase.first;
- while (sv) {
- svn = sv->next;
- if (sv->flag == 0) {
- BLI_remlink(&sc->vertbase, sv);
- MEM_freeN(sv);
- }
- else {
- sv->flag = 0;
- }
- sv = svn;
- }
-}
-
-void removedouble_scredges(bScreen *sc)
-{
- ScrEdge *verg, *se, *sn;
-
- /* compare */
- verg = sc->edgebase.first;
- while (verg) {
- se = verg->next;
- while (se) {
- sn = se->next;
- if (verg->v1 == se->v1 && verg->v2 == se->v2) {
- BLI_remlink(&sc->edgebase, se);
- MEM_freeN(se);
- }
- se = sn;
- }
- verg = verg->next;
- }
-}
-
-void removenotused_scredges(bScreen *sc)
+static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
{
- ScrEdge *se, *sen;
- ScrArea *sa;
- int a = 0;
-
- /* sets flags when edge is used in area */
- sa = sc->areabase.first;
- while (sa) {
- se = screen_findedge(sc, sa->v1, sa->v2);
- if (se == NULL) printf("error: area %d edge 1 doesn't exist\n", a);
- else se->flag = 1;
- se = screen_findedge(sc, sa->v2, sa->v3);
- if (se == NULL) printf("error: area %d edge 2 doesn't exist\n", a);
- else se->flag = 1;
- se = screen_findedge(sc, sa->v3, sa->v4);
- if (se == NULL) printf("error: area %d edge 3 doesn't exist\n", a);
- else se->flag = 1;
- se = screen_findedge(sc, sa->v4, sa->v1);
- if (se == NULL) printf("error: area %d edge 4 doesn't exist\n", a);
- else se->flag = 1;
- sa = sa->next;
- a++;
- }
- se = sc->edgebase.first;
- while (se) {
- sen = se->next;
- if (se->flag == 0) {
- BLI_remlink(&sc->edgebase, se);
- MEM_freeN(se);
- }
- else {
- se->flag = 0;
- }
- se = sen;
- }
+ return screen_addedge_ex(AREAMAP_FROM_SCREEN(sc), v1, v2);
}
bool scredge_is_horizontal(ScrEdge *se)
@@ -265,19 +111,21 @@ 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_find_active_scredge(bScreen *sc,
- const int winsize_x, const int winsize_y,
- const int mx, const int my)
+/**
+ * \param bounds_rect: Either window or screen bounds. Used to exclude edges along window/screen edges.
+ */
+ScrEdge *screen_area_map_find_active_scredge(
+ const ScrAreaMap *area_map,
+ const rcti *bounds_rect,
+ const int mx, const int my)
{
- ScrEdge *se;
int safety = U.widget_unit / 10;
- if (safety < 2) safety = 2;
+ CLAMP_MIN(safety, 2);
- for (se = sc->edgebase.first; se; se = se->next) {
+ 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) {
+ 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);
@@ -287,7 +135,7 @@ ScrEdge *screen_find_active_scredge(bScreen *sc,
}
}
else {
- if (se->v1->vec.x > 0 && se->v1->vec.x < winsize_x - 1) {
+ 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);
@@ -301,23 +149,55 @@ ScrEdge *screen_find_active_scredge(bScreen *sc,
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 */
+ rcti screen_rect;
+ ScrEdge *se;
+
+ WM_window_screen_rect_calc(win, &screen_rect);
+ se = screen_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_area_map_find_active_scredge(&win->global_areas, &win_rect, mx, my);
+ }
+ return se;
+}
+
/* adds no space data */
-static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
+static ScrArea *screen_addarea_ex(
+ ScrAreaMap *area_map,
+ ScrVert *bottom_left, ScrVert *top_left, ScrVert *top_right, ScrVert *bottom_right,
+ short spacetype)
{
ScrArea *sa = MEM_callocN(sizeof(ScrArea), "addscrarea");
- sa->v1 = v1;
- sa->v2 = v2;
- sa->v3 = v3;
- sa->v4 = v4;
- sa->headertype = headertype;
- sa->spacetype = sa->butspacetype = spacetype;
- BLI_addtail(&sc->areabase, sa);
+ sa->v1 = bottom_left;
+ sa->v2 = top_left;
+ sa->v3 = top_right;
+ sa->v4 = bottom_right;
+ sa->spacetype = spacetype;
+
+ BLI_addtail(&area_map->areabase, sa);
return sa;
}
+static ScrArea *screen_addarea(
+ bScreen *sc,
+ ScrVert *left_bottom, ScrVert *left_top, ScrVert *right_top, ScrVert *right_bottom,
+ short spacetype)
+{
+ return screen_addarea_ex(AREAMAP_FROM_SCREEN(sc), left_bottom, left_top, right_top, right_bottom,
+ spacetype);
+}
static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
{
@@ -346,24 +226,24 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac)
CLAMP(fac, 0.0f, 1.0f);
if (dir == 'h') {
- y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y);
+ y = sa->v1->vec.y +
+ round_fl_to_short(fac * (float)(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);
+ x = sa->v1->vec.x +
+ round_fl_to_short(fac * (float)(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;
}
@@ -398,7 +278,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
if (fac > 0.5f) {
/* new areas: top */
- newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype);
/* area below */
sa->v2 = sv1;
@@ -406,7 +286,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
}
else {
/* new areas: bottom */
- newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->spacetype);
/* area above */
sa->v1 = sv1;
@@ -430,7 +310,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
if (fac > 0.5f) {
/* new areas: right */
- newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype);
/* area left */
sa->v3 = sv2;
@@ -438,7 +318,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
}
else {
/* new areas: left */
- newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->spacetype);
/* area right */
sa->v1 = sv1;
@@ -450,33 +330,29 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
/* remove double vertices en edges */
if (merge)
- removedouble_scrverts(sc);
- removedouble_scredges(sc);
- removenotused_scredges(sc);
+ 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 *ED_screen_add(Main *bmain, wmWindow *win, Scene *scene, const char *name)
+/**
+ * Empty screen, with 1 dummy area without spacedata. Uses window size.
+ */
+bScreen *screen_add(Main *bmain, const char *name, const rcti *rect)
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
sc = BKE_libblock_alloc(bmain, ID_SCR, name, 0);
- sc->scene = scene;
sc->do_refresh = true;
sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
- sc->winid = win->winid;
- 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);
+ sv1 = screen_addvert(sc, rect->xmin, rect->ymin);
+ sv2 = screen_addvert(sc, rect->xmin, rect->ymax - 1);
+ sv3 = screen_addvert(sc, rect->xmax - 1, rect->ymax - 1);
+ sv4 = screen_addvert(sc, rect->xmax - 1, rect->ymin);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
@@ -484,12 +360,12 @@ bScreen *ED_screen_add(Main *bmain, wmWindow *win, Scene *scene, const char *nam
screen_addedge(sc, sv4, sv1);
/* dummy type, no spacedata */
- screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY);
+ screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY);
return sc;
}
-static void screen_copy(bScreen *to, bScreen *from)
+void screen_data_copy(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
@@ -511,7 +387,7 @@ static void screen_copy(bScreen *to, bScreen *from)
for (se = to->edgebase.first; se; se = se->next) {
se->v1 = se->v1->newv;
se->v2 = se->v2->newv;
- sortscrvert(&(se->v1), &(se->v2));
+ BKE_screen_sort_scrvert(&(se->v1), &(se->v2));
}
saf = from->areabase.first;
@@ -532,7 +408,16 @@ static void screen_copy(bScreen *to, bScreen *from)
/* put at zero (needed?) */
for (s1 = from->vertbase.first; s1; s1 = s1->next)
s1->newv = NULL;
+}
+/**
+ * Prepare a newly created screen for initializing it as active screen.
+ */
+void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
+{
+ screen_new->winid = win->winid;
+ screen_new->do_refresh = true;
+ screen_new->do_draw = true;
}
@@ -611,15 +496,17 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
}
screen_delarea(C, scr, sa2);
- removedouble_scrverts(scr);
+ BKE_screen_remove_double_scrverts(scr);
+ /* Update preview thumbnail */
+ BKE_icon_changed(scr->id.icon_id);
return 1;
}
-void select_connected_scredge(bScreen *sc, ScrEdge *edge)
+void select_connected_scredge(const wmWindow *win, ScrEdge *edge)
{
+ bScreen *sc = WM_window_get_active_screen(win);
ScrEdge *se;
- ScrVert *sv;
int oneselected;
char dir;
@@ -629,10 +516,8 @@ void select_connected_scredge(bScreen *sc, ScrEdge *edge)
if (edge->v1->vec.x == edge->v2->vec.x) dir = 'v';
else dir = 'h';
- sv = sc->vertbase.first;
- while (sv) {
+ ED_screen_verts_iter(win, sc, sv) {
sv->flag = 0;
- sv = sv->next;
}
edge->v1->flag = 1;
@@ -662,18 +547,24 @@ void select_connected_scredge(bScreen *sc, ScrEdge *edge)
}
}
-/* test if screen vertices should be scaled */
-static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
+/**
+ * Test if screen vertices should be scaled and do if needed.
+ */
+static void screen_vertices_scale(
+ const wmWindow *win, bScreen *sc,
+ const rcti *window_rect, const rcti *screen_rect)
{
/* 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();
+ 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 winsize_x_prev, winsize_y_prev;
- float facx, facy, tempf, min[2], max[2];
+ int screen_size_x_prev, screen_size_y_prev;
+ float min[2], max[2];
/* calculate size */
min[0] = min[1] = 20000.0f;
@@ -684,14 +575,8 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_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];
- }
-
- winsize_x_prev = (max[0] - min[0]) + 1;
- winsize_y_prev = (max[1] - min[1]) + 1;
+ screen_size_x_prev = (max[0] - min[0]) + 1;
+ screen_size_y_prev = (max[1] - min[1]) + 1;
#ifdef USE_HEADER_SIZE_CLAMP
@@ -699,19 +584,19 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
#define TEMP_TOP 2
/* if the window's Y axis grows, clamp header sized areas */
- if (winsize_y_prev < winsize_y) { /* growing? */
+ 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 == winsize_y_prev - 1) {
+ if (sa->v2->vec.y == max[1]) {
if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
sa->temp = TEMP_TOP;
}
}
- else if (sa->v1->vec.y == 0) {
+ else if (sa->v1->vec.y == min[1]) {
if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
sa->temp = TEMP_BOTTOM;
}
@@ -722,33 +607,23 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
#endif
- if (winsize_x_prev != winsize_x || winsize_y_prev != winsize_y) {
- facx = ((float)winsize_x - 1) / ((float)winsize_x_prev - 1);
- facy = ((float)winsize_y - 1) / ((float)winsize_y_prev - 1);
+ 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) {
- /* 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);
+ 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);
- CLAMP(sv->vec.x, 0, winsize_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, winsize_y - 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 (winsize_y_prev < winsize_y) { /* growing? */
+ if (screen_size_y_prev < screen_size_y) { /* growing? */
for (sa = sc->areabase.first; sa; sa = sa->next) {
ScrEdge *se = NULL;
@@ -762,9 +637,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
if (sa->temp == TEMP_TOP) {
/* lower edge */
const int yval = sa->v2->vec.y - headery_init;
- se = screen_findedge(sc, sa->v4, sa->v1);
+ se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se != NULL) {
- select_connected_scredge(sc, se);
+ select_connected_scredge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v2 && sv != sa->v3) {
@@ -777,9 +652,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
else {
/* upper edge */
const int yval = sa->v1->vec.y + headery_init;
- se = screen_findedge(sc, sa->v2, sa->v3);
+ se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
if (se != NULL) {
- select_connected_scredge(sc, se);
+ select_connected_scredge(win, se);
}
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v1 && sv != sa->v4) {
@@ -806,21 +681,20 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
int headery = headery_init;
/* adjust headery if verts are along the edge of window */
- if (sa->v1->vec.y > 0)
+ if (sa->v1->vec.y > window_rect->ymin)
headery += U.pixelsize;
- if (sa->v2->vec.y < winsize_y - 1)
+ if (sa->v2->vec.y < window_rect->ymax)
headery += U.pixelsize;
if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) {
/* lower edge */
- ScrEdge *se = screen_findedge(sc, sa->v4, sa->v1);
+ ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
if (se && sa->v1 != sa->v2) {
- int yval;
+ const int yval = sa->v2->vec.y - headery + 1;
- select_connected_scredge(sc, se);
+ 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) {
@@ -833,31 +707,45 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
}
}
+ /* 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;
+ }
+ /* 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 - ED_area_global_size_y(area);
+ break;
+ case GLOBAL_AREA_ALIGN_BOTTOM:
+ area->v2->vec.y = area->v3->vec.y = area->v1->vec.y + ED_area_global_size_y(area);
+ break;
+ }
+ }
}
+
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
-bScreen *ED_screen_duplicate(Main *bmain, wmWindow *win, bScreen *sc)
+/* screen sets cursor based on active region */
+static void region_cursor_set(wmWindow *win, bool swin_changed)
{
- bScreen *newsc;
-
- if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */
+ bScreen *screen = WM_window_get_active_screen(win);
- /* make new empty screen: */
- newsc = ED_screen_add(bmain, win, sc->scene, sc->id.name + 2);
- /* copy all data */
- screen_copy(newsc, sc);
-
- return newsc;
-}
-
-/* screen sets cursor based on swinid */
-static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
-{
- for (ScrArea *sa = win->screen->areabase.first; sa; sa = sa->next) {
+ ED_screen_areas_iter(win, screen, sa) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->swinid == swinid) {
+ if (ar == screen->active_region) {
if (swin_changed || (ar->type && ar->type->event_cursor)) {
+ if (ar->manipulator_map != NULL) {
+ if (WM_manipulatormap_cursor_set(ar->manipulator_map, win)) {
+ return;
+ }
+ }
ED_region_cursor_set(win, sa, ar);
}
return;
@@ -869,23 +757,24 @@ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
void ED_screen_do_listen(bContext *C, wmNotifier *note)
{
wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = CTX_wm_screen(C);
/* generic notes */
switch (note->category) {
case NC_WM:
if (note->data == ND_FILEREAD)
- win->screen->do_draw = true;
+ screen->do_draw = true;
break;
case NC_WINDOW:
- win->screen->do_draw = true;
+ screen->do_draw = true;
break;
case NC_SCREEN:
if (note->action == NA_EDITED)
- win->screen->do_draw = win->screen->do_refresh = true;
+ screen->do_draw = screen->do_refresh = true;
break;
case NC_SCENE:
if (note->data == ND_MODE)
- region_cursor_set(win, note->swinid, true);
+ region_cursor_set(win, true);
break;
}
}
@@ -906,48 +795,40 @@ static void screen_refresh_headersizes(void)
/* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
{
+ bScreen *screen = WM_window_get_active_screen(win);
+
/* exception for bg mode, we only need the screen context */
if (!G.background) {
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
- ScrArea *sa;
- rcti winrct;
-
- winrct.xmin = 0;
- winrct.xmax = winsize_x - 1;
- winrct.ymin = 0;
- winrct.ymax = winsize_y - 1;
+ rcti window_rect, screen_rect;
/* header size depends on DPI, let's verify */
WM_window_set_dpi(win);
screen_refresh_headersizes();
- screen_test_scale(win->screen, winsize_x, winsize_y);
+ WM_window_rect_calc(win, &window_rect);
+ WM_window_screen_rect_calc(win, &screen_rect); /* Get screen bounds __after__ updating window DPI! */
- if (win->screen->mainwin == 0) {
- win->screen->mainwin = wm_subwindow_open(win, &winrct, false);
- }
- else {
- wm_subwindow_position(win, win->screen->mainwin, &winrct, false);
- }
+ screen_vertices_scale(win, screen, &window_rect, &screen_rect);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ 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, sa);
+ ED_area_initialize(wm, win, area);
}
/* wake up animtimer */
- if (win->screen->animtimer)
- WM_event_timer_sleep(wm, win, win->screen->animtimer, false);
+ if (screen->animtimer)
+ WM_event_timer_sleep(wm, win, screen->animtimer, false);
}
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set screen\n", __func__);
}
- win->screen->do_refresh = false;
+ screen->do_refresh = false;
+ /* prevent multiwin errors */
+ screen->winid = win->winid;
- win->screen->context = ed_screen_context;
+ screen->context = ed_screen_context;
}
/* file read, set all screens, ... */
@@ -956,10 +837,23 @@ 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, bmain->workspaces.first);
+ }
- if (win->screen == NULL)
- win->screen = bmain->screen.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);
+ }
+ }
+}
+void ED_screen_ensure_updated(wmWindowManager *wm, wmWindow *win, bScreen *screen)
+{
+ if (screen->do_refresh) {
ED_screen_refresh(wm, win);
}
}
@@ -970,17 +864,17 @@ void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
void ED_region_exit(bContext *C, ARegion *ar)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ARegion *prevar = CTX_wm_region(C);
if (ar->type && ar->type->exit)
ar->type->exit(wm, ar);
CTX_wm_region_set(C, ar);
+
WM_event_remove_handlers(C, &ar->handlers);
- if (ar->swinid) {
- wm_subwindow_close(CTX_wm_window(C), ar->swinid);
- ar->swinid = 0;
- }
+ WM_event_modal_handler_region_replace(win, ar, NULL);
+ WM_draw_region_free(ar);
if (ar->headerstr) {
MEM_freeN(ar->headerstr);
@@ -988,16 +882,19 @@ void ED_region_exit(bContext *C, ARegion *ar)
}
if (ar->regiontimer) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
+ WM_event_remove_timer(wm, win, ar->regiontimer);
ar->regiontimer = NULL;
}
+ WM_msgbus_clear_by_owner(wm->message_bus, ar);
+
CTX_wm_region_set(C, prevar);
}
void ED_area_exit(bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *ar;
@@ -1005,10 +902,13 @@ void ED_area_exit(bContext *C, ScrArea *sa)
sa->type->exit(wm, sa);
CTX_wm_area_set(C, sa);
+
for (ar = sa->regionbase.first; ar; ar = ar->next)
ED_region_exit(C, ar);
WM_event_remove_handlers(C, &sa->handlers);
+ WM_event_modal_handler_area_replace(win, sa, NULL);
+
CTX_wm_area_set(C, prevsa);
}
@@ -1016,8 +916,6 @@ 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);
@@ -1026,21 +924,23 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
screen->animtimer = NULL;
screen->scrubbing = false;
- if (screen->mainwin)
- wm_subwindow_close(window, screen->mainwin);
- screen->mainwin = 0;
- screen->subwinactive = 0;
+ 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);
+ }
+ /* 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 (prevwin->screen->temp == 0) {
+ if (!WM_window_is_temp_screen(prevwin)) {
/* use previous window if possible */
CTX_wm_window_set(C, prevwin);
}
@@ -1054,16 +954,14 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* *********************************** */
/* case when on area-edge or in azones, or outside window */
-static void screen_cursor_set(wmWindow *win, const wmEvent *event)
+static void screen_cursor_set(wmWindow *win, const int xy[2])
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
+ const bScreen *screen = WM_window_get_active_screen(win);
AZone *az = NULL;
ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next)
- if ((az = ED_area_actionzone_find_xy(sa, &event->x)))
+ for (sa = screen->areabase.first; sa; sa = sa->next)
+ if ((az = ED_area_actionzone_find_xy(sa, xy)))
break;
if (sa) {
@@ -1077,7 +975,7 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event)
}
}
else {
- ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y);
+ ScrEdge *actedge = screen_find_active_scredge(win, screen, xy[0], xy[1]);
if (actedge) {
if (scredge_is_horizontal(actedge))
@@ -1093,20 +991,20 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event)
/* called in wm_event_system.c. sets state vars in screen, cursors */
/* event type is mouse move */
-void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
+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 (win->screen) {
- bScreen *scr = win->screen;
- ScrArea *sa;
+ if (scr) {
+ ScrArea *sa = NULL;
ARegion *ar;
- int oldswin = scr->subwinactive;
+ ARegion *old_ar = scr->active_region;
- for (sa = scr->areabase.first; sa; sa = sa->next) {
- if (event->x > sa->totrct.xmin && event->x < sa->totrct.xmax) {
- if (event->y > sa->totrct.ymin && event->y < sa->totrct.ymax) {
- if (NULL == ED_area_actionzone_refresh_xy(sa, &event->x)) {
+ 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 (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) {
+ sa = area_iter;
break;
}
}
@@ -1115,49 +1013,55 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
if (sa) {
/* make overlap active when mouse over */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
- scr->subwinactive = ar->swinid;
+ if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
+ scr->active_region = ar;
break;
}
}
}
else
- scr->subwinactive = scr->mainwin;
+ scr->active_region = NULL;
/* check for redraw headers */
- if (oldswin != scr->subwinactive) {
+ if (old_ar != scr->active_region) {
- for (sa = scr->areabase.first; sa; sa = sa->next) {
+ ED_screen_areas_iter(win, scr, area_iter) {
bool do_draw = false;
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid == oldswin || ar->swinid == scr->subwinactive)
+ 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 = sa->regionbase.first; ar; ar = ar->next)
- if (ar->regiontype == RGN_TYPE_HEADER)
- ED_region_tag_redraw(ar);
+ for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ }
}
}
}
/* cursors, for time being set always on edges, otherwise aregion doesnt switch */
- if (scr->subwinactive == scr->mainwin) {
- screen_cursor_set(win, event);
+ if (scr->active_region == NULL) {
+ screen_cursor_set(win, xy);
}
else {
/* notifier invokes freeing the buttons... causing a bit too much redraws */
- if (oldswin != scr->subwinactive) {
- region_cursor_set(win, scr->subwinactive, true);
+ if (old_ar != scr->active_region) {
+ region_cursor_set(win, true);
/* 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, win->screen);
+ if (C) {
+ UI_screen_free_active_but(C, scr);
+ }
}
else
- region_cursor_set(win, scr->subwinactive, false);
+ region_cursor_set(win, false);
}
}
}
@@ -1176,183 +1080,199 @@ int ED_screen_area_active(const bContext *C)
return 1;
for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar->swinid == sc->subwinactive)
+ if (ar == sc->active_region)
return 1;
}
return 0;
}
/**
- * operator call, WM + Window + screen already existed before
- *
- * \warning Do NOT call in area/region queues!
- * \returns success.
+ * Add an area and geometry (screen-edges and -vertices) for it to \a area_map,
+ * with coordinates/dimensions matching \a rect.
*/
-bool ED_screen_set(bContext *C, bScreen *sc)
+static ScrArea *screen_area_create_with_geometry(
+ ScrAreaMap *area_map, const rcti *rect,
+ short spacetype)
{
- Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- bScreen *oldscreen = CTX_wm_screen(C);
+ 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);
- /* validate screen, it's called with notifier reference */
- if (BLI_findindex(&bmain->screen, sc) == -1) {
- return true;
+ 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);
+
+ return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype);
+}
+
+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)
+{
+ 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 = 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, size_y, size_y);
+}
+
+void ED_screen_global_areas_create(wmWindow *win)
+{
+ 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);
}
+}
- if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
- /* find associated full */
- bScreen *sc1;
- for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
- ScrArea *sa = sc1->areabase.first;
- if (sa->full == sc) {
- sc = sc1;
- break;
- }
+
+/* -------------------------------------------------------------------- */
+/* Screen changing */
+
+static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
+{
+ for (bScreen *screen_iter = bmain->screen.first; screen_iter; screen_iter = screen_iter->id.next) {
+ ScrArea *sa = screen_iter->areabase.first;
+ if (sa && sa->full == screen) {
+ return screen_iter;
}
}
+ return screen;
+}
+
+/**
+ * \return the screen to activate.
+ * \warning The returned screen may not always equal \a screen_new!
+ */
+bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
+{
+ /* validate screen, it's called with notifier reference */
+ if (BLI_findindex(&bmain->screen, screen_new) == -1) {
+ return NULL;
+ }
+
+ if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
+ }
+
/* check for valid winid */
- if (sc->winid != 0 && sc->winid != win->winid) {
- return false;
+ if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
+ return NULL;
}
- if (oldscreen != sc) {
- wmTimer *wt = oldscreen->animtimer;
- ScrArea *sa;
- Scene *oldscene = oldscreen->scene;
+ if (screen_old != screen_new) {
+ wmTimer *wt = screen_old->animtimer;
/* remove handlers referencing areas in old screen */
- for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) {
WM_event_remove_area_handler(&win->modalhandlers, sa);
}
/* we put timer to sleep, so screen_exit has to think there's no timer */
- oldscreen->animtimer = NULL;
+ screen_old->animtimer = NULL;
if (wt) {
- WM_event_timer_sleep(wm, win, wt, true);
+ WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
}
-
- ED_screen_exit(C, win, oldscreen);
+ ED_screen_exit(C, win, screen_old);
/* Same scene, "transfer" playback to new screen. */
if (wt) {
- if (oldscene == sc->scene) {
- sc->animtimer = wt;
- }
- /* Else, stop playback. */
- else {
- oldscreen->animtimer = wt;
- ED_screen_animation_play(C, 0, 0);
- }
+ screen_new->animtimer = wt;
}
- win->screen = sc;
- CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf
-
- /* prevent multiwin errors */
- sc->winid = win->winid;
-
- ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENSET, sc);
-
- /* makes button hilites work */
- WM_event_add_mousemove(C);
-
- /* Needed to make sure all the derivedMeshes are
- * up-to-date before viewport starts acquiring this.
- *
- * This is needed in cases when, for example, boolean
- * modifier uses operant from invisible layer.
- * Without this trick boolean wouldn't apply correct.
- *
- * Quite the same happens when setting screen's scene,
- * so perhaps this is in fact correct thing to do.
- */
- if (oldscene != sc->scene) {
- BKE_scene_set_background(bmain, sc->scene);
- }
-
- /* Always do visible update since it's possible new screen will
- * have different layers visible in 3D view-ports.
- * This is possible because of view3d.lock_camera_and_layers option.
- */
- DAG_on_visible_update(bmain, false);
+ return screen_new;
}
- return true;
+ return NULL;
}
-static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
+void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
{
- wmWindow *win;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen == sc) {
- return true;
- }
+ CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
- if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
- ScrArea *sa = win->screen->areabase.first;
- if (sa->full == sc) {
- return true;
- }
- }
- }
+ ED_screen_refresh(CTX_wm_manager(C), win);
- return false;
+ BKE_screen_view3d_scene_sync(sc, scene); /* sync new screen with scene data */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout);
+
+ /* makes button hilites work */
+ WM_event_add_mousemove(C);
}
-/* only call outside of area/region loops */
-bool ED_screen_delete(bContext *C, bScreen *sc)
+
+/**
+ * \brief Change the active screen.
+ *
+ * Operator call, WM + Window + screen already existed before
+ *
+ * \warning Do NOT call in area/region queues!
+ * \returns if screen changing was successful.
+ */
+bool ED_screen_change(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- bScreen *newsc;
+ bScreen *screen_old = CTX_wm_screen(C);
+ bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
- /* don't allow deleting temp fullscreens for now */
- if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
- return false;
- }
-
- /* screen can only be in use by one window at a time, so as
- * long as we are able to find a screen that is unused, we
- * can safely assume ours is not in use anywhere an delete it */
-
- for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
-
- if (!newsc) {
- for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
- }
-
- if (!newsc) {
- return false;
- }
+ if (screen_new) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WM_window_set_active_screen(win, workspace, sc);
+ screen_change_update(C, win, screen_new);
- ED_screen_set(C, newsc);
-
- if (win->screen != sc) {
- BKE_libblock_free(bmain, sc);
return true;
}
- else {
- return false;
- }
+
+ return false;
}
-static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
+static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrArea *sa, View3D *v3d)
{
/* fix any cameras that are used in the 3d view but not in the scene */
BKE_screen_view3d_sync(v3d, scene);
- if (!v3d->camera || !BKE_scene_base_find(scene, v3d->camera)) {
- v3d->camera = BKE_scene_camera_find(sc->scene);
+ if (!v3d->camera || !BKE_view_layer_base_find(view_layer, v3d->camera)) {
+ v3d->camera = BKE_view_layer_camera_find(view_layer);
// XXX if (sc == curscreen) handle_view3d_lock();
if (!v3d->camera) {
ARegion *ar;
@@ -1376,100 +1296,21 @@ static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa,
}
}
-/* only call outside of area/region loops */
-void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
+void ED_screen_update_after_scene_change(const bScreen *screen, Scene *scene_new, ViewLayer *view_layer)
{
- Main *bmain = CTX_data_main(C);
- bScreen *sc;
-
- if (screen == NULL)
- return;
-
- if (ed_screen_used(CTX_wm_manager(C), screen)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
-
- if (scene != sc->scene) {
- /* all areas endlocalview */
- // XXX ScrArea *sa = sc->areabase.first;
- // while (sa) {
- // endlocalview(sa);
- // sa = sa->next;
- // }
- sc->scene = scene;
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ screen_set_3dview_camera(scene_new, view_layer, sa, v3d);
}
-
}
}
-
- // copy_view3d_lock(0); /* space.c */
-
- /* are there cameras in the views that are not in the scene? */
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
- ScrArea *sa = sc->areabase.first;
- while (sa) {
- SpaceLink *sl = sa->spacedata.first;
- while (sl) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
- ed_screen_set_3dview_camera(scene, sc, sa, v3d);
-
- }
- sl = sl->next;
- }
- sa = sa->next;
- }
- }
- }
-
- CTX_data_scene_set(C, scene);
- BKE_scene_set_background(bmain, scene);
- DAG_on_visible_update(bmain, false);
-
- ED_render_engine_changed(bmain);
- ED_update_for_newframe(bmain, scene, 1);
-
- /* complete redraw */
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
-}
-
-/**
- * \note Only call outside of area/region loops
- * \return true if successful
- */
-bool ED_screen_delete_scene(bContext *C, Scene *scene)
-{
- Main *bmain = CTX_data_main(C);
- Scene *newscene;
-
- if (scene->id.prev)
- newscene = scene->id.prev;
- else if (scene->id.next)
- newscene = scene->id.next;
- else
- return false;
-
- ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
-
- BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
-
- id_us_clear_real(&scene->id);
- if (scene->id.us == 0) {
- BKE_libblock_free(bmain, scene);
- }
-
- return true;
}
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
{
wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
ScrArea *newsa = NULL;
if (!sa || sa->full == NULL) {
@@ -1477,18 +1318,7 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
}
if (!newsa) {
- if (sa->full && (screen->state == SCREENMAXIMIZED)) {
- /* if this has been called from the temporary info header generated in
- * temp fullscreen layouts, find the correct fullscreen area to change
- * to create a new space inside */
- for (newsa = screen->areabase.first; newsa; newsa = newsa->next) {
- if (!(sa->flag & AREA_TEMP_INFO))
- break;
- }
- }
- else {
- newsa = sa;
- }
+ newsa = sa;
}
BLI_assert(newsa);
@@ -1571,6 +1401,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
bScreen *sc, *oldscreen;
ARegion *ar;
@@ -1592,9 +1423,10 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
if (sa && sa->full) {
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
/* restoring back to SCREENNORMAL */
sc = sa->full; /* the old screen to restore */
- oldscreen = win->screen; /* the one disappearing */
+ oldscreen = WM_window_get_active_screen(win); /* the one disappearing */
sc->state = SCREENNORMAL;
@@ -1608,10 +1440,8 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
/* clear full screen state */
old->full = NULL;
- old->flag &= ~AREA_TEMP_INFO;
}
- sa->flag &= ~AREA_TEMP_INFO;
sa->full = NULL;
if (fullsa == NULL) {
@@ -1621,6 +1451,10 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
if (state == SCREENFULL) {
+ /* unhide global areas */
+ for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area; glob_area = glob_area->next) {
+ glob_area->global->flag &= ~GLOBAL_AREA_IS_HIDDEN;
+ }
/* restore the old side panels/header visibility */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
ar->flag = ar->flagfullscreen;
@@ -1633,9 +1467,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
sc->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
- ED_screen_set(C, sc);
+ ED_screen_change(C, sc);
- BKE_libblock_free(CTX_data_main(C), oldscreen);
+ BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
/* After we've restored back to SCREENNORMAL, we have to wait with
* screen handling as it uses the area coords which aren't updated yet.
@@ -1645,14 +1479,20 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
else {
/* change from SCREENNORMAL to new state */
+ WorkSpaceLayout *layout_new;
ScrArea *newa;
char newname[MAX_ID_NAME - 2];
- oldscreen = win->screen;
+ BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL));
+
+ oldscreen = WM_window_get_active_screen(win);
oldscreen->state = state;
BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
- sc = ED_screen_add(bmain, win, oldscreen->scene, newname);
+
+ layout_new = ED_workspace_layout_add(bmain, workspace, win, newname);
+
+ sc = BKE_workspace_layout_screen_get(layout_new);
sc->state = state;
sc->redraws_flag = oldscreen->redraws_flag;
sc->temp = oldscreen->temp;
@@ -1663,51 +1503,35 @@ 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;
-
- if (state == SCREENMAXIMIZED) {
- /* returns the top small area */
- newa = area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1);
- ED_area_newspace(C, newa, SPACE_INFO, false);
-
- /* copy area */
- newa = newa->prev;
- ED_area_data_swap(newa, sa);
- sa->flag |= AREA_TEMP_INFO;
-
- sa->full = oldscreen;
- newa->full = oldscreen;
- newa->next->full = oldscreen; // XXX
}
- else if (state == SCREENFULL) {
- newa = (ScrArea *)sc->areabase.first;
- /* copy area */
- ED_area_data_swap(newa, sa);
- newa->flag = sa->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
+ newa = (ScrArea *)sc->areabase.first;
+ /* copy area */
+ ED_area_data_swap(newa, sa);
+ newa->flag = sa->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
+
+ if (state == SCREENFULL) {
+ /* temporarily hide global areas */
+ for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area; glob_area = glob_area->next) {
+ glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN;
+ }
/* temporarily hide the side panels/header */
for (ar = newa->regionbase.first; ar; ar = ar->next) {
ar->flagfullscreen = ar->flag;
- if (ELEM(ar->regiontype,
- RGN_TYPE_UI,
- RGN_TYPE_HEADER,
- RGN_TYPE_TOOLS))
- {
+ if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_HEADER, RGN_TYPE_TOOLS)) {
ar->flag |= RGN_FLAG_HIDDEN;
}
}
-
- sa->full = oldscreen;
- newa->full = oldscreen;
- }
- else {
- BLI_assert(false);
}
- ED_screen_set(C, sc);
+ sa->full = oldscreen;
+ newa->full = oldscreen;
+
+ ED_screen_change(C, sc);
}
/* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
@@ -1794,7 +1618,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
if (sa)
spacetype = sa->spacetype;
- sad->from_anim_edit = (ELEM(spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA, SPACE_TIME));
+ sad->from_anim_edit = (ELEM(spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA));
screen->animtimer->customdata = sad;
@@ -1842,13 +1666,10 @@ void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
}
}
-/* results in fully updated anim system
- * screen can be NULL */
-void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
+/* results in fully updated anim system */
+void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
{
- wmWindowManager *wm = bmain->wm.first;
- wmWindow *window;
- int layers = 0;
+ Scene *scene = DEG_get_input_scene(depsgraph);
#ifdef DURIAN_CAMERA_SWITCH
void *camera = BKE_scene_camera_switch_find(scene);
@@ -1857,19 +1678,15 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
scene->camera = camera;
/* are there cameras in the views that are not in the scene? */
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- BKE_screen_view3d_scene_sync(sc);
+ BKE_screen_view3d_scene_sync(sc, scene);
}
}
#endif
ED_clip_update_frame(bmain, scene->r.cfra);
- /* get layers from all windows */
- for (window = wm->windows.first; window; window = window->next)
- layers |= BKE_screen_visible_layers(window->screen, scene);
-
/* this function applies the changes too */
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* composite */
if (scene->use_nodes && scene->nodetree)
@@ -1890,11 +1707,10 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
/*
* return true if any active area requires to see in 3D
*/
-bool ED_screen_stereo3d_required(bScreen *screen)
+bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
{
ScrArea *sa;
- Scene *sce = screen->scene;
- const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
for (sa = screen->areabase.first; sa; sa = sa->next) {
switch (sa->spacetype) {
@@ -1969,3 +1785,40 @@ bool ED_screen_stereo3d_required(bScreen *screen)
return false;
}
+
+/**
+ * Find the scene displayed in \a screen.
+ * \note Assumes \a screen to be visible/active!
+ */
+
+Scene *ED_screen_scene_find_with_window(const bScreen *screen, const wmWindowManager *wm, struct wmWindow **r_window)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ if (r_window) {
+ *r_window = win;
+ }
+ return WM_window_get_active_scene(win);
+ }
+ }
+
+ BLI_assert(0);
+ return NULL;
+}
+
+
+Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
+{
+ return ED_screen_scene_find_with_window(screen, wm, NULL);
+}
+
+
+wmWindow *ED_screen_window_find(const bScreen *screen, const wmWindowManager *wm)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return win;
+ }
+ }
+ return NULL;
+}