|
Blender
V2.59
|
00001 /* 00002 * $Id: screen_edit.c 37986 2011-06-30 15:02:03Z ton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <string.h> 00033 #include <math.h> 00034 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_scene_types.h" 00039 #include "DNA_userdef_types.h" 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_utildefines.h" 00043 00044 #include "BKE_context.h" 00045 #include "BKE_global.h" 00046 #include "BKE_library.h" 00047 #include "BKE_main.h" 00048 #include "BKE_node.h" 00049 #include "BKE_screen.h" 00050 #include "BKE_scene.h" 00051 00052 #include "BIF_gl.h" 00053 #include "BIF_glutil.h" 00054 00055 #include "WM_api.h" 00056 #include "WM_types.h" 00057 00058 #include "ED_image.h" 00059 #include "ED_object.h" 00060 #include "ED_screen.h" 00061 #include "ED_screen_types.h" 00062 #include "ED_fileselect.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 { 00538 if (sa1 ) sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 00539 if (sa2 ) sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 00540 return 0; 00541 } 00542 00543 if(dir == 0) { 00544 sa1->v1= sa2->v1; 00545 sa1->v2= sa2->v2; 00546 screen_addedge(scr, sa1->v2, sa1->v3); 00547 screen_addedge(scr, sa1->v1, sa1->v4); 00548 } 00549 else if(dir == 1) { 00550 sa1->v2= sa2->v2; 00551 sa1->v3= sa2->v3; 00552 screen_addedge(scr, sa1->v1, sa1->v2); 00553 screen_addedge(scr, sa1->v3, sa1->v4); 00554 } 00555 else if(dir == 2) { 00556 sa1->v3= sa2->v3; 00557 sa1->v4= sa2->v4; 00558 screen_addedge(scr, sa1->v2, sa1->v3); 00559 screen_addedge(scr, sa1->v1, sa1->v4); 00560 } 00561 else if(dir == 3) { 00562 sa1->v1= sa2->v1; 00563 sa1->v4= sa2->v4; 00564 screen_addedge(scr, sa1->v1, sa1->v2); 00565 screen_addedge(scr, sa1->v3, sa1->v4); 00566 } 00567 00568 screen_delarea(C, scr, sa2); 00569 removedouble_scrverts(scr); 00570 sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 00571 00572 return 1; 00573 } 00574 00575 void select_connected_scredge(bScreen *sc, ScrEdge *edge) 00576 { 00577 ScrEdge *se; 00578 ScrVert *sv; 00579 int oneselected; 00580 char dir; 00581 00582 /* select connected, only in the right direction */ 00583 /* 'dir' is the direction of EDGE */ 00584 00585 if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v'; 00586 else dir= 'h'; 00587 00588 sv= sc->vertbase.first; 00589 while(sv) { 00590 sv->flag = 0; 00591 sv= sv->next; 00592 } 00593 00594 edge->v1->flag= 1; 00595 edge->v2->flag= 1; 00596 00597 oneselected= 1; 00598 while(oneselected) { 00599 se= sc->edgebase.first; 00600 oneselected= 0; 00601 while(se) { 00602 if(se->v1->flag + se->v2->flag==1) { 00603 if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) { 00604 se->v1->flag= se->v2->flag= 1; 00605 oneselected= 1; 00606 } 00607 if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) { 00608 se->v1->flag= se->v2->flag= 1; 00609 oneselected= 1; 00610 } 00611 } 00612 se= se->next; 00613 } 00614 } 00615 } 00616 00617 /* test if screen vertices should be scaled */ 00618 static void screen_test_scale(bScreen *sc, int winsizex, int winsizey) 00619 { 00620 ScrVert *sv=NULL; 00621 ScrArea *sa; 00622 int sizex, sizey; 00623 float facx, facy, tempf, min[2], max[2]; 00624 00625 /* calculate size */ 00626 min[0]= min[1]= 10000.0f; 00627 max[0]= max[1]= 0.0f; 00628 00629 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00630 min[0]= MIN2(min[0], sv->vec.x); 00631 min[1]= MIN2(min[1], sv->vec.y); 00632 max[0]= MAX2(max[0], sv->vec.x); 00633 max[1]= MAX2(max[1], sv->vec.y); 00634 } 00635 00636 /* always make 0.0 left under */ 00637 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00638 sv->vec.x -= min[0]; 00639 sv->vec.y -= min[1]; 00640 } 00641 00642 sizex= max[0]-min[0]; 00643 sizey= max[1]-min[1]; 00644 00645 if(sizex!= winsizex || sizey!= winsizey) { 00646 facx= winsizex; 00647 facx/= (float)sizex; 00648 facy= winsizey; 00649 facy/= (float)sizey; 00650 00651 /* make sure it fits! */ 00652 for(sv= sc->vertbase.first; sv; sv= sv->next) { 00653 /* FIXME, this resizing logic is no good when resizing the window + redrawing [#24428] 00654 * need some way to store these as floats internally and re-apply from there. */ 00655 tempf= ((float)sv->vec.x)*facx; 00656 sv->vec.x= (short)(tempf+0.5f); 00657 sv->vec.x+= AREAGRID-1; 00658 sv->vec.x-= (sv->vec.x % AREAGRID); 00659 00660 CLAMP(sv->vec.x, 0, winsizex); 00661 00662 tempf= ((float)sv->vec.y)*facy; 00663 sv->vec.y= (short)(tempf+0.5f); 00664 sv->vec.y+= AREAGRID-1; 00665 sv->vec.y-= (sv->vec.y % AREAGRID); 00666 00667 CLAMP(sv->vec.y, 0, winsizey); 00668 } 00669 } 00670 00671 /* test for collapsed areas. This could happen in some blender version... */ 00672 /* ton: removed option now, it needs Context... */ 00673 00674 /* make each window at least ED_area_headersize() high */ 00675 for(sa= sc->areabase.first; sa; sa= sa->next) { 00676 int headery= ED_area_headersize()+1; 00677 00678 if(sa->v1->vec.y+headery > sa->v2->vec.y) { 00679 /* lower edge */ 00680 ScrEdge *se= screen_findedge(sc, sa->v4, sa->v1); 00681 if(se && sa->v1!=sa->v2 ) { 00682 int yval; 00683 00684 select_connected_scredge(sc, se); 00685 00686 /* all selected vertices get the right offset */ 00687 yval= sa->v2->vec.y-headery; 00688 sv= sc->vertbase.first; 00689 while(sv) { 00690 /* if is a collapsed area */ 00691 if(sv!=sa->v2 && sv!=sa->v3) { 00692 if(sv->flag) sv->vec.y= yval; 00693 } 00694 sv= sv->next; 00695 } 00696 } 00697 } 00698 } 00699 00700 } 00701 00702 /* *********************** DRAWING **************************************** */ 00703 00704 00705 #define SCR_BACK 0.55 00706 #define SCR_ROUND 12 00707 00708 /* draw vertical shape visualising future joining (left as well 00709 * right direction of future joining) */ 00710 static void draw_horizontal_join_shape(ScrArea *sa, char dir) 00711 { 00712 vec2f points[10]; 00713 short i; 00714 float w, h; 00715 float width = sa->v3->vec.x - sa->v1->vec.x; 00716 float height = sa->v3->vec.y - sa->v1->vec.y; 00717 00718 if(height<width) { 00719 h = height/8; 00720 w = height/4; 00721 } 00722 else { 00723 h = width/8; 00724 w = width/4; 00725 } 00726 00727 points[0].x = sa->v1->vec.x; 00728 points[0].y = sa->v1->vec.y + height/2; 00729 00730 points[1].x = sa->v1->vec.x; 00731 points[1].y = sa->v1->vec.y; 00732 00733 points[2].x = sa->v4->vec.x - w; 00734 points[2].y = sa->v4->vec.y; 00735 00736 points[3].x = sa->v4->vec.x - w; 00737 points[3].y = sa->v4->vec.y + height/2 - 2*h; 00738 00739 points[4].x = sa->v4->vec.x - 2*w; 00740 points[4].y = sa->v4->vec.y + height/2; 00741 00742 points[5].x = sa->v4->vec.x - w; 00743 points[5].y = sa->v4->vec.y + height/2 + 2*h; 00744 00745 points[6].x = sa->v3->vec.x - w; 00746 points[6].y = sa->v3->vec.y; 00747 00748 points[7].x = sa->v2->vec.x; 00749 points[7].y = sa->v2->vec.y; 00750 00751 points[8].x = sa->v4->vec.x; 00752 points[8].y = sa->v4->vec.y + height/2 - h; 00753 00754 points[9].x = sa->v4->vec.x; 00755 points[9].y = sa->v4->vec.y + height/2 + h; 00756 00757 if(dir=='l') { 00758 /* when direction is left, then we flip direction of arrow */ 00759 float cx = sa->v1->vec.x + width; 00760 for(i=0;i<10;i++) { 00761 points[i].x -= cx; 00762 points[i].x = -points[i].x; 00763 points[i].x += sa->v1->vec.x; 00764 } 00765 } 00766 00767 glBegin(GL_POLYGON); 00768 for(i=0;i<5;i++) 00769 glVertex2f(points[i].x, points[i].y); 00770 glEnd(); 00771 glBegin(GL_POLYGON); 00772 for(i=4;i<8;i++) 00773 glVertex2f(points[i].x, points[i].y); 00774 glVertex2f(points[0].x, points[0].y); 00775 glEnd(); 00776 00777 glRectf(points[2].x, points[2].y, points[8].x, points[8].y); 00778 glRectf(points[6].x, points[6].y, points[9].x, points[9].y); 00779 } 00780 00781 /* draw vertical shape visualising future joining (up/down direction) */ 00782 static void draw_vertical_join_shape(ScrArea *sa, char dir) 00783 { 00784 vec2f points[10]; 00785 short i; 00786 float w, h; 00787 float width = sa->v3->vec.x - sa->v1->vec.x; 00788 float height = sa->v3->vec.y - sa->v1->vec.y; 00789 00790 if(height<width) { 00791 h = height/4; 00792 w = height/8; 00793 } 00794 else { 00795 h = width/4; 00796 w = width/8; 00797 } 00798 00799 points[0].x = sa->v1->vec.x + width/2; 00800 points[0].y = sa->v3->vec.y; 00801 00802 points[1].x = sa->v2->vec.x; 00803 points[1].y = sa->v2->vec.y; 00804 00805 points[2].x = sa->v1->vec.x; 00806 points[2].y = sa->v1->vec.y + h; 00807 00808 points[3].x = sa->v1->vec.x + width/2 - 2*w; 00809 points[3].y = sa->v1->vec.y + h; 00810 00811 points[4].x = sa->v1->vec.x + width/2; 00812 points[4].y = sa->v1->vec.y + 2*h; 00813 00814 points[5].x = sa->v1->vec.x + width/2 + 2*w; 00815 points[5].y = sa->v1->vec.y + h; 00816 00817 points[6].x = sa->v4->vec.x; 00818 points[6].y = sa->v4->vec.y + h; 00819 00820 points[7].x = sa->v3->vec.x; 00821 points[7].y = sa->v3->vec.y; 00822 00823 points[8].x = sa->v1->vec.x + width/2 - w; 00824 points[8].y = sa->v1->vec.y; 00825 00826 points[9].x = sa->v1->vec.x + width/2 + w; 00827 points[9].y = sa->v1->vec.y; 00828 00829 if(dir=='u') { 00830 /* when direction is up, then we flip direction of arrow */ 00831 float cy = sa->v1->vec.y + height; 00832 for(i=0;i<10;i++) { 00833 points[i].y -= cy; 00834 points[i].y = -points[i].y; 00835 points[i].y += sa->v1->vec.y; 00836 } 00837 } 00838 00839 glBegin(GL_POLYGON); 00840 for(i=0;i<5;i++) 00841 glVertex2f(points[i].x, points[i].y); 00842 glEnd(); 00843 glBegin(GL_POLYGON); 00844 for(i=4;i<8;i++) 00845 glVertex2f(points[i].x, points[i].y); 00846 glVertex2f(points[0].x, points[0].y); 00847 glEnd(); 00848 00849 glRectf(points[2].x, points[2].y, points[8].x, points[8].y); 00850 glRectf(points[6].x, points[6].y, points[9].x, points[9].y); 00851 } 00852 00853 /* draw join shape due to direction of joining */ 00854 static void draw_join_shape(ScrArea *sa, char dir) 00855 { 00856 if(dir=='u' || dir=='d') 00857 draw_vertical_join_shape(sa, dir); 00858 else 00859 draw_horizontal_join_shape(sa, dir); 00860 } 00861 00862 /* draw screen area darker with arrow (visualisation of future joining) */ 00863 static void scrarea_draw_shape_dark(ScrArea *sa, char dir) 00864 { 00865 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00866 glEnable(GL_BLEND); 00867 glColor4ub(0, 0, 0, 50); 00868 draw_join_shape(sa, dir); 00869 glDisable(GL_BLEND); 00870 } 00871 00872 /* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */ 00873 static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir)) 00874 { 00875 glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); 00876 glEnable(GL_BLEND); 00877 /* value 181 was hardly computed: 181~105 */ 00878 glColor4ub(255, 255, 255, 50); 00879 /* draw_join_shape(sa, dir); */ 00880 glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y); 00881 glDisable(GL_BLEND); 00882 } 00883 00884 static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, short a) 00885 { 00886 /* right border area */ 00887 if(x2<sizex-1) 00888 sdrawline(x2+a, y1, x2+a, y2); 00889 00890 /* left border area */ 00891 if(x1>0) /* otherwise it draws the emboss of window over */ 00892 sdrawline(x1+a, y1, x1+a, y2); 00893 00894 /* top border area */ 00895 if(y2<sizey-1) 00896 sdrawline(x1, y2+a, x2, y2+a); 00897 00898 /* bottom border area */ 00899 if(y1>0) 00900 sdrawline(x1, y1+a, x2, y1+a); 00901 00902 } 00903 00905 static void drawscredge_area(ScrArea *sa, int sizex, int sizey, int center) 00906 { 00907 short x1= sa->v1->vec.x; 00908 short y1= sa->v1->vec.y; 00909 short x2= sa->v3->vec.x; 00910 short y2= sa->v3->vec.y; 00911 short a, rt; 00912 00913 rt= 0; // CLAMPIS(G.rt, 0, 16); 00914 00915 if(center==0) { 00916 cpack(0x505050); 00917 for(a=-rt; a<=rt; a++) 00918 if(a!=0) 00919 drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, a); 00920 } 00921 else { 00922 cpack(0x0); 00923 drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0); 00924 } 00925 } 00926 00927 /* ****************** EXPORTED API TO OTHER MODULES *************************** */ 00928 00929 bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc) 00930 { 00931 bScreen *newsc; 00932 00933 if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */ 00934 00935 /* make new empty screen: */ 00936 newsc= ED_screen_add(win, sc->scene, sc->id.name+2); 00937 /* copy all data */ 00938 screen_copy(newsc, sc); 00939 00940 return newsc; 00941 } 00942 00943 /* screen sets cursor based on swinid */ 00944 static void region_cursor_set(wmWindow *win, int swinid) 00945 { 00946 ScrArea *sa= win->screen->areabase.first; 00947 00948 for(;sa; sa= sa->next) { 00949 ARegion *ar= sa->regionbase.first; 00950 for(;ar; ar= ar->next) { 00951 if(ar->swinid == swinid) { 00952 if(ar->type && ar->type->cursor) 00953 ar->type->cursor(win, sa, ar); 00954 else 00955 WM_cursor_set(win, CURSOR_STD); 00956 return; 00957 } 00958 } 00959 } 00960 } 00961 00962 void ED_screen_do_listen(bContext *C, wmNotifier *note) 00963 { 00964 wmWindow *win= CTX_wm_window(C); 00965 00966 /* generic notes */ 00967 switch(note->category) { 00968 case NC_WM: 00969 if(note->data==ND_FILEREAD) 00970 win->screen->do_draw= 1; 00971 break; 00972 case NC_WINDOW: 00973 win->screen->do_draw= 1; 00974 break; 00975 case NC_SCREEN: 00976 if(note->data==ND_SUBWINACTIVE) 00977 uiFreeActiveButtons(C, win->screen); 00978 if(note->action==NA_EDITED) 00979 win->screen->do_draw= win->screen->do_refresh= 1; 00980 break; 00981 case NC_SCENE: 00982 if(note->data==ND_MODE) 00983 region_cursor_set(win, note->swinid); 00984 break; 00985 } 00986 } 00987 00988 /* only for edge lines between areas, and the blended join arrows */ 00989 void ED_screen_draw(wmWindow *win) 00990 { 00991 ScrArea *sa; 00992 ScrArea *sa1= NULL; 00993 ScrArea *sa2= NULL; 00994 ScrArea *sa3= NULL; 00995 int dir = -1; 00996 int dira = -1; 00997 00998 wmSubWindowSet(win, win->screen->mainwin); 00999 01000 for(sa= win->screen->areabase.first; sa; sa= sa->next) { 01001 if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; 01002 if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; 01003 if (sa->flag & (AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; 01004 drawscredge_area(sa, win->sizex, win->sizey, 0); 01005 } 01006 for(sa= win->screen->areabase.first; sa; sa= sa->next) 01007 drawscredge_area(sa, win->sizex, win->sizey, 1); 01008 01009 /* blended join arrow */ 01010 if (sa1 && sa2) { 01011 dir = area_getorientation(sa1, sa2); 01012 if (dir >= 0) { 01013 switch(dir) { 01014 case 0: /* W */ 01015 dir = 'r'; 01016 dira = 'l'; 01017 break; 01018 case 1: /* N */ 01019 dir = 'd'; 01020 dira = 'u'; 01021 break; 01022 case 2: /* E */ 01023 dir = 'l'; 01024 dira = 'r'; 01025 break; 01026 case 3: /* S */ 01027 dir = 'u'; 01028 dira = 'd'; 01029 break; 01030 } 01031 } 01032 scrarea_draw_shape_dark(sa2, dir); 01033 scrarea_draw_shape_light(sa1, dira); 01034 } 01035 01036 /* splitpoint */ 01037 if(sa3) { 01038 glEnable(GL_BLEND); 01039 glColor4ub(255, 255, 255, 100); 01040 01041 if(sa3->flag & AREA_FLAG_DRAWSPLIT_H) { 01042 sdrawline(sa3->totrct.xmin, win->eventstate->y, sa3->totrct.xmax, win->eventstate->y); 01043 glColor4ub(0, 0, 0, 100); 01044 sdrawline(sa3->totrct.xmin, win->eventstate->y+1, sa3->totrct.xmax, win->eventstate->y+1); 01045 } 01046 else { 01047 sdrawline(win->eventstate->x, sa3->totrct.ymin, win->eventstate->x, sa3->totrct.ymax); 01048 glColor4ub(0, 0, 0, 100); 01049 sdrawline(win->eventstate->x+1, sa3->totrct.ymin, win->eventstate->x+1, sa3->totrct.ymax); 01050 } 01051 01052 glDisable(GL_BLEND); 01053 } 01054 01055 win->screen->do_draw= 0; 01056 } 01057 01058 /* helper call for below, dpi changes headers */ 01059 static void screen_refresh_headersizes(void) 01060 { 01061 const ListBase *lb= BKE_spacetypes_list(); 01062 SpaceType *st; 01063 01064 for(st= lb->first; st; st= st->next) { 01065 ARegionType *art= BKE_regiontype_from_id(st, RGN_TYPE_HEADER); 01066 if(art) art->prefsizey= ED_area_headersize(); 01067 } 01068 } 01069 01070 /* make this screen usable */ 01071 /* for file read and first use, for scaling window, area moves */ 01072 void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) 01073 { 01074 /* exception for bg mode, we only need the screen context */ 01075 if (!G.background) { 01076 ScrArea *sa; 01077 rcti winrct; 01078 01079 winrct.xmin= 0; 01080 winrct.xmax= win->sizex-1; 01081 winrct.ymin= 0; 01082 winrct.ymax= win->sizey-1; 01083 01084 screen_test_scale(win->screen, win->sizex, win->sizey); 01085 01086 if(win->screen->mainwin==0) 01087 win->screen->mainwin= wm_subwindow_open(win, &winrct); 01088 else 01089 wm_subwindow_position(win, win->screen->mainwin, &winrct); 01090 01091 /* header size depends on DPI, let's verify */ 01092 screen_refresh_headersizes(); 01093 01094 for(sa= win->screen->areabase.first; sa; sa= sa->next) { 01095 /* set spacetype and region callbacks, calls init() */ 01096 /* sets subwindows for regions, adds handlers */ 01097 ED_area_initialize(wm, win, sa); 01098 } 01099 01100 /* wake up animtimer */ 01101 if(win->screen->animtimer) 01102 WM_event_timer_sleep(wm, win, win->screen->animtimer, 0); 01103 } 01104 01105 if(G.f & G_DEBUG) printf("set screen\n"); 01106 win->screen->do_refresh= 0; 01107 01108 win->screen->context= ed_screen_context; 01109 } 01110 01111 /* file read, set all screens, ... */ 01112 void ED_screens_initialize(wmWindowManager *wm) 01113 { 01114 wmWindow *win; 01115 01116 for(win= wm->windows.first; win; win= win->next) { 01117 01118 if(win->screen==NULL) 01119 win->screen= G.main->screen.first; 01120 01121 ED_screen_refresh(wm, win); 01122 } 01123 } 01124 01125 01126 /* *********** exit calls are for closing running stuff ******** */ 01127 01128 void ED_region_exit(bContext *C, ARegion *ar) 01129 { 01130 ARegion *prevar= CTX_wm_region(C); 01131 01132 CTX_wm_region_set(C, ar); 01133 WM_event_remove_handlers(C, &ar->handlers); 01134 if(ar->swinid) 01135 wm_subwindow_close(CTX_wm_window(C), ar->swinid); 01136 ar->swinid= 0; 01137 01138 if(ar->headerstr) 01139 MEM_freeN(ar->headerstr); 01140 ar->headerstr= NULL; 01141 01142 CTX_wm_region_set(C, prevar); 01143 } 01144 01145 void ED_area_exit(bContext *C, ScrArea *sa) 01146 { 01147 ScrArea *prevsa= CTX_wm_area(C); 01148 ARegion *ar; 01149 01150 if (sa->spacetype == SPACE_FILE) { 01151 SpaceLink *sl= sa->spacedata.first; 01152 if(sl && sl->spacetype == SPACE_FILE) { 01153 ED_fileselect_exit(C, (SpaceFile *)sl); 01154 } 01155 } 01156 01157 CTX_wm_area_set(C, sa); 01158 for(ar= sa->regionbase.first; ar; ar= ar->next) 01159 ED_region_exit(C, ar); 01160 01161 WM_event_remove_handlers(C, &sa->handlers); 01162 CTX_wm_area_set(C, prevsa); 01163 } 01164 01165 void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) 01166 { 01167 wmWindowManager *wm= CTX_wm_manager(C); 01168 wmWindow *prevwin= CTX_wm_window(C); 01169 ScrArea *sa; 01170 ARegion *ar; 01171 01172 CTX_wm_window_set(C, window); 01173 01174 if(screen->animtimer) 01175 WM_event_remove_timer(wm, window, screen->animtimer); 01176 screen->animtimer= NULL; 01177 01178 if(screen->mainwin) 01179 wm_subwindow_close(window, screen->mainwin); 01180 screen->mainwin= 0; 01181 screen->subwinactive= 0; 01182 01183 for(ar= screen->regionbase.first; ar; ar= ar->next) 01184 ED_region_exit(C, ar); 01185 01186 for(sa= screen->areabase.first; sa; sa= sa->next) 01187 ED_area_exit(C, sa); 01188 01189 /* mark it available for use for other windows */ 01190 screen->winid= 0; 01191 01192 if (prevwin->screen->temp == 0) { 01193 /* use previous window if possible */ 01194 CTX_wm_window_set(C, prevwin); 01195 } else { 01196 /* none otherwise */ 01197 CTX_wm_window_set(C, NULL); 01198 } 01199 01200 } 01201 01202 /* *********************************** */ 01203 01204 /* case when on area-edge or in azones, or outside window */ 01205 static void screen_cursor_set(wmWindow *win, wmEvent *event) 01206 { 01207 AZone *az= NULL; 01208 ScrArea *sa; 01209 01210 for(sa= win->screen->areabase.first; sa; sa= sa->next) 01211 if((az=is_in_area_actionzone(sa, event->x, event->y))) 01212 break; 01213 01214 if(sa) { 01215 if(az->type==AZONE_AREA) 01216 WM_cursor_set(win, CURSOR_EDIT); 01217 else if(az->type==AZONE_REGION) { 01218 if(az->edge == AE_LEFT_TO_TOPRIGHT || az->edge == AE_RIGHT_TO_TOPLEFT) 01219 WM_cursor_set(win, CURSOR_X_MOVE); 01220 else 01221 WM_cursor_set(win, CURSOR_Y_MOVE); 01222 } 01223 } 01224 else { 01225 ScrEdge *actedge= screen_find_active_scredge(win->screen, event->x, event->y); 01226 01227 if (actedge) { 01228 if(scredge_is_horizontal(actedge)) 01229 WM_cursor_set(win, CURSOR_Y_MOVE); 01230 else 01231 WM_cursor_set(win, CURSOR_X_MOVE); 01232 } 01233 else 01234 WM_cursor_set(win, CURSOR_STD); 01235 } 01236 } 01237 01238 01239 /* called in wm_event_system.c. sets state vars in screen, cursors */ 01240 /* event type is mouse move */ 01241 void ED_screen_set_subwinactive(bContext *C, wmEvent *event) 01242 { 01243 wmWindow *win= CTX_wm_window(C); 01244 01245 if(win->screen) { 01246 bScreen *scr= win->screen; 01247 ScrArea *sa; 01248 ARegion *ar; 01249 int oldswin= scr->subwinactive; 01250 01251 for(sa= scr->areabase.first; sa; sa= sa->next) { 01252 if(event->x > sa->totrct.xmin && event->x < sa->totrct.xmax) 01253 if(event->y > sa->totrct.ymin && event->y < sa->totrct.ymax) 01254 if(NULL==is_in_area_actionzone(sa, event->x, event->y)) 01255 break; 01256 } 01257 if(sa) { 01258 for(ar= sa->regionbase.first; ar; ar= ar->next) { 01259 if(BLI_in_rcti(&ar->winrct, event->x, event->y)) 01260 scr->subwinactive= ar->swinid; 01261 } 01262 } 01263 else 01264 scr->subwinactive= scr->mainwin; 01265 01266 /* check for redraw headers */ 01267 if(oldswin!=scr->subwinactive) { 01268 01269 for(sa= scr->areabase.first; sa; sa= sa->next) { 01270 int do_draw= 0; 01271 01272 for(ar= sa->regionbase.first; ar; ar= ar->next) 01273 if(ar->swinid==oldswin || ar->swinid==scr->subwinactive) 01274 do_draw= 1; 01275 01276 if(do_draw) { 01277 for(ar= sa->regionbase.first; ar; ar= ar->next) 01278 if(ar->regiontype==RGN_TYPE_HEADER) 01279 ED_region_tag_redraw(ar); 01280 } 01281 } 01282 } 01283 01284 /* cursors, for time being set always on edges, otherwise aregion doesnt switch */ 01285 if(scr->subwinactive==scr->mainwin) { 01286 screen_cursor_set(win, event); 01287 } 01288 else if(oldswin!=scr->subwinactive) { 01289 region_cursor_set(win, scr->subwinactive); 01290 WM_event_add_notifier(C, NC_SCREEN|ND_SUBWINACTIVE, scr); 01291 } 01292 } 01293 } 01294 01295 int ED_screen_area_active(const bContext *C) 01296 { 01297 wmWindow *win= CTX_wm_window(C); 01298 bScreen *sc= CTX_wm_screen(C); 01299 ScrArea *sa= CTX_wm_area(C); 01300 01301 if(win && sc && sa) { 01302 AZone *az= is_in_area_actionzone(sa, win->eventstate->x, win->eventstate->y); 01303 ARegion *ar; 01304 01305 if (az && az->type == AZONE_REGION) 01306 return 1; 01307 01308 for(ar= sa->regionbase.first; ar; ar= ar->next) 01309 if(ar->swinid == sc->subwinactive) 01310 return 1; 01311 } 01312 return 0; 01313 } 01314 01315 /* operator call, WM + Window + screen already existed before */ 01316 /* Do NOT call in area/region queues! */ 01317 void ED_screen_set(bContext *C, bScreen *sc) 01318 { 01319 wmWindowManager *wm= CTX_wm_manager(C); 01320 wmWindow *win= CTX_wm_window(C); 01321 bScreen *oldscreen= CTX_wm_screen(C); 01322 ID *id; 01323 01324 /* validate screen, it's called with notifier reference */ 01325 for(id= CTX_data_main(C)->screen.first; id; id= id->next) 01326 if(sc == (bScreen *)id) 01327 break; 01328 if(id==NULL) 01329 return; 01330 01331 /* check for valid winid */ 01332 if(sc->winid!=0 && sc->winid!=win->winid) 01333 return; 01334 01335 if(sc->full) { /* find associated full */ 01336 bScreen *sc1; 01337 for(sc1= CTX_data_main(C)->screen.first; sc1; sc1= sc1->id.next) { 01338 ScrArea *sa= sc1->areabase.first; 01339 if(sa->full==sc) { 01340 sc= sc1; 01341 break; 01342 } 01343 } 01344 } 01345 01346 if (oldscreen != sc) { 01347 wmTimer *wt= oldscreen->animtimer; 01348 ScrArea *sa; 01349 01350 /* remove handlers referencing areas in old screen */ 01351 for(sa = oldscreen->areabase.first; sa; sa = sa->next) { 01352 WM_event_remove_area_handler(&win->modalhandlers, sa); 01353 } 01354 01355 /* we put timer to sleep, so screen_exit has to think there's no timer */ 01356 oldscreen->animtimer= NULL; 01357 if(wt) 01358 WM_event_timer_sleep(wm, win, wt, 1); 01359 01360 ED_screen_exit(C, win, oldscreen); 01361 oldscreen->animtimer= wt; 01362 01363 win->screen= sc; 01364 CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf 01365 01366 /* prevent multiwin errors */ 01367 sc->winid= win->winid; 01368 01369 ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); 01370 WM_event_add_notifier(C, NC_WINDOW, NULL); 01371 WM_event_add_notifier(C, NC_SCREEN|ND_SCREENSET, sc); 01372 01373 /* makes button hilites work */ 01374 WM_event_add_mousemove(C); 01375 } 01376 } 01377 01378 static int ed_screen_used(wmWindowManager *wm, bScreen *sc) 01379 { 01380 wmWindow *win; 01381 01382 for(win=wm->windows.first; win; win=win->next) 01383 if(win->screen == sc) 01384 return 1; 01385 01386 return 0; 01387 } 01388 01389 /* only call outside of area/region loops */ 01390 void ED_screen_delete(bContext *C, bScreen *sc) 01391 { 01392 Main *bmain= CTX_data_main(C); 01393 wmWindowManager *wm= CTX_wm_manager(C); 01394 wmWindow *win= CTX_wm_window(C); 01395 bScreen *newsc; 01396 int delete= 1; 01397 01398 /* don't allow deleting temp fullscreens for now */ 01399 if (sc->full == SCREENFULL) { 01400 return; 01401 } 01402 01403 01404 /* screen can only be in use by one window at a time, so as 01405 long as we are able to find a screen that is unused, we 01406 can safely assume ours is not in use anywhere an delete it */ 01407 01408 for(newsc= sc->id.prev; newsc; newsc=newsc->id.prev) 01409 if(!ed_screen_used(wm, newsc)) 01410 break; 01411 01412 if(!newsc) { 01413 for(newsc= sc->id.next; newsc; newsc=newsc->id.next) 01414 if(!ed_screen_used(wm, newsc)) 01415 break; 01416 } 01417 01418 if(!newsc) 01419 return; 01420 01421 ED_screen_set(C, newsc); 01422 01423 if(delete && win->screen != sc) 01424 free_libblock(&bmain->screen, sc); 01425 } 01426 01427 /* only call outside of area/region loops */ 01428 void ED_screen_set_scene(bContext *C, Scene *scene) 01429 { 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(CTX_data_main(C), scene); 01490 01491 ED_update_for_newframe(CTX_data_main(C), scene, curscreen, 1); 01492 01493 /* complete redraw */ 01494 WM_event_add_notifier(C, NC_WINDOW, NULL); 01495 01496 } 01497 01498 /* only call outside of area/region loops */ 01499 void ED_screen_delete_scene(bContext *C, Scene *scene) 01500 { 01501 Main *bmain= CTX_data_main(C); 01502 Scene *newscene; 01503 01504 if(scene->id.prev) 01505 newscene= scene->id.prev; 01506 else if(scene->id.next) 01507 newscene= scene->id.next; 01508 else 01509 return; 01510 01511 ED_screen_set_scene(C, newscene); 01512 01513 unlink_scene(bmain, scene, newscene); 01514 } 01515 01516 ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) 01517 { 01518 wmWindow *win= CTX_wm_window(C); 01519 bScreen *screen= CTX_wm_screen(C); 01520 ScrArea *newsa= NULL; 01521 01522 if(!sa || sa->full==NULL) { 01523 newsa= ED_screen_full_toggle(C, win, sa); 01524 } 01525 01526 if(!newsa) { 01527 if (sa->full) { 01528 /* if this has been called from the temporary info header generated in 01529 * temp fullscreen layouts, find the correct fullscreen area to change 01530 * to create a new space inside */ 01531 for (newsa = screen->areabase.first; newsa; newsa=newsa->next) { 01532 if (!(sa->flag & AREA_TEMP_INFO)) 01533 break; 01534 } 01535 } else 01536 newsa= sa; 01537 } 01538 01539 ED_area_newspace(C, newsa, type); 01540 01541 return newsa; 01542 } 01543 01544 void ED_screen_full_prevspace(bContext *C, ScrArea *sa) 01545 { 01546 wmWindow *win= CTX_wm_window(C); 01547 01548 ED_area_prevspace(C, sa); 01549 01550 if(sa->full) 01551 ED_screen_full_toggle(C, win, sa); 01552 } 01553 01554 /* restore a screen / area back to default operation, after temp fullscreen modes */ 01555 void ED_screen_full_restore(bContext *C, ScrArea *sa) 01556 { 01557 wmWindow *win= CTX_wm_window(C); 01558 SpaceLink *sl = sa->spacedata.first; 01559 01560 /* if fullscreen area has a secondary space (such as a file browser or fullscreen render 01561 * overlaid on top of a existing setup) then return to the previous space */ 01562 01563 if (sl->next) { 01564 /* specific checks for space types */ 01565 01566 int sima_restore = 0; 01567 01568 /* Special check added for non-render image window (back from fullscreen through "Back to Previous" button) */ 01569 if (sl->spacetype == SPACE_IMAGE) { 01570 SpaceImage *sima= sa->spacedata.first; 01571 if (!(sima->flag & SI_PREVSPACE) && !(sima->flag & SI_FULLWINDOW)) 01572 sima_restore = 1; 01573 } 01574 01575 if (sl->spacetype == SPACE_IMAGE && !sima_restore) { 01576 SpaceImage *sima= sa->spacedata.first; 01577 if (sima->flag & SI_PREVSPACE) 01578 sima->flag &= ~SI_PREVSPACE; 01579 if (sima->flag & SI_FULLWINDOW) { 01580 sima->flag &= ~SI_FULLWINDOW; 01581 ED_screen_full_prevspace(C, sa); 01582 } 01583 } else if (sl->spacetype == SPACE_FILE) { 01584 ED_screen_full_prevspace(C, sa); 01585 } else 01586 ED_screen_full_toggle(C, win, sa); 01587 } 01588 /* otherwise just tile the area again */ 01589 else { 01590 ED_screen_full_toggle(C, win, sa); 01591 } 01592 } 01593 01594 /* this function toggles: if area is full then the parent will be restored */ 01595 ScrArea *ED_screen_full_toggle(bContext *C, wmWindow *win, ScrArea *sa) 01596 { 01597 bScreen *sc, *oldscreen; 01598 ARegion *ar; 01599 01600 if(sa) { 01601 /* ensure we don't have a button active anymore, can crash when 01602 switching screens with tooltip open because region and tooltip 01603 are no longer in the same screen */ 01604 for(ar=sa->regionbase.first; ar; ar=ar->next) 01605 uiFreeBlocks(C, &ar->uiblocks); 01606 01607 /* prevent hanging header prints */ 01608 ED_area_headerprint(sa, NULL); 01609 } 01610 01611 if(sa && sa->full) { 01612 ScrArea *old; 01613 /*short fulltype;*/ /*UNUSED*/ 01614 01615 sc= sa->full; /* the old screen to restore */ 01616 oldscreen= win->screen; /* the one disappearing */ 01617 01618 /*fulltype = sc->full;*/ 01619 sc->full= 0; 01620 01621 /* removed: SCREENAUTOPLAY exception here */ 01622 01623 /* find old area */ 01624 for(old= sc->areabase.first; old; old= old->next) 01625 if(old->full) break; 01626 if(old==NULL) { 01627 if (G.f & G_DEBUG) 01628 printf("something wrong in areafullscreen\n"); 01629 return NULL; 01630 } 01631 01632 area_copy_data(old, sa, 1); /* 1 = swap spacelist */ 01633 if (sa->flag & AREA_TEMP_INFO) sa->flag &= ~AREA_TEMP_INFO; 01634 old->full= NULL; 01635 01636 /* animtimer back */ 01637 sc->animtimer= oldscreen->animtimer; 01638 oldscreen->animtimer= NULL; 01639 01640 ED_screen_set(C, sc); 01641 01642 free_screen(oldscreen); 01643 free_libblock(&CTX_data_main(C)->screen, oldscreen); 01644 01645 } 01646 else { 01647 ScrArea *newa; 01648 char newname[MAX_ID_NAME-2]; 01649 01650 oldscreen= win->screen; 01651 01652 /* nothing wrong with having only 1 area, as far as I can see... 01653 // is there only 1 area? 01654 if(oldscreen->areabase.first==oldscreen->areabase.last) 01655 return NULL; 01656 */ 01657 01658 oldscreen->full = SCREENFULL; 01659 BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name+2, "full"); 01660 sc= ED_screen_add(win, oldscreen->scene, newname); 01661 sc->full = SCREENFULL; // XXX 01662 01663 /* timer */ 01664 sc->animtimer= oldscreen->animtimer; 01665 oldscreen->animtimer= NULL; 01666 01667 /* returns the top small area */ 01668 newa= area_split(sc, (ScrArea *)sc->areabase.first, 'h', 0.99f, 1); 01669 ED_area_newspace(C, newa, SPACE_INFO); 01670 01671 /* use random area when we have no active one, e.g. when the 01672 mouse is outside of the window and we open a file browser */ 01673 if(!sa) 01674 sa= oldscreen->areabase.first; 01675 01676 /* copy area */ 01677 newa= newa->prev; 01678 area_copy_data(newa, sa, 1); /* 1 = swap spacelist */ 01679 sa->flag |= AREA_TEMP_INFO; 01680 01681 sa->full= oldscreen; 01682 newa->full= oldscreen; 01683 newa->next->full= oldscreen; // XXX 01684 01685 ED_screen_set(C, sc); 01686 } 01687 01688 /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */ 01689 CTX_wm_area_set(C, sc->areabase.first); 01690 01691 /* XXX retopo_force_update(); */ 01692 01693 return sc->areabase.first; 01694 } 01695 01696 /* update frame rate info for viewport drawing */ 01697 void ED_refresh_viewport_fps(bContext *C) 01698 { 01699 wmTimer *animtimer= CTX_wm_screen(C)->animtimer; 01700 Scene *scene= CTX_data_scene(C); 01701 01702 /* is anim playback running? */ 01703 if (animtimer && (U.uiflag & USER_SHOW_FPS)) { 01704 ScreenFrameRateInfo *fpsi= scene->fps_info; 01705 01706 /* if there isn't any info, init it first */ 01707 if (fpsi == NULL) 01708 fpsi= scene->fps_info= MEM_callocN(sizeof(ScreenFrameRateInfo), "refresh_viewport_fps fps_info"); 01709 01710 /* update the values */ 01711 fpsi->redrawtime= fpsi->lredrawtime; 01712 fpsi->lredrawtime= animtimer->ltime; 01713 } 01714 else { 01715 /* playback stopped or shouldn't be running */ 01716 if (scene->fps_info) 01717 MEM_freeN(scene->fps_info); 01718 scene->fps_info= NULL; 01719 } 01720 } 01721 01722 /* redraws: uses defines from stime->redraws 01723 * enable: 1 - forward on, -1 - backwards on, 0 - off 01724 */ 01725 void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable) 01726 { 01727 bScreen *screen= CTX_wm_screen(C); 01728 wmWindowManager *wm= CTX_wm_manager(C); 01729 wmWindow *win= CTX_wm_window(C); 01730 Scene *scene= CTX_data_scene(C); 01731 01732 if(screen->animtimer) 01733 WM_event_remove_timer(wm, win, screen->animtimer); 01734 screen->animtimer= NULL; 01735 01736 if(enable) { 01737 ScreenAnimData *sad= MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData"); 01738 01739 screen->animtimer= WM_event_add_timer(wm, win, TIMER0, (1.0/FPS)); 01740 01741 sad->ar= CTX_wm_region(C); 01742 sad->sfra = scene->r.cfra; 01743 sad->redraws= redraws; 01744 sad->refresh= refresh; 01745 sad->flag |= (enable < 0)? ANIMPLAY_FLAG_REVERSE: 0; 01746 sad->flag |= (sync == 0)? ANIMPLAY_FLAG_NO_SYNC: (sync == 1)? ANIMPLAY_FLAG_SYNC: 0; 01747 01748 screen->animtimer->customdata= sad; 01749 01750 } 01751 /* notifier catched by top header, for button */ 01752 WM_event_add_notifier(C, NC_SCREEN|ND_ANIMPLAY, screen); 01753 } 01754 01755 /* helper for screen_animation_play() - only to be used for TimeLine */ 01756 static ARegion *time_top_left_3dwindow(bScreen *screen) 01757 { 01758 ARegion *aret= NULL; 01759 ScrArea *sa; 01760 int min= 10000; 01761 01762 for(sa= screen->areabase.first; sa; sa= sa->next) { 01763 if(sa->spacetype==SPACE_VIEW3D) { 01764 ARegion *ar; 01765 for(ar= sa->regionbase.first; ar; ar= ar->next) { 01766 if(ar->regiontype==RGN_TYPE_WINDOW) { 01767 if(ar->winrct.xmin - ar->winrct.ymin < min) { 01768 aret= ar; 01769 min= ar->winrct.xmin - ar->winrct.ymin; 01770 } 01771 } 01772 } 01773 } 01774 } 01775 01776 return aret; 01777 } 01778 01779 void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh) 01780 { 01781 if(screen && screen->animtimer) { 01782 wmTimer *wt= screen->animtimer; 01783 ScreenAnimData *sad= wt->customdata; 01784 01785 sad->redraws= redraws; 01786 sad->refresh= refresh; 01787 sad->ar= NULL; 01788 if(redraws & TIME_REGION) 01789 sad->ar= time_top_left_3dwindow(screen); 01790 } 01791 } 01792 01793 /* results in fully updated anim system 01794 * screen can be NULL */ 01795 void ED_update_for_newframe(Main *bmain, Scene *scene, bScreen *screen, int UNUSED(mute)) 01796 { 01797 #ifdef DURIAN_CAMERA_SWITCH 01798 void *camera= scene_camera_switch_find(scene); 01799 if(camera && scene->camera != camera) { 01800 bScreen *sc; 01801 scene->camera= camera; 01802 /* are there cameras in the views that are not in the scene? */ 01803 for(sc= bmain->screen.first; sc; sc= sc->id.next) { 01804 BKE_screen_view3d_scene_sync(sc); 01805 } 01806 } 01807 #endif 01808 01809 //extern void audiostream_scrub(unsigned int frame); /* seqaudio.c */ 01810 01811 /* update animated image textures for gpu, etc, 01812 * call before scene_update_for_newframe so modifiers with textuers dont lag 1 frame */ 01813 ED_image_update_frame(bmain, scene->r.cfra); 01814 01815 /* this function applies the changes too */ 01816 /* XXX future: do all windows */ 01817 scene_update_for_newframe(bmain, scene, BKE_screen_visible_layers(screen, scene)); /* BKE_scene.h */ 01818 01819 //if ( (CFRA>1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB)) 01820 // audiostream_scrub( CFRA ); 01821 01822 /* 3d window, preview */ 01823 //BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); 01824 01825 /* all movie/sequence images */ 01826 //BIF_image_update_frame(); 01827 01828 /* composite */ 01829 if(scene->use_nodes && scene->nodetree) 01830 ntreeCompositTagAnimated(scene->nodetree); 01831 01832 /* update animated texture nodes */ 01833 { 01834 Tex *tex; 01835 for(tex= bmain->tex.first; tex; tex= tex->id.next) 01836 if( tex->use_nodes && tex->nodetree ) { 01837 ntreeTexTagAnimated( tex->nodetree ); 01838 } 01839 } 01840 01841 } 01842 01843