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.c1431
1 files changed, 505 insertions, 926 deletions
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 2e8c5204b3d..b4c639e51b6 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_image.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
+#include "BKE_image.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,258 +67,39 @@
#include "UI_interface.h"
-/* XXX actually should be not here... solve later */
-#include "wm_subwindow.h"
-
-#include "screen_intern.h" /* own module include */
-
-
-/* ******************* screen vert, edge, area managing *********************** */
-
-static ScrVert *screen_addvert(bScreen *sc, short x, short y)
-{
- ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
- sv->vec.x = x;
- sv->vec.y = y;
-
- BLI_addtail(&sc->vertbase, sv);
- return sv;
-}
-
-static void sortscrvert(ScrVert **v1, ScrVert **v2)
-{
- ScrVert *tmp;
-
- if (*v1 > *v2) {
- tmp = *v1;
- *v1 = *v2;
- *v2 = tmp;
- }
-}
-
-static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
-{
- ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
-
- sortscrvert(&v1, &v2);
- se->v1 = v1;
- se->v2 = v2;
-
- BLI_addtail(&sc->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;
+#include "WM_message.h"
- 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)
-{
- 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;
- }
-}
-
-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)
-{
- ScrEdge *se;
- int safety = U.widget_unit / 10;
-
- if (safety < 2) safety = 2;
-
- for (se = sc->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;
-}
+#include "DEG_depsgraph_query.h"
+#include "screen_intern.h" /* own module include */
/* 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)
{
@@ -330,54 +112,18 @@ static void screen_delarea(bContext *C, bScreen *sc, ScrArea *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.
@@ -386,19 +132,19 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
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->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype);
/* area below */
sa->v2 = sv1;
@@ -406,7 +152,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;
@@ -418,19 +164,19 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
}
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->headertype, sa->spacetype);
+ newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype);
/* area left */
sa->v3 = sv2;
@@ -438,7 +184,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,46 +196,42 @@ 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_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_addedge(sc, sv1, sv2);
- screen_addedge(sc, sv2, sv3);
- screen_addedge(sc, sv3, sv4);
- screen_addedge(sc, sv4, sv1);
+ 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, 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;
@@ -498,6 +240,8 @@ static void screen_copy(bScreen *to, bScreen *from)
/* free contents of 'to', is from blenkernel screen.c */
BKE_screen_free(to);
+ to->flag = from->flag;
+
BLI_duplicatelist(&to->vertbase, &from->vertbase);
BLI_duplicatelist(&to->edgebase, &from->edgebase);
BLI_duplicatelist(&to->areabase, &from->areabase);
@@ -511,7 +255,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 +276,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;
}
@@ -588,276 +341,53 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
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);
- 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)
-{
- ScrEdge *se;
- ScrVert *sv;
- 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';
-
- sv = sc->vertbase.first;
- while (sv) {
- sv->flag = 0;
- sv = sv->next;
- }
-
- 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 */
-static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_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 winsize_x_prev, winsize_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];
- }
-
- winsize_x_prev = (max[0] - min[0]) + 1;
- winsize_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 (winsize_y_prev < winsize_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 - 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 (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);
-
- /* 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, 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);
- }
- }
-
-
-#ifdef USE_HEADER_SIZE_CLAMP
- if (winsize_y_prev < winsize_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 = screen_findedge(sc, sa->v4, sa->v1);
- if (se != NULL) {
- select_connected_scredge(sc, 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 = screen_findedge(sc, sa->v2, sa->v3);
- if (se != NULL) {
- select_connected_scredge(sc, 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 < winsize_y - 1)
- 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);
- if (se && sa->v1 != sa->v2) {
- int yval;
-
- select_connected_scredge(sc, 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;
- }
- }
- }
- }
- }
- }
-
-}
/* ****************** 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->gizmo_map != NULL) {
+ if (WM_gizmomap_cursor_set(ar->gizmo_map, win)) {
+ return;
+ }
+ }
ED_region_cursor_set(win, sa, ar);
}
return;
@@ -869,23 +399,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 +437,37 @@ 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;
-
/* 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);
+ ED_screen_global_areas_refresh(win);
+ screen_refresh_headersizes();
- 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_geom_vertices_scale(win, screen);
- 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 +476,20 @@ void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
+ if (BKE_workspace_active_get(win->workspace_hook) == NULL) {
+ BKE_workspace_active_set(win->workspace_hook, bmain->workspaces.first);
+ }
- if (win->screen == NULL)
- win->screen = bmain->screen.first;
+ 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 +500,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 +518,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 +538,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 +552,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 +560,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 +590,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,10 +611,10 @@ 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_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);
@@ -1093,20 +627,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 +649,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);
+ /* cursors, for time being set always on edges, otherwise aregion doesn't switch */
+ 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 +716,261 @@ 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_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);
- /* validate screen, it's called with notifier reference */
- if (BLI_findindex(&bmain->screen, sc) == -1) {
- return true;
- }
+ 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);
- 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;
- }
+ return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype);
+}
+
+static void screen_area_set_geometry_rect(ScrArea *sa, const rcti *rect)
+{
+ sa->v1->vec.x = rect->xmin;
+ sa->v1->vec.y = rect->ymin;
+ sa->v2->vec.x = rect->xmin;
+ sa->v2->vec.y = rect->ymax;
+ sa->v3->vec.x = rect->xmax;
+ sa->v3->vec.y = rect->ymax;
+ sa->v4->vec.x = rect->xmax;
+ sa->v4->vec.y = rect->ymin;
+}
+
+static void screen_global_area_refresh(
+ wmWindow *win, bScreen *screen,
+ eSpace_Type space_type, GlobalAreaAlign align, const rcti *rect,
+ const short height_cur, const short height_min, const short height_max)
+{
+ ScrArea *area;
+
+ for (area = win->global_areas.areabase.first; area; area = area->next) {
+ if (area->spacetype == space_type) {
+ break;
}
}
- /* check for valid winid */
- if (sc->winid != 0 && sc->winid != win->winid) {
- return false;
+ if (area) {
+ screen_area_set_geometry_rect(area, rect);
}
+ else {
+ 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));
- if (oldscreen != sc) {
- wmTimer *wt = oldscreen->animtimer;
- ScrArea *sa;
- Scene *oldscene = oldscreen->scene;
+ area->regionbase = slink->regionbase;
- /* remove handlers referencing areas in old screen */
- for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
- WM_event_remove_area_handler(&win->modalhandlers, sa);
- }
+ BLI_addhead(&area->spacedata, slink);
+ BLI_listbase_clear(&slink->regionbase);
- /* we put timer to sleep, so screen_exit has to think there's no timer */
- oldscreen->animtimer = NULL;
- if (wt) {
- WM_event_timer_sleep(wm, win, wt, true);
- }
+ /* Data specific to global areas. */
+ area->global = MEM_callocN(sizeof(*area->global), __func__);
+ area->global->size_max = height_max;
+ area->global->size_min = height_min;
+ area->global->align = align;
+ }
- ED_screen_exit(C, win, oldscreen);
+ if (area->global->cur_fixed_height != height_cur) {
+ /* Refresh layout if size changes. */
+ area->global->cur_fixed_height = height_cur;
+ screen->do_refresh = true;
+ }
+}
- /* Same scene, "transfer" playback to new screen. */
- if (wt) {
- if (oldscene == sc->scene) {
- sc->animtimer = wt;
+static void screen_global_topbar_area_refresh(wmWindow *win, bScreen *screen)
+{
+ const short size_min = HEADERY;
+ const short size_max = 2.25 * HEADERY;
+ const short size = (screen->flag & SCREEN_COLLAPSE_TOPBAR) ? size_min : size_max;
+ 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_max;
+
+ screen_global_area_refresh(win, screen, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size, size_min, size_max);
+}
+
+static void screen_global_statusbar_area_refresh(wmWindow *win, bScreen *screen)
+{
+ const short size_min = 1;
+ const short size_max = 0.8f * HEADERY;
+ const short size = (screen->flag & SCREEN_COLLAPSE_STATUSBAR) ? size_min : size_max;
+ 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_max;
+
+ screen_global_area_refresh(win, screen, SPACE_STATUSBAR, GLOBAL_AREA_ALIGN_BOTTOM, &rect, size, size_min, size_max);
+}
+
+void ED_screen_global_areas_sync(wmWindow *win)
+{
+ /* Update screen flags from height in window, this is weak and perhaps
+ * global areas should just become part of the screen instead. */
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ screen->flag &= ~(SCREEN_COLLAPSE_STATUSBAR | SCREEN_COLLAPSE_TOPBAR);
+
+ for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ if (area->global->cur_fixed_height == area->global->size_min) {
+ if (area->spacetype == SPACE_TOPBAR) {
+ screen->flag |= SCREEN_COLLAPSE_TOPBAR;
}
- /* Else, stop playback. */
- else {
- oldscreen->animtimer = wt;
- ED_screen_animation_play(C, 0, 0);
+ else if (area->spacetype == SPACE_STATUSBAR) {
+ screen->flag |= SCREEN_COLLAPSE_STATUSBAR;
}
}
+ }
+}
- 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);
+void ED_screen_global_areas_refresh(wmWindow *win)
+{
+ /* Don't create global area for child and temporary windows. */
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ if ((win->parent != NULL) || screen->temp) {
+ if (win->global_areas.areabase.first) {
+ screen->do_refresh = true;
+ BKE_screen_area_map_free(&win->global_areas);
}
+ return;
+ }
+
+ screen_global_topbar_area_refresh(win, screen);
+ screen_global_statusbar_area_refresh(win, screen);
+}
- /* 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);
+
+/* -------------------------------------------------------------------- */
+/* 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 true;
+ return screen;
}
-static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
+/**
+ * \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)
{
- wmWindow *win;
+ /* validate screen, it's called with notifier reference */
+ if (BLI_findindex(&bmain->screen, screen_new) == -1) {
+ return NULL;
+ }
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen == sc) {
- return true;
+ if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
+ }
+
+ /* check for valid winid */
+ if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
+ return NULL;
+ }
+
+ if (screen_old != screen_new) {
+ wmTimer *wt = screen_old->animtimer;
+
+ /* remove handlers referencing areas in old screen */
+ for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) {
+ WM_event_remove_area_handler(&win->modalhandlers, sa);
}
- if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
- ScrArea *sa = win->screen->areabase.first;
- if (sa->full == sc) {
- return true;
- }
+ /* we put timer to sleep, so screen_exit has to think there's no timer */
+ screen_old->animtimer = NULL;
+ if (wt) {
+ WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
+ }
+ ED_screen_exit(C, win, screen_old);
+
+ /* Same scene, "transfer" playback to new screen. */
+ if (wt) {
+ screen_new->animtimer = wt;
}
+
+ return screen_new;
}
- return false;
+ return NULL;
}
-/* only call outside of area/region loops */
-bool ED_screen_delete(bContext *C, bScreen *sc)
+void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
{
- Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- bScreen *newsc;
+ 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);
- /* don't allow deleting temp fullscreens for now */
- if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
- return false;
- }
+ CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
- /* 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 */
+ ED_screen_refresh(CTX_wm_manager(C), win);
- for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
+ 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);
- if (!newsc) {
- for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
- }
+ /* makes button hilites work */
+ WM_event_add_mousemove(C);
+}
- if (!newsc) {
- return false;
- }
- ED_screen_set(C, newsc);
+/**
+ * \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);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen_old = CTX_wm_screen(C);
+ bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
+
+ 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);
- 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,104 +994,49 @@ 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_scene_change(bContext *C, wmWindow *win, Scene *scene)
{
- Main *bmain = CTX_data_main(C);
- bScreen *sc;
-
- if (screen == NULL)
- return;
+#if 0
+ ViewLayer *view_layer_old = WM_window_get_active_view_layer(win);
+#endif
- if (ed_screen_used(CTX_wm_manager(C), screen)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
+ /* Switch scene. */
+ win->scene = scene;
+ if (CTX_wm_window(C) == win) {
+ CTX_data_scene_set(C, scene);
}
- 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;
- }
+ /* Ensure the view layer name is updated. */
+ WM_window_ensure_active_view_layer(win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- }
+#if 0
+ /* Mode Syncing. */
+ if (view_layer_old) {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ Object *obact_new = OBACT(view_layer);
+ UNUSED_VARS(obact_new);
+ eObjectMode object_mode_old = workspace->object_mode;
+ Object *obact_old = OBACT(view_layer_old);
+ UNUSED_VARS(obact_old, object_mode_old);
}
+#endif
- // 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;
+ /* Update 3D view cameras. */
+ const bScreen *screen = WM_window_get_active_screen(win);
+ 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, view_layer, sa, v3d);
}
}
}
-
- 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;
-
- /* kill running jobs */
- wmWindowManager *wm = CTX_wm_manager(C);
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_ANY);
-
- 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) {
@@ -1481,18 +1044,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);
@@ -1575,6 +1127,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;
@@ -1591,16 +1144,19 @@ 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) {
+ 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;
+ sc->flag = oldscreen->flag;
/* find old area to restore from */
ScrArea *fullsa = NULL;
@@ -1612,10 +1168,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) {
@@ -1625,6 +1179,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;
@@ -1637,9 +1195,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.
@@ -1649,17 +1207,24 @@ 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;
+ sc->flag = oldscreen->flag;
/* timer */
sc->animtimer = oldscreen->animtimer;
@@ -1667,51 +1232,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, RGN_TYPE_NAV_BAR)) {
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 */
@@ -1798,7 +1347,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;
@@ -1846,13 +1395,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);
@@ -1861,19 +1407,16 @@ 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);
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
}
#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)
@@ -1894,11 +1437,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) {
@@ -1973,3 +1515,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;
+}