2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2008 Blender Foundation.
19 * All rights reserved.
22 * ***** END GPL LICENSE BLOCK *****
25 /** \file blender/editors/screen/screen_edit.c
34 #include "MEM_guardedalloc.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_userdef_types.h"
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
43 #include "BKE_context.h"
44 #include "BKE_depsgraph.h"
45 #include "BKE_image.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
48 #include "BKE_library_remap.h"
51 #include "BKE_screen.h"
52 #include "BKE_scene.h"
55 #include "BIF_glutil.h"
60 #include "ED_object.h"
61 #include "ED_screen.h"
62 #include "ED_screen_types.h"
65 #include "ED_render.h"
67 #include "UI_interface.h"
69 /* XXX actually should be not here... solve later */
70 #include "wm_subwindow.h"
72 #include "screen_intern.h" /* own module include */
75 /* ******************* screen vert, edge, area managing *********************** */
77 static ScrVert *screen_addvert(bScreen *sc, short x, short y)
79 ScrVert *sv = MEM_callocN(sizeof(ScrVert), "addscrvert");
83 BLI_addtail(&sc->vertbase, sv);
87 static void sortscrvert(ScrVert **v1, ScrVert **v2)
98 static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
100 ScrEdge *se = MEM_callocN(sizeof(ScrEdge), "addscredge");
102 sortscrvert(&v1, &v2);
106 BLI_addtail(&sc->edgebase, se);
111 ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
115 sortscrvert(&v1, &v2);
116 for (se = sc->edgebase.first; se; se = se->next)
117 if (se->v1 == v1 && se->v2 == v2)
123 void removedouble_scrverts(bScreen *sc)
129 verg = sc->vertbase.first;
131 if (verg->newv == NULL) { /* !!! */
134 if (v1->newv == NULL) { /* !?! */
135 if (v1->vec.x == verg->vec.x && v1->vec.y == verg->vec.y) {
136 /* printf("doublevert\n"); */
146 /* replace pointers in edges and faces */
147 se = sc->edgebase.first;
149 if (se->v1->newv) se->v1 = se->v1->newv;
150 if (se->v2->newv) se->v2 = se->v2->newv;
151 /* edges changed: so.... */
152 sortscrvert(&(se->v1), &(se->v2));
155 sa = sc->areabase.first;
157 if (sa->v1->newv) sa->v1 = sa->v1->newv;
158 if (sa->v2->newv) sa->v2 = sa->v2->newv;
159 if (sa->v3->newv) sa->v3 = sa->v3->newv;
160 if (sa->v4->newv) sa->v4 = sa->v4->newv;
165 verg = sc->vertbase.first;
169 BLI_remlink(&sc->vertbase, verg);
177 void removenotused_scrverts(bScreen *sc)
182 /* we assume edges are ok */
184 se = sc->edgebase.first;
191 sv = sc->vertbase.first;
195 BLI_remlink(&sc->vertbase, sv);
205 void removedouble_scredges(bScreen *sc)
207 ScrEdge *verg, *se, *sn;
210 verg = sc->edgebase.first;
215 if (verg->v1 == se->v1 && verg->v2 == se->v2) {
216 BLI_remlink(&sc->edgebase, se);
225 void removenotused_scredges(bScreen *sc)
231 /* sets flags when edge is used in area */
232 sa = sc->areabase.first;
234 se = screen_findedge(sc, sa->v1, sa->v2);
235 if (se == NULL) printf("error: area %d edge 1 doesn't exist\n", a);
237 se = screen_findedge(sc, sa->v2, sa->v3);
238 if (se == NULL) printf("error: area %d edge 2 doesn't exist\n", a);
240 se = screen_findedge(sc, sa->v3, sa->v4);
241 if (se == NULL) printf("error: area %d edge 3 doesn't exist\n", a);
243 se = screen_findedge(sc, sa->v4, sa->v1);
244 if (se == NULL) printf("error: area %d edge 4 doesn't exist\n", a);
249 se = sc->edgebase.first;
253 BLI_remlink(&sc->edgebase, se);
263 bool scredge_is_horizontal(ScrEdge *se)
265 return (se->v1->vec.y == se->v2->vec.y);
268 /* need win size to make sure not to include edges along screen edge */
269 ScrEdge *screen_find_active_scredge(bScreen *sc,
270 const int winsize_x, const int winsize_y,
271 const int mx, const int my)
274 int safety = U.widget_unit / 10;
276 if (safety < 2) safety = 2;
278 for (se = sc->edgebase.first; se; se = se->next) {
279 if (scredge_is_horizontal(se)) {
280 if (se->v1->vec.y > 0 && se->v1->vec.y < winsize_y - 1) {
282 min = MIN2(se->v1->vec.x, se->v2->vec.x);
283 max = MAX2(se->v1->vec.x, se->v2->vec.x);
285 if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
290 if (se->v1->vec.x > 0 && se->v1->vec.x < winsize_x - 1) {
292 min = MIN2(se->v1->vec.y, se->v2->vec.y);
293 max = MAX2(se->v1->vec.y, se->v2->vec.y);
295 if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
306 /* adds no space data */
307 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
309 ScrArea *sa = MEM_callocN(sizeof(ScrArea), "addscrarea");
314 sa->headertype = headertype;
315 sa->spacetype = sa->butspacetype = spacetype;
317 BLI_addtail(&sc->areabase, sa);
322 static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
327 BKE_screen_area_free(sa);
329 BLI_remlink(&sc->areabase, sa);
333 /* return 0: no split possible */
334 /* else return (integer) screencoordinate split point */
335 static short testsplitpoint(ScrArea *sa, char dir, float fac)
338 const short area_min_x = AREAMINX;
339 const short area_min_y = ED_area_headersize();
342 if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0;
343 if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0;
346 CLAMP(fac, 0.0f, 1.0f);
349 y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y);
351 if (y - sa->v1->vec.y < area_min_y)
352 y = sa->v1->vec.y + area_min_y;
353 else if (sa->v2->vec.y - y < area_min_y)
354 y = sa->v2->vec.y - area_min_y;
355 else y -= (y % AREAGRID);
360 x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x);
362 if (x - sa->v1->vec.x < area_min_x)
363 x = sa->v1->vec.x + area_min_x;
364 else if (sa->v4->vec.x - x < area_min_x)
365 x = sa->v4->vec.x - area_min_x;
366 else x -= (x % AREAGRID);
372 ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
374 ScrArea *newa = NULL;
378 if (sa == NULL) return NULL;
380 split = testsplitpoint(sa, dir, fac);
381 if (split == 0) return NULL;
383 /* note regarding (fac > 0.5f) checks below.
384 * normally it shouldn't matter which is used since the copy should match the original
385 * however with viewport rendering and python console this isn't the case. - campbell */
389 sv1 = screen_addvert(sc, sa->v1->vec.x, split);
390 sv2 = screen_addvert(sc, sa->v4->vec.x, split);
393 screen_addedge(sc, sa->v1, sv1);
394 screen_addedge(sc, sv1, sa->v2);
395 screen_addedge(sc, sa->v3, sv2);
396 screen_addedge(sc, sv2, sa->v4);
397 screen_addedge(sc, sv1, sv2);
401 newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
408 /* new areas: bottom */
409 newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->headertype, sa->spacetype);
416 ED_area_data_copy(newa, sa, true);
421 sv1 = screen_addvert(sc, split, sa->v1->vec.y);
422 sv2 = screen_addvert(sc, split, sa->v2->vec.y);
425 screen_addedge(sc, sa->v1, sv1);
426 screen_addedge(sc, sv1, sa->v4);
427 screen_addedge(sc, sa->v2, sv2);
428 screen_addedge(sc, sv2, sa->v3);
429 screen_addedge(sc, sv1, sv2);
432 /* new areas: right */
433 newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->headertype, sa->spacetype);
440 /* new areas: left */
441 newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
448 ED_area_data_copy(newa, sa, true);
451 /* remove double vertices en edges */
453 removedouble_scrverts(sc);
454 removedouble_scredges(sc);
455 removenotused_scredges(sc);
460 /* empty screen, with 1 dummy area without spacedata */
461 /* uses window size */
462 bScreen *ED_screen_add(Main *bmain, wmWindow *win, Scene *scene, const char *name)
464 const int winsize_x = WM_window_pixels_x(win);
465 const int winsize_y = WM_window_pixels_y(win);
468 ScrVert *sv1, *sv2, *sv3, *sv4;
470 sc = BKE_libblock_alloc(bmain, ID_SCR, name, 0);
472 sc->do_refresh = true;
473 sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
474 sc->winid = win->winid;
476 sv1 = screen_addvert(sc, 0, 0);
477 sv2 = screen_addvert(sc, 0, winsize_y - 1);
478 sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1);
479 sv4 = screen_addvert(sc, winsize_x - 1, 0);
481 screen_addedge(sc, sv1, sv2);
482 screen_addedge(sc, sv2, sv3);
483 screen_addedge(sc, sv3, sv4);
484 screen_addedge(sc, sv4, sv1);
486 /* dummy type, no spacedata */
487 screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY);
492 static void screen_copy(bScreen *to, bScreen *from)
498 /* free contents of 'to', is from blenkernel screen.c */
501 BLI_duplicatelist(&to->vertbase, &from->vertbase);
502 BLI_duplicatelist(&to->edgebase, &from->edgebase);
503 BLI_duplicatelist(&to->areabase, &from->areabase);
504 BLI_listbase_clear(&to->regionbase);
506 s2 = to->vertbase.first;
507 for (s1 = from->vertbase.first; s1; s1 = s1->next, s2 = s2->next) {
511 for (se = to->edgebase.first; se; se = se->next) {
512 se->v1 = se->v1->newv;
513 se->v2 = se->v2->newv;
514 sortscrvert(&(se->v1), &(se->v2));
517 saf = from->areabase.first;
518 for (sa = to->areabase.first; sa; sa = sa->next, saf = saf->next) {
519 sa->v1 = sa->v1->newv;
520 sa->v2 = sa->v2->newv;
521 sa->v3 = sa->v3->newv;
522 sa->v4 = sa->v4->newv;
524 BLI_listbase_clear(&sa->spacedata);
525 BLI_listbase_clear(&sa->regionbase);
526 BLI_listbase_clear(&sa->actionzones);
527 BLI_listbase_clear(&sa->handlers);
529 ED_area_data_copy(sa, saf, true);
532 /* put at zero (needed?) */
533 for (s1 = from->vertbase.first; s1; s1 = s1->next)
539 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
540 /* -1 = not valid check */
541 /* used with join operator */
542 int area_getorientation(ScrArea *sa, ScrArea *sb)
544 ScrVert *sav1, *sav2, *sav3, *sav4;
545 ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
547 if (sa == NULL || sb == NULL) return -1;
558 if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
561 else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */
564 else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */
567 else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
574 /* Helper function to join 2 areas, it has a return value, 0=failed 1=success
575 * used by the split, join operators
577 int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
581 dir = area_getorientation(sa1, sa2);
582 /*printf("dir is : %i\n", dir);*/
591 screen_addedge(scr, sa1->v2, sa1->v3);
592 screen_addedge(scr, sa1->v1, sa1->v4);
597 screen_addedge(scr, sa1->v1, sa1->v2);
598 screen_addedge(scr, sa1->v3, sa1->v4);
603 screen_addedge(scr, sa1->v2, sa1->v3);
604 screen_addedge(scr, sa1->v1, sa1->v4);
609 screen_addedge(scr, sa1->v1, sa1->v2);
610 screen_addedge(scr, sa1->v3, sa1->v4);
613 screen_delarea(C, scr, sa2);
614 removedouble_scrverts(scr);
619 void select_connected_scredge(bScreen *sc, ScrEdge *edge)
626 /* select connected, only in the right direction */
627 /* 'dir' is the direction of EDGE */
629 if (edge->v1->vec.x == edge->v2->vec.x) dir = 'v';
632 sv = sc->vertbase.first;
642 while (oneselected) {
643 se = sc->edgebase.first;
646 if (se->v1->flag + se->v2->flag == 1) {
648 if (se->v1->vec.y == se->v2->vec.y) {
649 se->v1->flag = se->v2->flag = 1;
654 if (se->v1->vec.x == se->v2->vec.x) {
655 se->v1->flag = se->v2->flag = 1;
665 /* test if screen vertices should be scaled */
666 static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
668 /* clamp Y size of header sized areas when expanding windows
669 * avoids annoying empty space around file menu */
670 #define USE_HEADER_SIZE_CLAMP
672 const int headery_init = ED_area_headersize();
675 int winsize_x_prev, winsize_y_prev;
676 float facx, facy, tempf, min[2], max[2];
679 min[0] = min[1] = 20000.0f;
680 max[0] = max[1] = 0.0f;
682 for (sv = sc->vertbase.first; sv; sv = sv->next) {
683 const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
684 minmax_v2v2_v2(min, max, fv);
687 /* always make 0.0 left under */
688 for (sv = sc->vertbase.first; sv; sv = sv->next) {
693 winsize_x_prev = (max[0] - min[0]) + 1;
694 winsize_y_prev = (max[1] - min[1]) + 1;
697 #ifdef USE_HEADER_SIZE_CLAMP
698 #define TEMP_BOTTOM 1
701 /* if the window's Y axis grows, clamp header sized areas */
702 if (winsize_y_prev < winsize_y) { /* growing? */
703 const int headery_margin_max = headery_init + 4;
704 for (sa = sc->areabase.first; sa; sa = sa->next) {
705 ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
708 if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
709 if (sa->v2->vec.y == winsize_y_prev - 1) {
710 if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
714 else if (sa->v1->vec.y == 0) {
715 if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
716 sa->temp = TEMP_BOTTOM;
725 if (winsize_x_prev != winsize_x || winsize_y_prev != winsize_y) {
726 facx = ((float)winsize_x - 1) / ((float)winsize_x_prev - 1);
727 facy = ((float)winsize_y - 1) / ((float)winsize_y_prev - 1);
729 /* make sure it fits! */
730 for (sv = sc->vertbase.first; sv; sv = sv->next) {
731 /* FIXME, this re-sizing logic is no good when re-sizing the window + redrawing [#24428]
732 * need some way to store these as floats internally and re-apply from there. */
733 tempf = ((float)sv->vec.x) * facx;
734 sv->vec.x = (short)(tempf + 0.5f);
735 //sv->vec.x += AREAGRID - 1;
736 //sv->vec.x -= (sv->vec.x % AREAGRID);
738 CLAMP(sv->vec.x, 0, winsize_x - 1);
740 tempf = ((float)sv->vec.y) * facy;
741 sv->vec.y = (short)(tempf + 0.5f);
742 //sv->vec.y += AREAGRID - 1;
743 //sv->vec.y -= (sv->vec.y % AREAGRID);
745 CLAMP(sv->vec.y, 0, winsize_y - 1);
750 #ifdef USE_HEADER_SIZE_CLAMP
751 if (winsize_y_prev < winsize_y) { /* growing? */
752 for (sa = sc->areabase.first; sa; sa = sa->next) {
758 if (sa->v1 == sa->v2)
761 /* adjust headery if verts are along the edge of window */
762 if (sa->temp == TEMP_TOP) {
764 const int yval = sa->v2->vec.y - headery_init;
765 se = screen_findedge(sc, sa->v4, sa->v1);
767 select_connected_scredge(sc, se);
769 for (sv = sc->vertbase.first; sv; sv = sv->next) {
770 if (sv != sa->v2 && sv != sa->v3) {
779 const int yval = sa->v1->vec.y + headery_init;
780 se = screen_findedge(sc, sa->v2, sa->v3);
782 select_connected_scredge(sc, se);
784 for (sv = sc->vertbase.first; sv; sv = sv->next) {
785 if (sv != sa->v1 && sv != sa->v4) {
795 #undef USE_HEADER_SIZE_CLAMP
801 /* test for collapsed areas. This could happen in some blender version... */
802 /* ton: removed option now, it needs Context... */
804 /* make each window at least ED_area_headersize() high */
805 for (sa = sc->areabase.first; sa; sa = sa->next) {
806 int headery = headery_init;
808 /* adjust headery if verts are along the edge of window */
809 if (sa->v1->vec.y > 0)
810 headery += U.pixelsize;
811 if (sa->v2->vec.y < winsize_y - 1)
812 headery += U.pixelsize;
814 if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) {
816 ScrEdge *se = screen_findedge(sc, sa->v4, sa->v1);
817 if (se && sa->v1 != sa->v2) {
820 select_connected_scredge(sc, se);
822 /* all selected vertices get the right offset */
823 yval = sa->v2->vec.y - headery + 1;
824 for (sv = sc->vertbase.first; sv; sv = sv->next) {
825 /* if is a collapsed area */
826 if (sv != sa->v2 && sv != sa->v3) {
838 /* ****************** EXPORTED API TO OTHER MODULES *************************** */
840 bScreen *ED_screen_duplicate(Main *bmain, wmWindow *win, bScreen *sc)
844 if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */
846 /* make new empty screen: */
847 newsc = ED_screen_add(bmain, win, sc->scene, sc->id.name + 2);
849 screen_copy(newsc, sc);
854 /* screen sets cursor based on swinid */
855 static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
857 for (ScrArea *sa = win->screen->areabase.first; sa; sa = sa->next) {
858 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
859 if (ar->swinid == swinid) {
860 if (swin_changed || (ar->type && ar->type->event_cursor)) {
861 ED_region_cursor_set(win, sa, ar);
869 void ED_screen_do_listen(bContext *C, wmNotifier *note)
871 wmWindow *win = CTX_wm_window(C);
874 switch (note->category) {
876 if (note->data == ND_FILEREAD)
877 win->screen->do_draw = true;
880 win->screen->do_draw = true;
883 if (note->action == NA_EDITED)
884 win->screen->do_draw = win->screen->do_refresh = true;
887 if (note->data == ND_MODE)
888 region_cursor_set(win, note->swinid, true);
893 /* helper call for below, dpi changes headers */
894 static void screen_refresh_headersizes(void)
896 const ListBase *lb = BKE_spacetypes_list();
899 for (st = lb->first; st; st = st->next) {
900 ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER);
901 if (art) art->prefsizey = ED_area_headersize();
905 /* make this screen usable */
906 /* for file read and first use, for scaling window, area moves */
907 void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
909 /* exception for bg mode, we only need the screen context */
911 const int winsize_x = WM_window_pixels_x(win);
912 const int winsize_y = WM_window_pixels_y(win);
917 winrct.xmax = winsize_x - 1;
919 winrct.ymax = winsize_y - 1;
921 /* header size depends on DPI, let's verify */
922 WM_window_set_dpi(win);
923 screen_refresh_headersizes();
925 screen_test_scale(win->screen, winsize_x, winsize_y);
927 if (win->screen->mainwin == 0) {
928 win->screen->mainwin = wm_subwindow_open(win, &winrct, false);
931 wm_subwindow_position(win, win->screen->mainwin, &winrct, false);
934 for (sa = win->screen->areabase.first; sa; sa = sa->next) {
935 /* set spacetype and region callbacks, calls init() */
936 /* sets subwindows for regions, adds handlers */
937 ED_area_initialize(wm, win, sa);
940 /* wake up animtimer */
941 if (win->screen->animtimer)
942 WM_event_timer_sleep(wm, win, win->screen->animtimer, false);
945 if (G.debug & G_DEBUG_EVENTS) {
946 printf("%s: set screen\n", __func__);
948 win->screen->do_refresh = false;
950 win->screen->context = ed_screen_context;
953 /* file read, set all screens, ... */
954 void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
958 for (win = wm->windows.first; win; win = win->next) {
960 if (win->screen == NULL)
961 win->screen = bmain->screen.first;
963 ED_screen_refresh(wm, win);
968 /* *********** exit calls are for closing running stuff ******** */
970 void ED_region_exit(bContext *C, ARegion *ar)
972 wmWindowManager *wm = CTX_wm_manager(C);
973 ARegion *prevar = CTX_wm_region(C);
975 if (ar->type && ar->type->exit)
976 ar->type->exit(wm, ar);
978 CTX_wm_region_set(C, ar);
979 WM_event_remove_handlers(C, &ar->handlers);
981 wm_subwindow_close(CTX_wm_window(C), ar->swinid);
986 MEM_freeN(ar->headerstr);
987 ar->headerstr = NULL;
990 if (ar->regiontimer) {
991 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
992 ar->regiontimer = NULL;
995 CTX_wm_region_set(C, prevar);
998 void ED_area_exit(bContext *C, ScrArea *sa)
1000 wmWindowManager *wm = CTX_wm_manager(C);
1001 ScrArea *prevsa = CTX_wm_area(C);
1004 if (sa->type && sa->type->exit)
1005 sa->type->exit(wm, sa);
1007 CTX_wm_area_set(C, sa);
1008 for (ar = sa->regionbase.first; ar; ar = ar->next)
1009 ED_region_exit(C, ar);
1011 WM_event_remove_handlers(C, &sa->handlers);
1012 CTX_wm_area_set(C, prevsa);
1015 void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
1017 wmWindowManager *wm = CTX_wm_manager(C);
1018 wmWindow *prevwin = CTX_wm_window(C);
1022 CTX_wm_window_set(C, window);
1024 if (screen->animtimer)
1025 WM_event_remove_timer(wm, window, screen->animtimer);
1026 screen->animtimer = NULL;
1027 screen->scrubbing = false;
1029 if (screen->mainwin)
1030 wm_subwindow_close(window, screen->mainwin);
1031 screen->mainwin = 0;
1032 screen->subwinactive = 0;
1034 for (ar = screen->regionbase.first; ar; ar = ar->next)
1035 ED_region_exit(C, ar);
1037 for (sa = screen->areabase.first; sa; sa = sa->next)
1038 ED_area_exit(C, sa);
1040 /* mark it available for use for other windows */
1043 if (prevwin->screen->temp == 0) {
1044 /* use previous window if possible */
1045 CTX_wm_window_set(C, prevwin);
1048 /* none otherwise */
1049 CTX_wm_window_set(C, NULL);
1054 /* *********************************** */
1056 /* case when on area-edge or in azones, or outside window */
1057 static void screen_cursor_set(wmWindow *win, const wmEvent *event)
1059 const int winsize_x = WM_window_pixels_x(win);
1060 const int winsize_y = WM_window_pixels_y(win);
1065 for (sa = win->screen->areabase.first; sa; sa = sa->next)
1066 if ((az = is_in_area_actionzone(sa, &event->x)))
1070 if (az->type == AZONE_AREA)
1071 WM_cursor_set(win, CURSOR_EDIT);
1072 else if (az->type == AZONE_REGION) {
1073 if (az->edge == AE_LEFT_TO_TOPRIGHT || az->edge == AE_RIGHT_TO_TOPLEFT)
1074 WM_cursor_set(win, CURSOR_X_MOVE);
1076 WM_cursor_set(win, CURSOR_Y_MOVE);
1080 ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y);
1083 if (scredge_is_horizontal(actedge))
1084 WM_cursor_set(win, CURSOR_Y_MOVE);
1086 WM_cursor_set(win, CURSOR_X_MOVE);
1089 WM_cursor_set(win, CURSOR_STD);
1094 /* called in wm_event_system.c. sets state vars in screen, cursors */
1095 /* event type is mouse move */
1096 void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
1098 wmWindow *win = CTX_wm_window(C);
1101 bScreen *scr = win->screen;
1104 int oldswin = scr->subwinactive;
1106 for (sa = scr->areabase.first; sa; sa = sa->next) {
1107 if (event->x > sa->totrct.xmin && event->x < sa->totrct.xmax)
1108 if (event->y > sa->totrct.ymin && event->y < sa->totrct.ymax)
1109 if (NULL == is_in_area_actionzone(sa, &event->x))
1113 /* make overlap active when mouse over */
1114 for (ar = sa->regionbase.first; ar; ar = ar->next) {
1115 if (BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
1116 scr->subwinactive = ar->swinid;
1122 scr->subwinactive = scr->mainwin;
1124 /* check for redraw headers */
1125 if (oldswin != scr->subwinactive) {
1127 for (sa = scr->areabase.first; sa; sa = sa->next) {
1128 bool do_draw = false;
1130 for (ar = sa->regionbase.first; ar; ar = ar->next)
1131 if (ar->swinid == oldswin || ar->swinid == scr->subwinactive)
1135 for (ar = sa->regionbase.first; ar; ar = ar->next)
1136 if (ar->regiontype == RGN_TYPE_HEADER)
1137 ED_region_tag_redraw(ar);
1142 /* cursors, for time being set always on edges, otherwise aregion doesnt switch */
1143 if (scr->subwinactive == scr->mainwin) {
1144 screen_cursor_set(win, event);
1147 /* notifier invokes freeing the buttons... causing a bit too much redraws */
1148 if (oldswin != scr->subwinactive) {
1149 region_cursor_set(win, scr->subwinactive, true);
1151 /* this used to be a notifier, but needs to be done immediate
1152 * because it can undo setting the right button as active due
1153 * to delayed notifier handling */
1154 UI_screen_free_active_but(C, win->screen);
1157 region_cursor_set(win, scr->subwinactive, false);
1162 int ED_screen_area_active(const bContext *C)
1164 wmWindow *win = CTX_wm_window(C);
1165 bScreen *sc = CTX_wm_screen(C);
1166 ScrArea *sa = CTX_wm_area(C);
1168 if (win && sc && sa) {
1169 AZone *az = is_in_area_actionzone(sa, &win->eventstate->x);
1172 if (az && az->type == AZONE_REGION)
1175 for (ar = sa->regionbase.first; ar; ar = ar->next)
1176 if (ar->swinid == sc->subwinactive)
1183 * operator call, WM + Window + screen already existed before
1185 * \warning Do NOT call in area/region queues!
1188 bool ED_screen_set(bContext *C, bScreen *sc)
1190 Main *bmain = CTX_data_main(C);
1191 wmWindowManager *wm = CTX_wm_manager(C);
1192 wmWindow *win = CTX_wm_window(C);
1193 bScreen *oldscreen = CTX_wm_screen(C);
1195 /* validate screen, it's called with notifier reference */
1196 if (BLI_findindex(&bmain->screen, sc) == -1) {
1200 if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
1201 /* find associated full */
1203 for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
1204 ScrArea *sa = sc1->areabase.first;
1205 if (sa->full == sc) {
1212 /* check for valid winid */
1213 if (sc->winid != 0 && sc->winid != win->winid) {
1217 if (oldscreen != sc) {
1218 wmTimer *wt = oldscreen->animtimer;
1220 Scene *oldscene = oldscreen->scene;
1222 /* remove handlers referencing areas in old screen */
1223 for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
1224 WM_event_remove_area_handler(&win->modalhandlers, sa);
1227 /* we put timer to sleep, so screen_exit has to think there's no timer */
1228 oldscreen->animtimer = NULL;
1230 WM_event_timer_sleep(wm, win, wt, true);
1233 ED_screen_exit(C, win, oldscreen);
1235 /* Same scene, "transfer" playback to new screen. */
1237 if (oldscene == sc->scene) {
1240 /* Else, stop playback. */
1242 oldscreen->animtimer = wt;
1243 ED_screen_animation_play(C, 0, 0);
1248 CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf
1250 /* prevent multiwin errors */
1251 sc->winid = win->winid;
1253 ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
1254 WM_event_add_notifier(C, NC_WINDOW, NULL);
1255 WM_event_add_notifier(C, NC_SCREEN | ND_SCREENSET, sc);
1257 /* makes button hilites work */
1258 WM_event_add_mousemove(C);
1260 /* Needed to make sure all the derivedMeshes are
1261 * up-to-date before viewport starts acquiring this.
1263 * This is needed in cases when, for example, boolean
1264 * modifier uses operant from invisible layer.
1265 * Without this trick boolean wouldn't apply correct.
1267 * Quite the same happens when setting screen's scene,
1268 * so perhaps this is in fact correct thing to do.
1270 if (oldscene != sc->scene) {
1271 BKE_scene_set_background(bmain, sc->scene);
1274 /* Always do visible update since it's possible new screen will
1275 * have different layers visible in 3D view-ports.
1276 * This is possible because of view3d.lock_camera_and_layers option.
1278 DAG_on_visible_update(bmain, false);
1284 static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
1288 for (win = wm->windows.first; win; win = win->next) {
1289 if (win->screen == sc) {
1293 if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
1294 ScrArea *sa = win->screen->areabase.first;
1295 if (sa->full == sc) {
1304 /* only call outside of area/region loops */
1305 bool ED_screen_delete(bContext *C, bScreen *sc)
1307 Main *bmain = CTX_data_main(C);
1308 wmWindowManager *wm = CTX_wm_manager(C);
1309 wmWindow *win = CTX_wm_window(C);
1312 /* don't allow deleting temp fullscreens for now */
1313 if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
1317 /* screen can only be in use by one window at a time, so as
1318 * long as we are able to find a screen that is unused, we
1319 * can safely assume ours is not in use anywhere an delete it */
1321 for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
1322 if (!ed_screen_used(wm, newsc) && !newsc->temp)
1326 for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
1327 if (!ed_screen_used(wm, newsc) && !newsc->temp)
1335 ED_screen_set(C, newsc);
1337 if (win->screen != sc) {
1338 BKE_libblock_free(bmain, sc);
1346 static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
1348 /* fix any cameras that are used in the 3d view but not in the scene */
1349 BKE_screen_view3d_sync(v3d, scene);
1351 if (!v3d->camera || !BKE_scene_base_find(scene, v3d->camera)) {
1352 v3d->camera = BKE_scene_camera_find(sc->scene);
1353 // XXX if (sc == curscreen) handle_view3d_lock();
1356 ListBase *regionbase;
1358 /* regionbase is in different place depending if space is active */
1359 if (v3d == sa->spacedata.first)
1360 regionbase = &sa->regionbase;
1362 regionbase = &v3d->regionbase;
1364 for (ar = regionbase->first; ar; ar = ar->next) {
1365 if (ar->regiontype == RGN_TYPE_WINDOW) {
1366 RegionView3D *rv3d = ar->regiondata;
1367 if (rv3d->persp == RV3D_CAMOB) {
1368 rv3d->persp = RV3D_PERSP;
1376 /* only call outside of area/region loops */
1377 void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
1379 Main *bmain = CTX_data_main(C);
1385 if (ed_screen_used(CTX_wm_manager(C), screen)) {
1386 ED_object_editmode_exit(C, EM_FREEDATA);
1389 for (sc = bmain->screen.first; sc; sc = sc->id.next) {
1390 if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
1392 if (scene != sc->scene) {
1393 /* all areas endlocalview */
1394 // XXX ScrArea *sa = sc->areabase.first;
1396 // endlocalview(sa);
1405 // copy_view3d_lock(0); /* space.c */
1407 /* are there cameras in the views that are not in the scene? */
1408 for (sc = bmain->screen.first; sc; sc = sc->id.next) {
1409 if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
1410 ScrArea *sa = sc->areabase.first;
1412 SpaceLink *sl = sa->spacedata.first;
1414 if (sl->spacetype == SPACE_VIEW3D) {
1415 View3D *v3d = (View3D *) sl;
1416 ed_screen_set_3dview_camera(scene, sc, sa, v3d);
1426 CTX_data_scene_set(C, scene);
1427 BKE_scene_set_background(bmain, scene);
1428 DAG_on_visible_update(bmain, false);
1430 ED_render_engine_changed(bmain);
1431 ED_update_for_newframe(bmain, scene, 1);
1433 /* complete redraw */
1434 WM_event_add_notifier(C, NC_WINDOW, NULL);
1439 * \note Only call outside of area/region loops
1440 * \return true if successful
1442 bool ED_screen_delete_scene(bContext *C, Scene *scene)
1444 Main *bmain = CTX_data_main(C);
1448 newscene = scene->id.prev;
1449 else if (scene->id.next)
1450 newscene = scene->id.next;
1454 ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
1456 BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
1458 id_us_clear_real(&scene->id);
1459 if (scene->id.us == 0) {
1460 BKE_libblock_free(bmain, scene);
1466 ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
1468 wmWindow *win = CTX_wm_window(C);
1469 bScreen *screen = CTX_wm_screen(C);
1470 ScrArea *newsa = NULL;
1472 if (!sa || sa->full == NULL) {
1473 newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
1477 if (sa->full && (screen->state == SCREENMAXIMIZED)) {
1478 /* if this has been called from the temporary info header generated in
1479 * temp fullscreen layouts, find the correct fullscreen area to change
1480 * to create a new space inside */
1481 for (newsa = screen->areabase.first; newsa; newsa = newsa->next) {
1482 if (!(sa->flag & AREA_TEMP_INFO))
1493 if (sa && (sa->spacetype != type)) {
1494 newsa->flag |= AREA_FLAG_TEMP_TYPE;
1497 newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
1500 ED_area_newspace(C, newsa, type, (newsa->flag & AREA_FLAG_TEMP_TYPE));
1506 * \a was_prev_temp for the case previous space was a temporary fullscreen as well
1508 void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
1510 BLI_assert(sa->full);
1512 if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
1513 /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
1514 ED_area_prevspace(C, sa);
1517 ED_screen_restore_temp_type(C, sa);
1521 void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
1523 /* incase nether functions below run */
1524 ED_area_tag_redraw(sa);
1526 if (sa->flag & AREA_FLAG_TEMP_TYPE) {
1527 ED_area_prevspace(C, sa);
1528 sa->flag &= ~AREA_FLAG_TEMP_TYPE;
1532 ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
1536 /* restore a screen / area back to default operation, after temp fullscreen modes */
1537 void ED_screen_full_restore(bContext *C, ScrArea *sa)
1539 wmWindow *win = CTX_wm_window(C);
1540 SpaceLink *sl = sa->spacedata.first;
1541 bScreen *screen = CTX_wm_screen(C);
1542 short state = (screen ? screen->state : SCREENMAXIMIZED);
1544 /* if fullscreen area has a temporary space (such as a file browser or fullscreen render
1545 * overlaid on top of an existing setup) then return to the previous space */
1548 if (sa->flag & AREA_FLAG_TEMP_TYPE) {
1549 ED_screen_full_prevspace(C, sa);
1552 ED_screen_state_toggle(C, win, sa, state);
1554 /* warning: 'sa' may be freed */
1556 /* otherwise just tile the area again */
1558 ED_screen_state_toggle(C, win, sa, state);
1563 * this function toggles: if area is maximized/full then the parent will be restored
1565 * \warning \a sa may be freed.
1567 ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state)
1569 Main *bmain = CTX_data_main(C);
1570 wmWindowManager *wm = CTX_wm_manager(C);
1571 bScreen *sc, *oldscreen;
1575 /* ensure we don't have a button active anymore, can crash when
1576 * switching screens with tooltip open because region and tooltip
1577 * are no longer in the same screen */
1578 for (ar = sa->regionbase.first; ar; ar = ar->next) {
1579 UI_blocklist_free(C, &ar->uiblocks);
1581 if (ar->regiontimer) {
1582 WM_event_remove_timer(wm, NULL, ar->regiontimer);
1583 ar->regiontimer = NULL;
1587 /* prevent hanging header prints */
1588 ED_area_headerprint(sa, NULL);
1591 if (sa && sa->full) {
1592 /* restoring back to SCREENNORMAL */
1593 sc = sa->full; /* the old screen to restore */
1594 oldscreen = win->screen; /* the one disappearing */
1596 sc->state = SCREENNORMAL;
1598 /* find old area to restore from */
1599 ScrArea *fullsa = NULL;
1600 for (ScrArea *old = sc->areabase.first; old; old = old->next) {
1601 /* area to restore from is always first */
1602 if (old->full && !fullsa) {
1606 /* clear full screen state */
1608 old->flag &= ~AREA_TEMP_INFO;
1611 sa->flag &= ~AREA_TEMP_INFO;
1614 if (fullsa == NULL) {
1615 if (G.debug & G_DEBUG)
1616 printf("%s: something wrong in areafullscreen\n", __func__);
1620 if (state == SCREENFULL) {
1621 /* restore the old side panels/header visibility */
1622 for (ar = sa->regionbase.first; ar; ar = ar->next) {
1623 ar->flag = ar->flagfullscreen;
1627 ED_area_data_swap(fullsa, sa);
1629 /* animtimer back */
1630 sc->animtimer = oldscreen->animtimer;
1631 oldscreen->animtimer = NULL;
1633 ED_screen_set(C, sc);
1635 BKE_libblock_free(CTX_data_main(C), oldscreen);
1637 /* After we've restored back to SCREENNORMAL, we have to wait with
1638 * screen handling as it uses the area coords which aren't updated yet.
1639 * Without doing so, the screen handling gets wrong area coords,
1640 * which in worst case can lead to crashes (see T43139) */
1641 sc->skip_handling = true;
1644 /* change from SCREENNORMAL to new state */
1646 char newname[MAX_ID_NAME - 2];
1648 oldscreen = win->screen;
1650 oldscreen->state = state;
1651 BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
1652 sc = ED_screen_add(bmain, win, oldscreen->scene, newname);
1654 sc->redraws_flag = oldscreen->redraws_flag;
1655 sc->temp = oldscreen->temp;
1658 sc->animtimer = oldscreen->animtimer;
1659 oldscreen->animtimer = NULL;
1661 /* use random area when we have no active one, e.g. when the
1662 * mouse is outside of the window and we open a file browser */
1664 sa = oldscreen->areabase.first;
1666 if (state == SCREENMAXIMIZED) {
1667 /* returns the top small area */
1668 newa = area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1);
1669 ED_area_newspace(C, newa, SPACE_INFO, false);
1673 ED_area_data_swap(newa, sa);
1674 sa->flag |= AREA_TEMP_INFO;
1676 sa->full = oldscreen;
1677 newa->full = oldscreen;
1678 newa->next->full = oldscreen; // XXX
1680 else if (state == SCREENFULL) {
1681 newa = (ScrArea *)sc->areabase.first;
1684 ED_area_data_swap(newa, sa);
1685 newa->flag = sa->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
1687 /* temporarily hide the side panels/header */
1688 for (ar = newa->regionbase.first; ar; ar = ar->next) {
1689 ar->flagfullscreen = ar->flag;
1691 if (ELEM(ar->regiontype,
1696 ar->flag |= RGN_FLAG_HIDDEN;
1700 sa->full = oldscreen;
1701 newa->full = oldscreen;
1707 ED_screen_set(C, sc);
1710 /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
1711 CTX_wm_area_set(C, sc->areabase.first);
1713 return sc->areabase.first;
1716 /* update frame rate info for viewport drawing */
1717 void ED_refresh_viewport_fps(bContext *C)
1719 wmTimer *animtimer = CTX_wm_screen(C)->animtimer;
1720 Scene *scene = CTX_data_scene(C);
1722 /* is anim playback running? */
1723 if (animtimer && (U.uiflag & USER_SHOW_FPS)) {
1724 ScreenFrameRateInfo *fpsi = scene->fps_info;
1726 /* if there isn't any info, init it first */
1728 fpsi = scene->fps_info = MEM_callocN(sizeof(ScreenFrameRateInfo), "refresh_viewport_fps fps_info");
1730 /* update the values */
1731 fpsi->redrawtime = fpsi->lredrawtime;
1732 fpsi->lredrawtime = animtimer->ltime;
1735 /* playback stopped or shouldn't be running */
1736 if (scene->fps_info)
1737 MEM_freeN(scene->fps_info);
1738 scene->fps_info = NULL;
1742 /* redraws: uses defines from stime->redraws
1743 * enable: 1 - forward on, -1 - backwards on, 0 - off
1745 void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable)
1747 bScreen *screen = CTX_wm_screen(C);
1748 wmWindowManager *wm = CTX_wm_manager(C);
1749 wmWindow *win = CTX_wm_window(C);
1750 Scene *scene = CTX_data_scene(C);
1751 bScreen *stopscreen = ED_screen_animation_playing(wm);
1754 WM_event_remove_timer(wm, win, stopscreen->animtimer);
1755 stopscreen->animtimer = NULL;
1759 ScreenAnimData *sad = MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData");
1761 screen->animtimer = WM_event_add_timer(wm, win, TIMER0, (1.0 / FPS));
1763 sad->ar = CTX_wm_region(C);
1764 /* if startframe is larger than current frame, we put currentframe on startframe.
1765 * note: first frame then is not drawn! (ton) */
1767 if (scene->r.psfra > scene->r.cfra) {
1768 sad->sfra = scene->r.cfra;
1769 scene->r.cfra = scene->r.psfra;
1772 sad->sfra = scene->r.cfra;
1775 if (scene->r.sfra > scene->r.cfra) {
1776 sad->sfra = scene->r.cfra;
1777 scene->r.cfra = scene->r.sfra;
1780 sad->sfra = scene->r.cfra;
1782 sad->redraws = redraws;
1783 sad->refresh = refresh;
1784 sad->flag |= (enable < 0) ? ANIMPLAY_FLAG_REVERSE : 0;
1785 sad->flag |= (sync == 0) ? ANIMPLAY_FLAG_NO_SYNC : (sync == 1) ? ANIMPLAY_FLAG_SYNC : 0;
1787 ScrArea *sa = CTX_wm_area(C);
1789 char spacetype = -1;
1792 spacetype = sa->spacetype;
1794 sad->from_anim_edit = (ELEM(spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA, SPACE_TIME));
1796 screen->animtimer->customdata = sad;
1800 /* notifier catched by top header, for button */
1801 WM_event_add_notifier(C, NC_SCREEN | ND_ANIMPLAY, NULL);
1804 /* helper for screen_animation_play() - only to be used for TimeLine */
1805 static ARegion *time_top_left_3dwindow(bScreen *screen)
1807 ARegion *aret = NULL;
1811 for (sa = screen->areabase.first; sa; sa = sa->next) {
1812 if (sa->spacetype == SPACE_VIEW3D) {
1814 for (ar = sa->regionbase.first; ar; ar = ar->next) {
1815 if (ar->regiontype == RGN_TYPE_WINDOW) {
1816 if (ar->winrct.xmin - ar->winrct.ymin < min) {
1818 min = ar->winrct.xmin - ar->winrct.ymin;
1828 void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
1830 if (screen && screen->animtimer) {
1831 wmTimer *wt = screen->animtimer;
1832 ScreenAnimData *sad = wt->customdata;
1834 sad->redraws = redraws;
1835 sad->refresh = refresh;
1837 if (redraws & TIME_REGION)
1838 sad->ar = time_top_left_3dwindow(screen);
1842 /* results in fully updated anim system
1843 * screen can be NULL */
1844 void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
1846 wmWindowManager *wm = bmain->wm.first;
1850 #ifdef DURIAN_CAMERA_SWITCH
1851 void *camera = BKE_scene_camera_switch_find(scene);
1852 if (camera && scene->camera != camera) {
1854 scene->camera = camera;
1855 /* are there cameras in the views that are not in the scene? */
1856 for (sc = bmain->screen.first; sc; sc = sc->id.next) {
1857 BKE_screen_view3d_scene_sync(sc);
1862 ED_clip_update_frame(bmain, scene->r.cfra);
1864 /* get layers from all windows */
1865 for (window = wm->windows.first; window; window = window->next)
1866 layers |= BKE_screen_visible_layers(window->screen, scene);
1868 /* this function applies the changes too */
1869 BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers);
1872 if (scene->use_nodes && scene->nodetree)
1873 ntreeCompositTagAnimated(scene->nodetree);
1875 /* update animated texture nodes */
1878 for (tex = bmain->tex.first; tex; tex = tex->id.next) {
1879 if (tex->use_nodes && tex->nodetree) {
1880 ntreeTexTagAnimated(tex->nodetree);
1888 * return true if any active area requires to see in 3D
1890 bool ED_screen_stereo3d_required(bScreen *screen)
1893 Scene *sce = screen->scene;
1894 const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
1896 for (sa = screen->areabase.first; sa; sa = sa->next) {
1897 switch (sa->spacetype) {
1905 v3d = sa->spacedata.first;
1906 if (v3d->camera && v3d->stereo3d_camera == STEREO_3D_ID) {
1908 for (ar = sa->regionbase.first; ar; ar = ar->next) {
1909 if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
1910 RegionView3D *rv3d = ar->regiondata;
1911 if (rv3d->persp == RV3D_CAMOB) {
1923 /* images should always show in stereo, even if
1924 * the file doesn't have views enabled */
1925 sima = sa->spacedata.first;
1926 if (sima->image && BKE_image_is_stereo(sima->image) &&
1927 (sima->iuser.flag & IMA_SHOW_STEREO))
1940 snode = sa->spacedata.first;
1941 if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
1953 sseq = sa->spacedata.first;
1954 if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
1958 if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {