Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2008 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00030 #include <string.h> 00031 #include <math.h> 00032 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "DNA_scene_types.h" 00037 #include "DNA_userdef_types.h" 00038 00039 #include "BLI_blenlib.h" 00040 #include "BLI_utildefines.h" 00041 00042 #include "BKE_context.h" 00043 #include "BKE_global.h" 00044 #include "BKE_library.h" 00045 #include "BKE_main.h" 00046 #include "BKE_node.h" 00047 #include "BKE_screen.h" 00048 #include "BKE_scene.h" 00049 00050 #include "BIF_gl.h" 00051 #include "BIF_glutil.h" 00052 00053 #include "WM_api.h" 00054 #include "WM_types.h" 00055 00056 #include "ED_image.h" 00057 #include "ED_object.h" 00058 #include "ED_screen.h" 00059 #include "ED_screen_types.h" 00060 #include "ED_fileselect.h" 00061 #include "ED_clip.h" 00062 #include "ED_render.h" 00063 00064 #include "UI_interface.h" 00065 00066 /* XXX actually should be not here... solve later */ 00067 #include "wm_subwindow.h" 00068 00069 #include "screen_intern.h" /* own module include */ 00070 00071 00072 /* ******************* screen vert, edge, area managing *********************** */ 00073 00074 static ScrVert *screen_addvert(bScreen *sc, short x, short y) 00075 { 00076 ScrVert *sv= MEM_callocN(sizeof(ScrVert), "addscrvert"); 00077 sv->vec.x= x; 00078 sv->vec.y= y; 00079 00080 BLI_addtail(&sc->vertbase, sv); 00081 return sv; 00082 } 00083 00084 static void sortscrvert(ScrVert **v1, ScrVert **v2) 00085 { 00086 ScrVert *tmp; 00087 00088 if (*v1 > *v2) { 00089 tmp= *v1; 00090 *v1= *v2; 00091 *v2= tmp; 00092 } 00093 } 00094 00095 static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2) 00096 { 00097 ScrEdge *se= MEM_callocN(sizeof(ScrEdge), "addscredge"); 00098 00099 sortscrvert(&v1, &v2); 00100 se->v1= v1; 00101 se->v2= v2; 00102 00103 BLI_addtail(&sc->edgebase, se); 00104 return se; 00105 } 00106 00107 00108 ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2) 00109 { 00110 ScrEdge *se; 00111 00112 sortscrvert(&v1, &v2); 00113 for (se= sc->edgebase.first; se; se= se->next) 00114 if(se->v1==v1 && se->v2==v2) 00115 return se; 00116 00117 return NULL; 00118 } 00119 00120 void removedouble_scrverts(bScreen *sc) 00121 { 00122 ScrVert *v1, *verg; 00123 ScrEdge *se; 00124 ScrArea *sa; 00125 00126 verg= sc->vertbase.first; 00127 while(verg) { 00128 if(verg->newv==NULL) { /* !!! */ 00129 v1= verg->next; 00130 while(v1) { 00131 if(v1->newv==NULL) { /* !?! */ 00132 if(v1->vec.x==verg->vec.x && v1->vec.y==verg->vec.y) { 00133 /* printf("doublevert\n"); */ 00134 v1->newv= verg; 00135 } 00136 } 00137 v1= v1->next; 00138 } 00139 } 00140 verg= verg->next; 00141 } 00142 00143 /* replace pointers in edges and faces */ 00144 se= sc->edgebase.first; 00145 while(se) { 00146 if(se->v1->newv) se->v1= se->v1->newv; 00147 if(se->v2->newv) se->v2= se->v2->newv; 00148 /* edges changed: so.... */ 00149 sortscrvert(&(se->v1), &(se->v2)); 00150 se= se->next; 00151 } 00152 sa= sc->areabase.first; 00153 while(sa) { 00154 if(sa->v1->newv) sa->v1= sa->v1->newv; 00155 if(sa->v2->newv) sa->v2= sa->v2->newv; 00156 if(sa->v3->newv) sa->v3= sa->v3->newv; 00157 if(sa->v4->newv) sa->v4= sa->v4->newv; 00158 sa= sa->next; 00159 } 00160 00161 /* remove */ 00162 verg= sc->vertbase.first; 00163 while(verg) { 00164 v1= verg->next; 00165 if(verg->newv) { 00166 BLI_remlink(&sc->vertbase, verg); 00167 MEM_freeN(verg); 00168 } 00169 verg= v1; 00170 } 00171 00172 } 00173 00174 void removenotused_scrverts(bScreen *sc) 00175 { 00176 ScrVert *sv, *svn; 00177 ScrEdge *se; 00178 00179 /* we assume edges are ok */ 00180 00181 se= sc->edgebase.first; 00182 while(se) { 00183 se->v1->flag= 1; 00184 se->v2->flag= 1; 00185 se= se->next; 00186 } 00187 00188 sv= sc->vertbase.first; 00189 while(sv) { 00190 svn= sv->next; 00191 if(sv->flag==0) { 00192 BLI_remlink(&sc->vertbase, sv); 00193 MEM_freeN(sv); 00194 } 00195 else sv->flag= 0; 00196 sv= svn; 00197 } 00198 } 00199 00200 void removedouble_scredges(bScreen *sc) 00201 { 00202 ScrEdge *verg, *se, *sn; 00203 00204 /* compare */ 00205 verg= sc->edgebase.first; 00206 while(verg) { 00207 se= verg->next; 00208 while(se) { 00209 sn= se->next; 00210 if(verg->v1==se->v1 && verg->v2==se->v2) { 00211 BLI_remlink(&sc->edgebase, se); 00212 MEM_freeN(se); 00213 } 00214 se= sn; 00215 } 00216 verg= verg->next; 00217 } 00218 } 00219 00220 void removenotused_scredges(bScreen *sc) 00221 { 00222 ScrEdge *se, *sen; 00223 ScrArea *sa; 00224 int a=0; 00225 00226 /* sets flags when edge is used in area */ 00227 sa= sc->areabase.first; 00228 while(sa) { 00229 se= screen_findedge(sc, sa->v1, sa->v2); 00230 if(se==NULL) printf("error: area %d edge 1 doesn't exist\n", a); 00231 else se->flag= 1; 00232 se= screen_findedge(sc, sa->v2, sa->v3); 00233 if(se==NULL) printf("error: area %d edge 2 doesn't exist\n", a); 00234 else se->flag= 1; 00235 se= screen_findedge(sc, sa->v3, sa->v4); 00236 if(se==NULL) printf("error: area %d edge 3 doesn't exist\n", a); 00237 else se->flag= 1; 00238 se= screen_findedge(sc, sa->v4, sa->v1); 00239 if(se==NULL) printf("error: area %d edge 4 doesn't exist\n", a); 00240 else se->flag= 1; 00241 sa= sa->next; 00242 a++; 00243 } 00244 se= sc->edgebase.first; 00245 while(se) { 00246 sen= se->next; 00247 if(se->flag==0) { 00248 BLI_remlink(&sc->edgebase, se); 00249 MEM_freeN(se); 00250 } 00251 else se->flag= 0; 00252 se= sen; 00253 } 00254 } 00255 00256 int scredge_is_horizontal(ScrEdge *se) 00257 { 00258 return (se->v1->vec.y == se->v2->vec.y); 00259 } 00260 00261 ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my) 00262 { 00263 ScrEdge *se; 00264 00265 for (se= sc->edgebase.first; se; se= se->next) { 00266 if (scredge_is_horizontal(se)) { 00267 short min, max; 00268 min= MIN2(se->v1->vec.x, se->v2->vec.x); 00269 max= MAX2(se->v1->vec.x, se->v2->vec.x); 00270 00271 if (abs(my-se->v1->vec.y)<=2 && mx>=min && mx<=max) 00272 return se; 00273 } 00274 else { 00275 short min, max; 00276 min= MIN2(se->v1->vec.y, se->v2->vec.y); 00277 max= MAX2(se->v1->vec.y, se->v2->vec.y); 00278 00279 if (abs(mx-se->v1->vec.x)<=2 && my>=min && my<=max) 00280 return se; 00281 } 00282 } 00283 00284 return NULL; 00285 } 00286 00287 00288 00289 /* adds no space data */ 00290 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype) 00291 { 00292 ScrArea *sa= MEM_callocN(sizeof(ScrArea), "addscrarea"); 00293 sa->v1= v1; 00294 sa->v2= v2; 00295 sa->v3= v3; 00296 sa->v4= v4; 00297 sa->headertype= headertype; 00298 sa->spacetype= sa->butspacetype= spacetype; 00299 00300 BLI_addtail(&sc->areabase, sa); 00301 00302 return sa; 00303 } 00304 00305 static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa) 00306 { 00307 00308 ED_area_exit(C, sa); 00309 00310 BKE_screen_area_free(sa); 00311 00312 BLI_remlink(&sc->areabase, sa); 00313 MEM_freeN(sa); 00314 } 00315 00316 /* return 0: no split possible */ 00317 /* else return (integer) screencoordinate split point */ 00318 static short testsplitpoint(ScrArea *sa, char dir, float fac) 00319 { 00320 short x, y; 00321 00322 // area big enough? 00323 if(dir=='v' && (sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX)) return 0; 00324 if(dir=='h' && (sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY)) return 0; 00325 00326 // to be sure 00327 CLAMP(fac, 0.0f, 1.0f); 00328 00329 if(dir=='h') { 00330 y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y); 00331 00332 if(y- sa->v1->vec.y < AREAMINY) 00333 y= sa->v1->vec.y+ AREAMINY; 00334 else if(sa->v2->vec.y- y < AREAMINY) 00335 y= sa->v2->vec.y- AREAMINY; 00336 else y-= (y % AREAGRID); 00337 00338 return y; 00339 } 00340 else { 00341 x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x); 00342 00343 if(x- sa->v1->vec.x < AREAMINX) 00344 x= sa->v1->vec.x+ AREAMINX; 00345 else if(sa->v4->vec.x- x < AREAMINX) 00346 x= sa->v4->vec.x- AREAMINX; 00347 else x-= (x % AREAGRID); 00348 00349 return x; 00350 } 00351 } 00352 00353 ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge) 00354 { 00355 ScrArea *newa=NULL; 00356 ScrVert *sv1, *sv2; 00357 short split; 00358 00359 if(sa==NULL) return NULL; 00360 00361 split= testsplitpoint(sa, dir, fac); 00362 if(split==0) return NULL; 00363 00364 if(dir=='h') { 00365 /* new vertices */ 00366 sv1= screen_addvert(sc, sa->v1->vec.x, split); 00367 sv2= screen_addvert(sc, sa->v4->vec.x, split); 00368 00369 /* new edges */ 00370 screen_addedge(sc, sa->v1, sv1); 00371 screen_addedge(sc, sv1, sa->v2); 00372 screen_addedge(sc, sa->v3, sv2); 00373 screen_addedge(sc, sv2, sa->v4); 00374 screen_addedge(sc, sv1, sv2); 00375 00376 /* new areas: top */ 00377 newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype); 00378 area_copy_data(newa, sa, 0); 00379 00380 /* area below */ 00381 sa->v2= sv1; 00382 sa->v3= sv2; 00383 00384 } 00385 else { 00386 /* new vertices */ 00387 sv1= screen_addvert(sc, split, sa->v1->vec.y); 00388 sv2= screen_addvert(sc, split, sa->v2->vec.y); 00389 00390 /* new edges */ 00391 screen_addedge(sc, sa->v1, sv1); 00392 screen_addedge(sc, sv1, sa->v4); 00393 screen_addedge(sc, sa->v2, sv2); 00394 screen_addedge(sc, sv2, sa->v3); 00395 screen_addedge(sc, sv1, sv2); 00396 00397 /* new areas: left */ 00398 newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype); 00399 area_copy_data(newa, sa, 0); 00400 00401 /* area right */ 00402 sa->v1= sv1; 00403 sa->v2= sv2; 00404 } 00405 00406 /* remove double vertices en edges */ 00407 if(merge) 00408 removedouble_scrverts(sc); 00409 removedouble_scredges(sc); 00410 removenotused_scredges(sc); 00411 00412 return newa; 00413 } 00414 00415 /* empty screen, with 1 dummy area without spacedata */ 00416 /* uses window size */ 00417 bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name) 00418 { 00419 bScreen *sc; 00420 ScrVert *sv1, *sv2, *sv3, *sv4; 00421 00422 sc= alloc_libblock(&G.main->screen, ID_SCR, name); 00423 sc->scene= scene; 00424 sc->do_refresh= 1; 00425 sc->redraws_flag= TIME_ALL_3D_WIN|TIME_ALL_ANIM_WIN; 00426 sc->winid= win->winid; 00427 00428 sv1= screen_addvert(sc, 0, 0); 00429 sv2= screen_addvert(sc, 0, win->sizey-1); 00430 sv3= screen_addvert(sc, win->sizex-1, win->sizey-1); 00431 sv4= screen_addvert(sc, win->sizex-1, 0); 00432 00433 screen_addedge(sc, sv1, sv2); 00434 screen_addedge(sc, sv2, sv3); 00435 screen_addedge(sc, sv3, sv4); 00436 screen_addedge(sc, sv4, sv1); 00437 00438 /* dummy type, no spacedata */ 00439 screen_addarea(sc, sv1, sv2, sv3, sv4, HEADERDOWN, SPACE_EMPTY); 00440 00441 return sc; 00442 } 00443 00444 static void screen_copy(bScreen *to, bScreen *from) 00445 { 00446 ScrVert *s1, *s2; 00447 ScrEdge *se; 00448 ScrArea *sa, *saf; 00449 00450 /* free contents of 'to', is from blenkernel screen.c */ 00451 free_screen(to); 00452 00453 BLI_duplicatelist(&to->vertbase, &from->vertbase); 00454 BLI_duplicatelist(&to->edgebase, &from->edgebase); 00455 BLI_duplicatelist(&to->areabase, &from->areabase); 00456 to->regionbase.first= to->regionbase.last= NULL; 00457 00458 s2= to->vertbase.first; 00459 for(s1= from->vertbase.first; s1; s1= s1->next, s2= s2->next) { 00460 s1->newv= s2; 00461 } 00462 00463 for(se= to->edgebase.first; se; se= se->next) { 00464 se->v1= se->v1->newv; 00465 se->v2= se->v2->newv; 00466 sortscrvert(&(se->v1), &(se->v2)); 00467 } 00468 00469 saf= from->areabase.first; 00470 for(sa= to->areabase.first; sa; sa= sa->next, saf= saf->next) { 00471 sa->v1= sa->v1->newv; 00472 sa->v2= sa->v2->newv; 00473 sa->v3= sa->v3->newv; 00474 sa->v4= sa->v4->newv; 00475 00476 sa->spacedata.first= sa->spacedata.last= NULL; 00477 sa->regionbase.first= sa->regionbase.last= NULL; 00478 sa->actionzones.first= sa->actionzones.last= NULL; 00479 sa->handlers.first= sa->handlers.last= NULL; 00480 00481 area_copy_data(sa, saf, 0); 00482 } 00483 00484 /* put at zero (needed?) */ 00485 for(s1= from->vertbase.first; s1; s1= s1->next) 00486 s1->newv= NULL; 00487 00488 } 00489 00490 00491 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */ 00492 /* -1 = not valid check */ 00493 /* used with join operator */ 00494 int area_getorientation(ScrArea *sa, ScrArea *sb) 00495 { 00496 ScrVert *sav1, *sav2, *sav3, *sav4; 00497 ScrVert *sbv1, *sbv2, *sbv3, *sbv4; 00498 00499 if(sa==NULL || sb==NULL) return -1; 00500 00501 sav1= sa->v1; 00502 sav2= sa->v2; 00503 sav3= sa->v3; 00504 sav4= sa->v4; 00505 sbv1= sb->v1; 00506 sbv2= sb->v2; 00507 sbv3= sb->v3; 00508 sbv4= sb->v4; 00509 00510 if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */ 00511 return 0; 00512 } 00513 else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */ 00514 return 1; 00515 } 00516 else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */ 00517 return 2; 00518 } 00519 else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/ 00520 return 3; 00521 } 00522 00523 return -1; 00524 } 00525 00526 /* Helper function to join 2 areas, it has a return value, 0=failed 1=success 00527 * used by the split, join operators 00528 */ 00529 int screen_area_join(bContext *C, bScreen* scr, ScrArea *sa1, ScrArea *sa2) 00530 { 00531 int dir; 00532 00533 dir = area_getorientation(sa1, sa2); 00534 /*printf("dir is : %i \n", dir);*/ 00535 00536 if (dir < 0) { 00537 if (sa1 ) sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 00538 if (sa2 ) sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 00539 return 0; 00540 } 00541 00542 if(dir == 0) { 00543 sa1->v1= sa2->v1; 00544 sa1->v2= sa2->v2; 00545 screen_addedge(scr, sa1->v2, sa1->v3); 00546 screen_addedge(scr, sa1->v1, sa1->v4); 00547 } 00548 else if(dir == 1) { 00549 sa1->v2= sa2->v2; 00550 sa1->v3= sa2->v3; 00551 screen_addedge(scr, sa1->v1, sa1->v2); 00552 screen_addedge(scr, sa1->v3, sa1->v4); 00553 } 00554 else if(dir == 2) { 00555 sa1->v3= sa2->v3; 00556 sa1->v4= sa2->v4; 00557 screen_addedge(scr, sa1->v2, sa1->v3); 00558 screen_addedge(scr, sa1->v1, sa1->v4); 00559 } 00560 else if(dir == 3) { 00561 sa1->v1= sa2->v1; 00562 sa1->v4= sa2->v4; 00563 screen_addedge(scr, sa1->v1, sa1->v2); 00564 screen_addedge(scr, sa1->v3, sa1->v4); 00565 } 00566 00567 screen_delarea(C, scr, sa2); 00568 removedouble_scrverts(scr); 00569 sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 00570 00571 return 1; 00572 } 00573 00574 void select_connected_scredge(bScreen *sc, ScrEdge *edge) 00575 { 00576 ScrEdge *se; 00577 ScrVert *sv; 00578 int oneselected; 00579 char dir; 00580 00581 /* select connected, only in the right direction */ 00582 /* 'dir' is the direction of EDGE */ 00583 00584 if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v'; 00585 else dir= 'h'; 00586 00587 sv= sc->vertbase.first; 00588 while(sv) { 00589 sv->flag = 0; 00590 sv= sv->next; 00591 } 00592 00593 edge->v1->flag= 1; 00594 edge->v2->flag= 1; 00595 00596 oneselected= 1; 00597 while(oneselected) { 00598 se= sc->edgebase.first; 00599 oneselected= 0; 00600 while(se) { 00601 if(se->v1->flag + se->v2->flag==1) { 00602 if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) { 00603 se->v1->flag= se->v2->flag= 1; 00604 oneselected= 1; 00605 } 00606 if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) { 00607 se->v1->flag= se->v2->flag= 1; 00608 oneselected= 1; 00609 } 00610 } 00611 se= se->next; 00612 } 00613 } 00614 } 00615 00616 /* test if screen vertices should be scaled */ 00617 static void screen_test_scale(bScreen *sc, int winsizex, int winsizey) 00618 { 00619 ScrVert *sv=NULL; 00620 ScrArea *sa; 00621 int sizex, sizey; 00622 float facx, facy, tempf, min[2], max[2]; 00623 00624 /* calculate size */ 00625 min[0]= min[1]= 10000.0f; 00626 max[0]= max[1]= 0.0f; 00627 00628 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00629 min[0]= MIN2(min[0], sv->vec.x); 00630 min[1]= MIN2(min[1], sv->vec.y); 00631 max[0]= MAX2(max[0], sv->vec.x); 00632 max[1]= MAX2(max[1], sv->vec.y); 00633 } 00634 00635 /* always make 0.0 left under */ 00636 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00637 sv->vec.x -= min[0]; 00638 sv->vec.y -= min[1]; 00639 } 00640 00641 sizex= max[0]-min[0]; 00642 sizey= max[1]-min[1]; 00643 00644 if(sizex!= winsizex || sizey!= winsizey) { 00645 facx= winsizex; 00646 facx/= (float)sizex; 00647 facy= winsizey; 00648 facy/= (float)sizey; 00649 00650 /* make sure it fits! */ 00651 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00652 /* FIXME, this resizing logic is no good when resizing the window + redrawing [#24428] 00653 * need some way to store these as floats internally and re-apply from there. */ 00654 tempf= ((float)sv->vec.x)*facx; 00655 sv->vec.x= (short)(tempf+0.5f); 00656 sv->vec.x+= AREAGRID-1; 00657 sv->vec.x-= (sv->vec.x % AREAGRID); 00658 00659 CLAMP(sv->vec.x, 0, winsizex); 00660 00661 tempf= ((float)sv->vec.y)*facy; 00662 sv->vec.y= (short)(tempf+0.5f); 00663 sv->vec.y+= AREAGRID-1; 00664 sv->vec.y-= (sv->vec.y % AREAGRID); 00665 00666 CLAMP(sv->vec.y, 0, winsizey); 00667 } 00668 } 00669 00670 /* test for collapsed areas. This could happen in some blender version... */ 00671 /* ton: removed option now, it needs Context... */ 00672 00673 /* make each window at least ED_area_headersize() high */ 00674 for(sa= sc->areabase.first; sa; sa= sa->next) { 00675 int headery= ED_area_headersize()+1; 00676 00677 if(sa->v1->vec.y+headery > sa->v2->vec.y) { 00678 /* lower edge */ 00679 ScrEdge *se= screen_findedge(sc, sa->v4, sa->v1); 00680 if(se && sa->v1!=sa->v2 ) { 00681 int yval; 00682 00683 select_connected_scredge(sc, se); 00684 00685 /* all selected vertices get the right offset */ 00686 yval= sa->v2->vec.y-headery; 00687 sv= sc->vertbase.first; 00688 while(sv) { 00689 /* if is a collapsed area */ 00690 if(sv!=sa->v2 && sv!=sa->v3) { 00691 if(sv->flag) sv->vec.y= yval; 00692 } 00693 sv= sv->next; 00694 } 00695 } 00696 } 00697 } 00698 00699 } 00700 00701 /* *********************** DRAWING **************************************** */ 00702 00703 00704 #define SCR_BACK 0.55 00705 #define SCR_ROUND 12 00706 00707 /* draw vertical shape visualising future joining (left as well 00708 * right direction of future joining) */ 00709 static void draw_horizontal_join_shape(ScrArea *sa, char dir) 00710 { 00711 vec2f points[10]; 00712 short i; 00713 float w, h; 00714 float width = sa->v3->vec.x - sa->v1->vec.x; 00715 float height = sa->v3->vec.y - sa->v1->vec.y; 00716 00717 if(height<width) { 00718 h = height/8; 00719 w = height/4; 00720 } 00721 else { 00722 h = width/8; 00723 w = width/4; 00724 } 00725 00726 points[0].x = sa->v1->vec.x; 00727 points[0].y = sa->v1->vec.y + height/2; 00728 00729 points[1].x = sa->v1->vec.x; 00730 points[1].y = sa->v1->vec.y; 00731 00732 points[2].x = sa->v4->vec.x - w; 00733 points[2].y = sa->v4->vec.y; 00734 00735 points[3].x = sa->v4->vec.x - w; 00736 points[3].y = sa->v4->vec.y + height/2 - 2*h; 00737 00738 points[4].x = sa->v4->vec.x - 2*w; 00739 points[4].y = sa->v4->vec.y + height/2; 00740 00741 points[5].x = sa->v4->vec.x - w; 00742 points[5].y = sa->v4->vec.y + height/2 + 2*h; 00743 00744 points[6].x = sa->v3->vec.x - w; 00745 points[6].y = sa->v3->vec.y; 00746 00747 points[7].x = sa->v2->vec.x; 00748 points[7].y = sa->v2->vec.y; 00749 00750 points[8].x = sa->v4->vec.x; 00751 points[8].y = sa->v4->vec.y + height/2 - h; 00752 00753 points[9].x = sa->v4->vec.x; 00754 points[9].y = sa->v4->vec.y + height/2 + h; 00755 00756 if(dir=='l') { 00757 /* when direction is left, then we flip direction of arrow */ 00758 float cx = sa->v1->vec.x + width; 00759 for(i=0;i<10;i++) { 00760 points[i].x -= cx; 00761 points[i].x = -points[i].x; 00762 points[i].x += sa->v1->vec.x; 00763 } 00764 } 00765 00766 glBegin(GL_POLYGON); 00767 for(i=0;i<5;i++) 00768 glVertex2f(points[i].x, points[i].y); 00769 glEnd(); 00770 glBegin(GL_POLYGON); 00771 for(i=4;i<8;i++) 00772 glVertex2f(points[i].x, points[i].y); 00773 glVertex2f(points[0].x, points[0].y); 00774 glEnd(); 00775 00776 glRectf(points[2].x, points[2].y, points[8].x, points[8].y); 00777 glRectf(points[6].x, points[6].y, points[9].x, points[9].y); 00778 } 00779 00780 /* draw vertical shape visualising future joining (up/down direction) */ 00781 static void draw_vertical_join_shape(ScrArea *sa, char dir) 00782 { 00783 vec2f points[10]; 00784 short i; 00785 float w, h; 00786 float width = sa->v3->vec.x - sa->v1->vec.x; 00787 float height = sa->v3->vec.y - sa->v1->vec.y; 00788 00789 if(height<width) { 00790 h = height/4; 00791 w = height/8; 00792 } 00793 else { 00794 h = width/4; 00795 w = width/8; 00796 } 00797 00798 points[0].x = sa->v1->vec.x + width/2; 00799 points[0].y = sa->v3->vec.y; 00800 00801 points[1].x = sa->v2->vec.x; 00802 points[1].y = sa->v2->vec.y; 00803 00804 points[2].x = sa->v1->vec.x; 00805 points[2].y = sa->v1->vec.y + h; 00806 00807 points[3].x = sa->v1->vec.x + width/2 - 2*w; 00808 points[3].y = sa->v1->vec.y + h; 00809 00810 points[4].x = sa->v1->vec.x + width/2; 00811 points[4].y = sa->v1->vec.y + 2*h; 00812 00813 points[5].x = sa->v1->vec.x + width/2 + 2*w; 00814 points[5].y = sa->v1->vec.y + h; 00815 00816 points[6].x = sa->v4->vec.x; 00817 points[6].y = sa->v4->vec.y + h; 00818 00819 points[7].x = sa->v3->vec.x; 00820 points[7].y = sa->v3->vec.y; 00821 00822 points[8].x = sa->v1->vec.x + width/2 - w; 00823 points[8].y = sa->v1->vec.y; 00824 00825 points[9].x = sa->v1->vec.x + width/2 + w; 00826 points[9].y = sa->v1->vec.y; 00827 00828 if(dir=='u') { 00829 /* when direction is up, then we flip direction of arrow */ 00830 float cy = sa->v1->vec.y + height; 00831 for(i=0;i<10;i++) { 00832 points[i].y -= cy; 00833 points[i].y = -points[i].y; 00834 points[i].y += sa->v1->vec.y; 00835 } 00836 } 00837 00838 glBegin(GL_POLYGON); 00839 for(i=0;i<5;i++) 00840 glVertex2f(points[i].x, points[i].y); 00841 glEnd(); 00842 glBegin(GL_POLYGON); 00843 for(i=4;i<8;i++) 00844 glVertex2f(points[i].x, points[i].y); 00845 glVertex2f(points[0].x, points[0].y); 00846 glEnd(); 00847 00848 glRectf(points[2].x, points[2].y, points[8].x, points[8].y); 00849 glRectf(points[6].x, points[6].y, points[9].x, points[9].y); 00850 } 00851 00852 /* draw join shape due to direction of joining */ 00853 static void draw_join_shape(ScrArea *sa, char dir) 00854 { 00855 if(dir=='u' || dir=='d') 00856 draw_vertical_join_shape(sa, dir); 00857 else 00858 draw_horizontal_join_shape(sa, dir); 00859 } 00860 00861 /* draw screen area darker with arrow (visualisation of future joining) */ 00862 static void scrarea_draw_shape_dark(ScrArea *sa, char dir) 00863 { 00864 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00865 glEnable(GL_BLEND); 00866 glColor4ub(0, 0, 0, 50); 00867 draw_join_shape(sa, dir); 00868 glDisable(GL_BLEND); 00869 } 00870 00871 /* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */ 00872 static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir)) 00873 { 00874 glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); 00875 glEnable(GL_BLEND); 00876 /* value 181 was hardly computed: 181~105 */ 00877 glColor4ub(255, 255, 255, 50); 00878 /* draw_join_shape(sa, dir); */ 00879 glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y); 00880 glDisable(GL_BLEND); 00881 } 00882 00883 static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, short a) 00884 { 00885 /* right border area */ 00886 if(x2<sizex-1) 00887 sdrawline(x2+a, y1, x2+a, y2); 00888 00889 /* left border area */ 00890 if(x1>0) /* otherwise it draws the emboss of window over */ 00891 sdrawline(x1+a, y1, x1+a, y2); 00892 00893 /* top border area */ 00894 if(y2<sizey-1) 00895 sdrawline(x1, y2+a, x2, y2+a); 00896 00897 /* bottom border area */ 00898 if(y1>0) 00899 sdrawline(x1, y1+a, x2, y1+a); 00900 00901 } 00902 00904 static void drawscredge_area(ScrArea *sa, int sizex, int sizey, int center) 00905 { 00906 short x1= sa->v1->vec.x; 00907 short y1= sa->v1->vec.y; 00908 short x2= sa->v3->vec.x; 00909 short y2= sa->v3->vec.y; 00910 short a, rt; 00911 00912 rt= 0; // CLAMPIS(G.rt, 0, 16); 00913 00914 if(center==0) { 00915 cpack(0x505050); 00916 for(a=-rt; a<=rt; a++) 00917 if(a!=0) 00918 drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, a); 00919 } 00920 else { 00921 cpack(0x0); 00922 drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0); 00923 } 00924 } 00925 00926 /* ****************** EXPORTED API TO OTHER MODULES *************************** */ 00927 00928 bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc) 00929 { 00930 bScreen *newsc; 00931 00932 if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */ 00933 00934 /* make new empty screen: */ 00935 newsc= ED_screen_add(win, sc->scene, sc->id.name+2); 00936 /* copy all data */ 00937 screen_copy(newsc, sc); 00938 00939 return newsc; 00940 } 00941 00942 /* screen sets cursor based on swinid */ 00943 static void region_cursor_set(wmWindow *win, int swinid) 00944 { 00945 ScrArea *sa= win->screen->areabase.first; 00946 00947 for(;sa; sa= sa->next) { 00948 ARegion *ar= sa->regionbase.first; 00949 for(;ar; ar= ar->next) { 00950 if(ar->swinid == swinid) { 00951 if(ar->type && ar->type->cursor) 00952 ar->type->cursor(win, sa, ar); 00953 else 00954 WM_cursor_set(win, CURSOR_STD); 00955 return; 00956 } 00957 } 00958 } 00959 } 00960 00961 void ED_screen_do_listen(bContext *C, wmNotifier *note) 00962 { 00963 wmWindow *win= CTX_wm_window(C); 00964 00965 /* generic notes */ 00966 switch(note->category) { 00967 case NC_WM: 00968 if(note->data==ND_FILEREAD) 00969 win->screen->do_draw= 1; 00970 break; 00971 case NC_WINDOW: 00972 win->screen->do_draw= 1; 00973 break; 00974 case NC_SCREEN: 00975 if(note->data==ND_SUBWINACTIVE) 00976 uiFreeActiveButtons(C, win->screen); 00977 if(note->action==NA_EDITED) 00978 win->screen->do_draw= win->screen->do_refresh= 1; 00979 break; 00980 case NC_SCENE: 00981 if(note->data==ND_MODE) 00982 region_cursor_set(win, note->swinid); 00983 break; 00984 } 00985 } 00986 00987 /* only for edge lines between areas, and the blended join arrows */ 00988 void ED_screen_draw(wmWindow *win) 00989 { 00990 ScrArea *sa; 00991 ScrArea *sa1= NULL; 00992 ScrArea *sa2= NULL; 00993 ScrArea *sa3= NULL; 00994 int dir = -1; 00995 int dira = -1; 00996 00997 wmSubWindowSet(win, win->screen->mainwin); 00998 00999 for(sa= win->screen->areabase.first; sa; sa= sa->next) { 01000 if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; 01001 if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; 01002 if (sa->flag & (AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; 01003 drawscredge_area(sa, win->sizex, win->sizey, 0); 01004 } 01005 for(sa= win->screen->areabase.first; sa; sa= sa->next) 01006 drawscredge_area(sa, win->sizex, win->sizey, 1); 01007 01008 /* blended join arrow */ 01009 if (sa1 && sa2) { 01010 dir = area_getorientation(sa1, sa2); 01011 if (dir >= 0) { 01012 switch(dir) { 01013 case 0: /* W */ 01014 dir = 'r'; 01015 dira = 'l'; 01016 break; 01017 case 1: /* N */ 01018 dir = 'd'; 01019 dira = 'u'; 01020 break; 01021 case 2: /* E */ 01022 dir = 'l'; 01023 dira = 'r'; 01024 break; 01025 case 3: /* S */ 01026 dir = 'u'; 01027 dira = 'd'; 01028 break; 01029 } 01030 } 01031 scrarea_draw_shape_dark(sa2, dir); 01032 scrarea_draw_shape_light(sa1, dira); 01033 } 01034 01035 /* splitpoint */ 01036 if(sa3) { 01037 glEnable(GL_BLEND); 01038 glColor4ub(255, 255, 255, 100); 01039 01040 if(sa3->flag & AREA_FLAG_DRAWSPLIT_H) { 01041 sdrawline(sa3->totrct.xmin, win->eventstate->y, sa3->totrct.xmax, win->eventstate->y); 01042 glColor4ub(0, 0, 0, 100); 01043 sdrawline(sa3->totrct.xmin, win->eventstate->y+1, sa3->totrct.xmax, win->eventstate->y+1); 01044 } 01045 else { 01046 sdrawline(win->eventstate->x, sa3->totrct.ymin, win->eventstate->x, sa3->totrct.ymax); 01047 glColor4ub(0, 0, 0, 100); 01048 sdrawline(win->eventstate->x+1, sa3->totrct.ymin, win->eventstate->x+1, sa3->totrct.ymax); 01049 } 01050 01051 glDisable(GL_BLEND); 01052 } 01053 01054 win->screen->do_draw= 0; 01055 } 01056 01057 /* helper call for below, dpi changes headers */ 01058 static void screen_refresh_headersizes(void) 01059 { 01060 const ListBase *lb= BKE_spacetypes_list(); 01061 SpaceType *st; 01062 01063 for(st= lb->first; st; st= st->next) { 01064 ARegionType *art= BKE_regiontype_from_id(st, RGN_TYPE_HEADER); 01065 if(art) art->prefsizey= ED_area_headersize(); 01066 } 01067 } 01068 01069 /* make this screen usable */ 01070 /* for file read and first use, for scaling window, area moves */ 01071 void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) 01072 { 01073 /* exception for bg mode, we only need the screen context */ 01074 if (!G.background) { 01075 ScrArea *sa; 01076 rcti winrct; 01077 01078 winrct.xmin= 0; 01079 winrct.xmax= win->sizex-1; 01080 winrct.ymin= 0; 01081 winrct.ymax= win->sizey-1; 01082 01083 screen_test_scale(win->screen, win->sizex, win->sizey); 01084 01085 if(win->screen->mainwin==0) 01086 win->screen->mainwin= wm_subwindow_open(win, &winrct); 01087 else 01088 wm_subwindow_position(win, win->screen->mainwin, &winrct); 01089 01090 /* header size depends on DPI, let's verify */ 01091 screen_refresh_headersizes(); 01092 01093 for(sa= win->screen->areabase.first; sa; sa= sa->next) { 01094 /* set spacetype and region callbacks, calls init() */ 01095 /* sets subwindows for regions, adds handlers */ 01096 ED_area_initialize(wm, win, sa); 01097 } 01098 01099 /* wake up animtimer */ 01100 if(win->screen->animtimer) 01101 WM_event_timer_sleep(wm, win, win->screen->animtimer, 0); 01102 } 01103 01104 if(G.f & G_DEBUG) printf("set screen\n"); 01105 win->screen->do_refresh= 0; 01106 01107 win->screen->context= ed_screen_context; 01108 } 01109 01110 /* file read, set all screens, ... */ 01111 void ED_screens_initialize(wmWindowManager *wm) 01112 { 01113 wmWindow *win; 01114 01115 for(win= wm->windows.first; win; win= win->next) { 01116 01117 if(win->screen==NULL) 01118 win->screen= G.main->screen.first; 01119 01120 ED_screen_refresh(wm, win); 01121 } 01122 } 01123 01124 01125 /* *********** exit calls are for closing running stuff ******** */ 01126 01127 void ED_region_exit(bContext *C, ARegion *ar) 01128 { 01129 ARegion *prevar= CTX_wm_region(C); 01130 01131 CTX_wm_region_set(C, ar); 01132 WM_event_remove_handlers(C, &ar->handlers); 01133 if(ar->swinid) 01134 wm_subwindow_close(CTX_wm_window(C), ar->swinid); 01135 ar->swinid= 0; 01136 01137 if(ar->headerstr) 01138 MEM_freeN(ar->headerstr); 01139 ar->headerstr= NULL; 01140 01141 CTX_wm_region_set(C, prevar); 01142 } 01143 01144 void ED_area_exit(bContext *C, ScrArea *sa) 01145 { 01146 ScrArea *prevsa= CTX_wm_area(C); 01147 ARegion *ar; 01148 01149 if (sa->spacetype == SPACE_FILE) { 01150 SpaceLink *sl= sa->spacedata.first; 01151 if(sl && sl->spacetype == SPACE_FILE) { 01152 ED_fileselect_exit(C, (SpaceFile *)sl); 01153 } 01154 } 01155 01156 CTX_wm_area_set(C, sa); 01157 for(ar= sa->regionbase.first; ar; ar= ar->next) 01158 ED_region_exit(C, ar); 01159 01160 WM_event_remove_handlers(C, &sa->handlers); 01161 CTX_wm_area_set(C, prevsa); 01162 } 01163 01164 void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) 01165 { 01166 wmWindowManager *wm= CTX_wm_manager(C); 01167 wmWindow *prevwin= CTX_wm_window(C); 01168 ScrArea *sa; 01169 ARegion *ar; 01170 01171 CTX_wm_window_set(C, window); 01172 01173 if(screen->animtimer) 01174 WM_event_remove_timer(wm, window, screen->animtimer); 01175 screen->animtimer= NULL; 01176 01177 if(screen->mainwin) 01178 wm_subwindow_close(window, screen->mainwin); 01179 screen->mainwin= 0; 01180 screen->subwinactive= 0; 01181 01182 for(ar= screen->regionbase.first; ar; ar= ar->next) 01183 ED_region_exit(C, ar); 01184 01185 for(sa= screen->areabase.first; sa; sa= sa->next) 01186 ED_area_exit(C, sa); 01187 01188 /* mark it available for use for other windows */ 01189 screen->winid= 0; 01190 01191 if (prevwin->screen->temp == 0) { 01192 /* use previous window if possible */ 01193 CTX_wm_window_set(C, prevwin); 01194 } else { 01195 /* none otherwise */ 01196 CTX_wm_window_set(C, NULL); 01197 } 01198 01199 } 01200 01201 /* *********************************** */ 01202 01203 /* case when on area-edge or in azones, or outside window */ 01204 static void screen_cursor_set(wmWindow *win, wmEvent *event) 01205 { 01206 AZone *az= NULL; 01207 ScrArea *sa; 01208 01209 for(sa= win->screen->areabase.first; sa; sa= sa->next) 01210 if((az=is_in_area_actionzone(sa, event->x, event->y))) 01211 break; 01212 01213 if(sa) { 01214 if(az->type==AZONE_AREA) 01215 WM_cursor_set(win, CURSOR_EDIT); 01216 else if(az->type==AZONE_REGION) { 01217 if(az->edge == AE_LEFT_TO_TOPRIGHT || az->edge == AE_RIGHT_TO_TOPLEFT) 01218 WM_cursor_set(win, CURSOR_X_MOVE); 01219 else 01220 WM_cursor_set(win, CURSOR_Y_MOVE); 01221 } 01222 } 01223 else { 01224 ScrEdge *actedge= screen_find_active_scredge(win->screen, event->x, event->y); 01225 01226 if (actedge) { 01227 if(scredge_is_horizontal(actedge)) 01228 WM_cursor_set(win, CURSOR_Y_MOVE); 01229 else 01230 WM_cursor_set(win, CURSOR_X_MOVE); 01231 } 01232 else 01233 WM_cursor_set(win, CURSOR_STD); 01234 } 01235 } 01236 01237 01238 /* called in wm_event_system.c. sets state vars in screen, cursors */ 01239 /* event type is mouse move */ 01240 void ED_screen_set_subwinactive(bContext *C, wmEvent *event) 01241 { 01242 wmWindow *win= CTX_wm_window(C); 01243 01244 if(win->screen) { 01245 bScreen *scr= win->screen; 01246 ScrArea *sa; 01247 ARegion *ar; 01248 int oldswin= scr->subwinactive; 01249 01250 for(sa= scr->areabase.first; sa; sa= sa->next) { 01251 if(event->x > sa->totrct.xmin && event->x < sa->totrct.xmax) 01252 if(event->y > sa->totrct.ymin && event->y < sa->totrct.ymax) 01253 if(NULL==is_in_area_actionzone(sa, event->x, event->y)) 01254 break; 01255 } 01256 if(sa) { 01257 for(ar= sa->regionbase.first; ar; ar= ar->next) { 01258 if(BLI_in_rcti(&ar->winrct, event->x, event->y)) 01259 scr->subwinactive= ar->swinid; 01260 } 01261 } 01262 else 01263 scr->subwinactive= scr->mainwin; 01264 01265 /* check for redraw headers */ 01266 if(oldswin!=scr->subwinactive) { 01267 01268 for(sa= scr->areabase.first; sa; sa= sa->next) { 01269 int do_draw= 0; 01270 01271 for(ar= sa->regionbase.first; ar; ar= ar->next) 01272 if(ar->swinid==oldswin || ar->swinid==scr->subwinactive) 01273 do_draw= 1; 01274 01275 if(do_draw) { 01276 for(ar= sa->regionbase.first; ar; ar= ar->next) 01277 if(ar->regiontype==RGN_TYPE_HEADER) 01278 ED_region_tag_redraw(ar); 01279 } 01280 } 01281 } 01282 01283 /* cursors, for time being set always on edges, otherwise aregion doesnt switch */ 01284 if(scr->subwinactive==scr->mainwin) { 01285 screen_cursor_set(win, event); 01286 } 01287 else if(oldswin!=scr->subwinactive) { 01288 region_cursor_set(win, scr->subwinactive); 01289 WM_event_add_notifier(C, NC_SCREEN|ND_SUBWINACTIVE, scr); 01290 } 01291 } 01292 } 01293 01294 int ED_screen_area_active(const bContext *C) 01295 { 01296 wmWindow *win= CTX_wm_window(C); 01297 bScreen *sc= CTX_wm_screen(C); 01298 ScrArea *sa= CTX_wm_area(C); 01299 01300 if(win && sc && sa) { 01301 AZone *az= is_in_area_actionzone(sa, win->eventstate->x, win->eventstate->y); 01302 ARegion *ar; 01303 01304 if (az && az->type == AZONE_REGION) 01305 return 1; 01306 01307 for(ar= sa->regionbase.first; ar; ar= ar->next) 01308 if(ar->swinid == sc->subwinactive) 01309 return 1; 01310 } 01311 return 0; 01312 } 01313 01314 /* operator call, WM + Window + screen already existed before */ 01315 /* Do NOT call in area/region queues! */ 01316 void ED_screen_set(bContext *C, bScreen *sc) 01317 { 01318 wmWindowManager *wm= CTX_wm_manager(C); 01319 wmWindow *win= CTX_wm_window(C); 01320 bScreen *oldscreen= CTX_wm_screen(C); 01321 ID *id; 01322 01323 /* validate screen, it's called with notifier reference */ 01324 for(id= CTX_data_main(C)->screen.first; id; id= id->next) 01325 if(sc == (bScreen *)id) 01326 break; 01327 if(id==NULL) 01328 return; 01329 01330 /* check for valid winid */ 01331 if(sc->winid!=0 && sc->winid!=win->winid) 01332 return; 01333 01334 if(sc->full) { /* find associated full */ 01335 bScreen *sc1; 01336 for(sc1= CTX_data_main(C)->screen.first; sc1; sc1= sc1->id.next) { 01337 ScrArea *sa= sc1->areabase.first; 01338 if(sa->full==sc) { 01339 sc= sc1; 01340 break; 01341 } 01342 } 01343 } 01344 01345 if (oldscreen != sc) { 01346 wmTimer *wt= oldscreen->animtimer; 01347 ScrArea *sa; 01348 01349 /* remove handlers referencing areas in old screen */ 01350 for(sa = oldscreen->areabase.first; sa; sa = sa->next) { 01351 WM_event_remove_area_handler(&win->modalhandlers, sa); 01352 } 01353 01354 /* we put timer to sleep, so screen_exit has to think there's no timer */ 01355 oldscreen->animtimer= NULL; 01356 if(wt) 01357 WM_event_timer_sleep(wm, win, wt, 1); 01358 01359 ED_screen_exit(C, win, oldscreen); 01360 oldscreen->animtimer= wt; 01361 01362 win->screen= sc; 01363 CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf 01364 01365 /* prevent multiwin errors */ 01366 sc->winid= win->winid; 01367 01368 ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); 01369 WM_event_add_notifier(C, NC_WINDOW, NULL); 01370 WM_event_add_notifier(C, NC_SCREEN|ND_SCREENSET, sc); 01371 01372 /* makes button hilites work */ 01373 WM_event_add_mousemove(C); 01374 } 01375 } 01376 01377 static int ed_screen_used(wmWindowManager *wm, bScreen *sc) 01378 { 01379 wmWindow *win; 01380 01381 for(win=wm->windows.first; win; win=win->next) 01382 if(win->screen == sc) 01383 return 1; 01384 01385 return 0; 01386 } 01387 01388 /* only call outside of area/region loops */ 01389 void ED_screen_delete(bContext *C, bScreen *sc) 01390 { 01391 Main *bmain= CTX_data_main(C); 01392 wmWindowManager *wm= CTX_wm_manager(C); 01393 wmWindow *win= CTX_wm_window(C); 01394 bScreen *newsc; 01395 int delete= 1; 01396 01397 /* don't allow deleting temp fullscreens for now */ 01398 if (sc->full == SCREENFULL) { 01399 return; 01400 } 01401 01402 01403 /* screen can only be in use by one window at a time, so as 01404 long as we are able to find a screen that is unused, we 01405 can safely assume ours is not in use anywhere an delete it */ 01406 01407 for(newsc= sc->id.prev; newsc; newsc=newsc->id.prev) 01408 if(!ed_screen_used(wm, newsc)) 01409 break; 01410 01411 if(!newsc) { 01412 for(newsc= sc->id.next; newsc; newsc=newsc->id.next) 01413 if(!ed_screen_used(wm, newsc)) 01414 break; 01415 } 01416 01417 if(!newsc) 01418 return; 01419 01420 ED_screen_set(C, newsc); 01421 01422 if(delete && win->screen != sc) 01423 free_libblock(&bmain->screen, sc); 01424 } 01425 01426 /* only call outside of area/region loops */ 01427 void ED_screen_set_scene(bContext *C, Scene *scene) 01428 { 01429 Main *bmain= CTX_data_main(C); 01430 bScreen *sc; 01431 bScreen *curscreen= CTX_wm_screen(C); 01432 01433 ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO); 01434 01435 for(sc= CTX_data_main(C)->screen.first; sc; sc= sc->id.next) { 01436 if((U.flag & USER_SCENEGLOBAL) || sc==curscreen) { 01437 01438 if(scene != sc->scene) { 01439 /* all areas endlocalview */ 01440 // XXX ScrArea *sa= sc->areabase.first; 01441 // while(sa) { 01442 // endlocalview(sa); 01443 // sa= sa->next; 01444 // } 01445 sc->scene= scene; 01446 } 01447 01448 } 01449 } 01450 01451 // copy_view3d_lock(0); /* space.c */ 01452 01453 /* are there cameras in the views that are not in the scene? */ 01454 for(sc= CTX_data_main(C)->screen.first; sc; sc= sc->id.next) { 01455 if( (U.flag & USER_SCENEGLOBAL) || sc==curscreen) { 01456 ScrArea *sa= sc->areabase.first; 01457 while(sa) { 01458 SpaceLink *sl= sa->spacedata.first; 01459 while(sl) { 01460 if(sl->spacetype==SPACE_VIEW3D) { 01461 View3D *v3d= (View3D*) sl; 01462 01463 BKE_screen_view3d_sync(v3d, scene); 01464 01465 if (!v3d->camera || !object_in_scene(v3d->camera, scene)) { 01466 v3d->camera= scene_find_camera(sc->scene); 01467 // XXX if (sc==curscreen) handle_view3d_lock(); 01468 if (!v3d->camera) { 01469 ARegion *ar; 01470 for(ar=v3d->regionbase.first; ar; ar= ar->next) { 01471 if(ar->regiontype == RGN_TYPE_WINDOW) { 01472 RegionView3D *rv3d= ar->regiondata; 01473 01474 if(rv3d->persp==RV3D_CAMOB) 01475 rv3d->persp= RV3D_PERSP; 01476 } 01477 } 01478 } 01479 } 01480 } 01481 sl= sl->next; 01482 } 01483 sa= sa->next; 01484 } 01485 } 01486 } 01487 01488 CTX_data_scene_set(C, scene); 01489 set_scene_bg(bmain, scene); 01490 01491 ED_render_engine_changed(bmain); 01492 ED_update_for_newframe(bmain, scene, curscreen, 1); 01493 01494 /* complete redraw */ 01495 WM_event_add_notifier(C, NC_WINDOW, NULL); 01496 01497 } 01498 01499 /* only call outside of area/region loops */ 01500 void ED_screen_delete_scene(bContext *C, Scene *scene) 01501 { 01502 Main *bmain= CTX_data_main(C); 01503 Scene *newscene; 01504 01505 if(scene->id.prev) 01506 newscene= scene->id.prev; 01507 else if(scene->id.next) 01508 newscene= scene->id.next; 01509 else 01510 return; 01511 01512 ED_screen_set_scene(C, newscene); 01513 01514 unlink_scene(bmain, scene, newscene); 01515 } 01516 01517 ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) 01518 { 01519 wmWindow *win= CTX_wm_window(C); 01520 bScreen *screen= CTX_wm_screen(C); 01521 ScrArea *newsa= NULL; 01522 01523 if(!sa || sa->full==NULL) { 01524 newsa= ED_screen_full_toggle(C, win, sa); 01525 } 01526 01527 if(!newsa) { 01528 if (sa->full) { 01529 /* if this has been called from the temporary info header generated in 01530 * temp fullscreen layouts, find the correct fullscreen area to change 01531 * to create a new space inside */ 01532 for (newsa = screen->areabase.first; newsa; newsa=newsa->next) { 01533 if (!(sa->flag & AREA_TEMP_INFO)) 01534 break; 01535 } 01536 } else 01537 newsa= sa; 01538 } 01539 01540 ED_area_newspace(C, newsa, type); 01541 01542 return newsa; 01543 } 01544 01545 void ED_screen_full_prevspace(bContext *C, ScrArea *sa) 01546 { 01547 wmWindow *win= CTX_wm_window(C); 01548 01549 ED_area_prevspace(C, sa); 01550 01551 if(sa->full) 01552 ED_screen_full_toggle(C, win, sa); 01553 } 01554 01555 /* restore a screen / area back to default operation, after temp fullscreen modes */ 01556 void ED_screen_full_restore(bContext *C, ScrArea *sa) 01557 { 01558 wmWindow *win= CTX_wm_window(C); 01559 SpaceLink *sl = sa->spacedata.first; 01560 01561 /* if fullscreen area has a secondary space (such as a file browser or fullscreen render 01562 * overlaid on top of a existing setup) then return to the previous space */ 01563 01564 if (sl->next) { 01565 /* specific checks for space types */ 01566 01567 int sima_restore = 0; 01568 01569 /* Special check added for non-render image window (back from fullscreen through "Back to Previous" button) */ 01570 if (sl->spacetype == SPACE_IMAGE) { 01571 SpaceImage *sima= sa->spacedata.first; 01572 if (!(sima->flag & SI_PREVSPACE) && !(sima->flag & SI_FULLWINDOW)) 01573 sima_restore = 1; 01574 } 01575 01576 if (sl->spacetype == SPACE_IMAGE && !sima_restore) { 01577 SpaceImage *sima= sa->spacedata.first; 01578 if (sima->flag & SI_PREVSPACE) 01579 sima->flag &= ~SI_PREVSPACE; 01580 if (sima->flag & SI_FULLWINDOW) { 01581 sima->flag &= ~SI_FULLWINDOW; 01582 ED_screen_full_prevspace(C, sa); 01583 } 01584 } else if (sl->spacetype == SPACE_FILE) { 01585 ED_screen_full_prevspace(C, sa); 01586 } else 01587 ED_screen_full_toggle(C, win, sa); 01588 } 01589 /* otherwise just tile the area again */ 01590 else { 01591 ED_screen_full_toggle(C, win, sa); 01592 } 01593 } 01594 01595 /* this function toggles: if area is full then the parent will be restored */ 01596 ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa) 01597 { 01598 bScreen *sc, *oldscreen; 01599 ARegion *ar; 01600 01601 if(sa) { 01602 /* ensure we don't have a button active anymore, can crash when 01603 switching screens with tooltip open because region and tooltip 01604 are no longer in the same screen */ 01605 for(ar=sa->regionbase.first; ar; ar=ar->next) 01606 uiFreeBlocks(C, &ar->uiblocks); 01607 01608 /* prevent hanging header prints */ 01609 ED_area_headerprint(sa, NULL); 01610 } 01611 01612 if(sa && sa->full) { 01613 ScrArea *old; 01614 /*short fulltype;*/ /*UNUSED*/ 01615 01616 sc= sa->full; /* the old screen to restore */ 01617 oldscreen= win->screen; /* the one disappearing */ 01618 01619 /*fulltype = sc->full;*/ 01620 sc->full= 0; 01621 01622 /* removed: SCREENAUTOPLAY exception here */ 01623 01624 /* find old area */ 01625 for(old= sc->areabase.first; old; old= old->next) 01626 if(old->full) break; 01627 if(old==NULL) { 01628 if (G.f & G_DEBUG) 01629 printf("something wrong in areafullscreen\n"); 01630 return NULL; 01631 } 01632 01633 area_copy_data(old, sa, 1); /* 1 = swap spacelist */ 01634 if (sa->flag & AREA_TEMP_INFO) sa->flag &= ~AREA_TEMP_INFO; 01635 old->full= NULL; 01636 01637 /* animtimer back */ 01638 sc->animtimer= oldscreen->animtimer; 01639 oldscreen->animtimer= NULL; 01640 01641 ED_screen_set(C, sc); 01642 01643 free_screen(oldscreen); 01644 free_libblock(&CTX_data_main(C)->screen, oldscreen); 01645 01646 } 01647 else { 01648 ScrArea *newa; 01649 char newname[MAX_ID_NAME-2]; 01650 01651 oldscreen= win->screen; 01652 01653 /* nothing wrong with having only 1 area, as far as I can see... 01654 // is there only 1 area? 01655 if(oldscreen->areabase.first==oldscreen->areabase.last) 01656 return NULL; 01657 */ 01658 01659 oldscreen->full = SCREENFULL; 01660 BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name+2, "full"); 01661 sc= ED_screen_add(win, oldscreen->scene, newname); 01662 sc->full = SCREENFULL; // XXX 01663 01664 /* timer */ 01665 sc->animtimer= oldscreen->animtimer; 01666 oldscreen->animtimer= NULL; 01667 01668 /* returns the top small area */ 01669 newa= area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1); 01670 ED_area_newspace(C, newa, SPACE_INFO); 01671 01672 /* use random area when we have no active one, e.g. when the 01673 mouse is outside of the window and we open a file browser */ 01674 if(!sa) 01675 sa= oldscreen->areabase.first; 01676 01677 /* copy area */ 01678 newa= newa->prev; 01679 area_copy_data(newa, sa, 1); /* 1 = swap spacelist */ 01680 sa->flag |= AREA_TEMP_INFO; 01681 01682 sa->full= oldscreen; 01683 newa->full= oldscreen; 01684 newa->next->full= oldscreen; // XXX 01685 01686 ED_screen_set(C, sc); 01687 } 01688 01689 /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */ 01690 CTX_wm_area_set(C, sc->areabase.first); 01691 01692 return sc->areabase.first; 01693 } 01694 01695 /* update frame rate info for viewport drawing */ 01696 void ED_refresh_viewport_fps(bContext *C) 01697 { 01698 wmTimer *animtimer= CTX_wm_screen(C)->animtimer; 01699 Scene *scene= CTX_data_scene(C); 01700 01701 /* is anim playback running? */ 01702 if (animtimer && (U.uiflag & USER_SHOW_FPS)) { 01703 ScreenFrameRateInfo *fpsi= scene->fps_info; 01704 01705 /* if there isn't any info, init it first */ 01706 if (fpsi == NULL) 01707 fpsi= scene->fps_info= MEM_callocN(sizeof(ScreenFrameRateInfo), "refresh_viewport_fps fps_info"); 01708 01709 /* update the values */ 01710 fpsi->redrawtime= fpsi->lredrawtime; 01711 fpsi->lredrawtime= animtimer->ltime; 01712 } 01713 else { 01714 /* playback stopped or shouldn't be running */ 01715 if (scene->fps_info) 01716 MEM_freeN(scene->fps_info); 01717 scene->fps_info= NULL; 01718 } 01719 } 01720 01721 /* redraws: uses defines from stime->redraws 01722 * enable: 1 - forward on, -1 - backwards on, 0 - off 01723 */ 01724 void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable) 01725 { 01726 bScreen *screen= CTX_wm_screen(C); 01727 wmWindowManager *wm= CTX_wm_manager(C); 01728 wmWindow *win= CTX_wm_window(C); 01729 Scene *scene= CTX_data_scene(C); 01730 01731 if(screen->animtimer) 01732 WM_event_remove_timer(wm, win, screen->animtimer); 01733 screen->animtimer= NULL; 01734 01735 if(enable) { 01736 ScreenAnimData *sad= MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData"); 01737 01738 screen->animtimer= WM_event_add_timer(wm, win, TIMER0, (1.0/FPS)); 01739 01740 sad->ar= CTX_wm_region(C); 01741 sad->sfra = scene->r.cfra; 01742 sad->redraws= redraws; 01743 sad->refresh= refresh; 01744 sad->flag |= (enable < 0)? ANIMPLAY_FLAG_REVERSE: 0; 01745 sad->flag |= (sync == 0)? ANIMPLAY_FLAG_NO_SYNC: (sync == 1)? ANIMPLAY_FLAG_SYNC: 0; 01746 01747 screen->animtimer->customdata= sad; 01748 01749 } 01750 /* notifier catched by top header, for button */ 01751 WM_event_add_notifier(C, NC_SCREEN|ND_ANIMPLAY, screen); 01752 } 01753 01754 /* helper for screen_animation_play() - only to be used for TimeLine */ 01755 static ARegion *time_top_left_3dwindow(bScreen *screen) 01756 { 01757 ARegion *aret= NULL; 01758 ScrArea *sa; 01759 int min= 10000; 01760 01761 for(sa= screen->areabase.first; sa; sa= sa->next) { 01762 if(sa->spacetype==SPACE_VIEW3D) { 01763 ARegion *ar; 01764 for(ar= sa->regionbase.first; ar; ar= ar->next) { 01765 if(ar->regiontype==RGN_TYPE_WINDOW) { 01766 if(ar->winrct.xmin - ar->winrct.ymin < min) { 01767 aret= ar; 01768 min= ar->winrct.xmin - ar->winrct.ymin; 01769 } 01770 } 01771 } 01772 } 01773 } 01774 01775 return aret; 01776 } 01777 01778 void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh) 01779 { 01780 if(screen && screen->animtimer) { 01781 wmTimer *wt= screen->animtimer; 01782 ScreenAnimData *sad= wt->customdata; 01783 01784 sad->redraws= redraws; 01785 sad->refresh= refresh; 01786 sad->ar= NULL; 01787 if(redraws & TIME_REGION) 01788 sad->ar= time_top_left_3dwindow(screen); 01789 } 01790 } 01791 01792 /* results in fully updated anim system 01793 * screen can be NULL */ 01794 void ED_update_for_newframe(Main *bmain, Scene *scene, bScreen *screen, int UNUSED(mute)) 01795 { 01796 #ifdef DURIAN_CAMERA_SWITCH 01797 void *camera= scene_camera_switch_find(scene); 01798 if(camera && scene->camera != camera) { 01799 bScreen *sc; 01800 scene->camera= camera; 01801 /* are there cameras in the views that are not in the scene? */ 01802 for(sc= bmain->screen.first; sc; sc= sc->id.next) { 01803 BKE_screen_view3d_scene_sync(sc); 01804 } 01805 } 01806 #endif 01807 01808 //extern void audiostream_scrub(unsigned int frame); /* seqaudio.c */ 01809 01810 /* update animated image textures for gpu, etc, 01811 * call before scene_update_for_newframe so modifiers with textuers dont lag 1 frame */ 01812 ED_image_update_frame(bmain, scene->r.cfra); 01813 01814 ED_clip_update_frame(bmain, scene->r.cfra); 01815 01816 /* this function applies the changes too */ 01817 /* XXX future: do all windows */ 01818 scene_update_for_newframe(bmain, scene, BKE_screen_visible_layers(screen, scene)); /* BKE_scene.h */ 01819 01820 //if ( (CFRA>1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB)) 01821 // audiostream_scrub( CFRA ); 01822 01823 /* 3d window, preview */ 01824 //BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); 01825 01826 /* all movie/sequence images */ 01827 //BIF_image_update_frame(); 01828 01829 /* composite */ 01830 if(scene->use_nodes && scene->nodetree) 01831 ntreeCompositTagAnimated(scene->nodetree); 01832 01833 /* update animated texture nodes */ 01834 { 01835 Tex *tex; 01836 for(tex= bmain->tex.first; tex; tex= tex->id.next) 01837 if( tex->use_nodes && tex->nodetree ) { 01838 ntreeTexTagAnimated( tex->nodetree ); 01839 } 01840 } 01841 01842 } 01843 01844