Blender V2.61 - r43446
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00033 #include "BLI_winstuff.h" 00034 00035 #include <string.h> 00036 #include <stdio.h> 00037 #include <math.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "DNA_scene_types.h" 00042 #include "DNA_screen_types.h" 00043 #include "DNA_space_types.h" 00044 #include "DNA_view3d_types.h" 00045 00046 #include "BLI_blenlib.h" 00047 00048 #include "BKE_screen.h" 00049 00050 /* ************ Spacetype/regiontype handling ************** */ 00051 00052 /* keep global; this has to be accessible outside of windowmanager */ 00053 static ListBase spacetypes= {NULL, NULL}; 00054 00055 /* not SpaceType itself */ 00056 static void spacetype_free(SpaceType *st) 00057 { 00058 ARegionType *art; 00059 PanelType *pt; 00060 HeaderType *ht; 00061 00062 for(art= st->regiontypes.first; art; art= art->next) { 00063 BLI_freelistN(&art->drawcalls); 00064 00065 for(pt= art->paneltypes.first; pt; pt= pt->next) 00066 if(pt->ext.free) 00067 pt->ext.free(pt->ext.data); 00068 00069 for(ht= art->headertypes.first; ht; ht= ht->next) 00070 if(ht->ext.free) 00071 ht->ext.free(ht->ext.data); 00072 00073 BLI_freelistN(&art->paneltypes); 00074 BLI_freelistN(&art->headertypes); 00075 } 00076 00077 BLI_freelistN(&st->regiontypes); 00078 BLI_freelistN(&st->toolshelf); 00079 00080 } 00081 00082 void BKE_spacetypes_free(void) 00083 { 00084 SpaceType *st; 00085 00086 for(st= spacetypes.first; st; st= st->next) { 00087 spacetype_free(st); 00088 } 00089 00090 BLI_freelistN(&spacetypes); 00091 } 00092 00093 SpaceType *BKE_spacetype_from_id(int spaceid) 00094 { 00095 SpaceType *st; 00096 00097 for(st= spacetypes.first; st; st= st->next) { 00098 if(st->spaceid==spaceid) 00099 return st; 00100 } 00101 return NULL; 00102 } 00103 00104 ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) 00105 { 00106 ARegionType *art; 00107 00108 for(art= st->regiontypes.first; art; art= art->next) 00109 if(art->regionid==regionid) 00110 return art; 00111 00112 printf("Error, region type missing in - name:\"%s\", id:%d\n", st->name, st->spaceid); 00113 return st->regiontypes.first; 00114 } 00115 00116 00117 const ListBase *BKE_spacetypes_list(void) 00118 { 00119 return &spacetypes; 00120 } 00121 00122 void BKE_spacetype_register(SpaceType *st) 00123 { 00124 SpaceType *stype; 00125 00126 /* sanity check */ 00127 stype= BKE_spacetype_from_id(st->spaceid); 00128 if(stype) { 00129 printf("error: redefinition of spacetype %s\n", stype->name); 00130 spacetype_free(stype); 00131 MEM_freeN(stype); 00132 } 00133 00134 BLI_addtail(&spacetypes, st); 00135 } 00136 00137 /* ***************** Space handling ********************** */ 00138 00139 void BKE_spacedata_freelist(ListBase *lb) 00140 { 00141 SpaceLink *sl; 00142 ARegion *ar; 00143 00144 for (sl= lb->first; sl; sl= sl->next) { 00145 SpaceType *st= BKE_spacetype_from_id(sl->spacetype); 00146 00147 /* free regions for pushed spaces */ 00148 for(ar=sl->regionbase.first; ar; ar=ar->next) 00149 BKE_area_region_free(st, ar); 00150 00151 BLI_freelistN(&sl->regionbase); 00152 00153 if(st && st->free) 00154 st->free(sl); 00155 } 00156 00157 BLI_freelistN(lb); 00158 } 00159 00160 ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) 00161 { 00162 ARegion *newar= MEM_dupallocN(ar); 00163 Panel *pa, *newpa, *patab; 00164 00165 newar->prev= newar->next= NULL; 00166 newar->handlers.first= newar->handlers.last= NULL; 00167 newar->uiblocks.first= newar->uiblocks.last= NULL; 00168 newar->swinid= 0; 00169 00170 /* use optional regiondata callback */ 00171 if(ar->regiondata) { 00172 ARegionType *art= BKE_regiontype_from_id(st, ar->regiontype); 00173 00174 if(art && art->duplicate) 00175 newar->regiondata= art->duplicate(ar->regiondata); 00176 else 00177 newar->regiondata= MEM_dupallocN(ar->regiondata); 00178 } 00179 00180 if(ar->v2d.tab_offset) 00181 newar->v2d.tab_offset= MEM_dupallocN(ar->v2d.tab_offset); 00182 00183 newar->panels.first= newar->panels.last= NULL; 00184 BLI_duplicatelist(&newar->panels, &ar->panels); 00185 00186 /* copy panel pointers */ 00187 for(newpa= newar->panels.first; newpa; newpa= newpa->next) { 00188 patab= newar->panels.first; 00189 pa= ar->panels.first; 00190 while(patab) { 00191 if(newpa->paneltab == pa) { 00192 newpa->paneltab = patab; 00193 break; 00194 } 00195 patab= patab->next; 00196 pa= pa->next; 00197 } 00198 } 00199 00200 return newar; 00201 } 00202 00203 00204 /* from lb2 to lb1, lb1 is supposed to be free'd */ 00205 static void region_copylist(SpaceType *st, ListBase *lb1, ListBase *lb2) 00206 { 00207 ARegion *ar; 00208 00209 /* to be sure */ 00210 lb1->first= lb1->last= NULL; 00211 00212 for(ar= lb2->first; ar; ar= ar->next) { 00213 ARegion *arnew= BKE_area_region_copy(st, ar); 00214 BLI_addtail(lb1, arnew); 00215 } 00216 } 00217 00218 00219 /* lb1 should be empty */ 00220 void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2) 00221 { 00222 SpaceLink *sl; 00223 00224 lb1->first= lb1->last= NULL; /* to be sure */ 00225 00226 for (sl= lb2->first; sl; sl= sl->next) { 00227 SpaceType *st= BKE_spacetype_from_id(sl->spacetype); 00228 00229 if(st && st->duplicate) { 00230 SpaceLink *slnew= st->duplicate(sl); 00231 00232 BLI_addtail(lb1, slnew); 00233 00234 region_copylist(st, &slnew->regionbase, &sl->regionbase); 00235 } 00236 } 00237 } 00238 00239 /* facility to set locks for drawing to survive (render) threads accessing drawing data */ 00240 /* lock can become bitflag too */ 00241 /* should be replaced in future by better local data handling for threads */ 00242 void BKE_spacedata_draw_locks(int set) 00243 { 00244 SpaceType *st; 00245 00246 for(st= spacetypes.first; st; st= st->next) { 00247 ARegionType *art; 00248 00249 for(art= st->regiontypes.first; art; art= art->next) { 00250 if(set) 00251 art->do_lock= art->lock; 00252 else 00253 art->do_lock= 0; 00254 } 00255 } 00256 } 00257 00258 00259 /* not region itself */ 00260 void BKE_area_region_free(SpaceType *st, ARegion *ar) 00261 { 00262 if(st) { 00263 ARegionType *art= BKE_regiontype_from_id(st, ar->regiontype); 00264 00265 if(art && art->free) 00266 art->free(ar); 00267 00268 if(ar->regiondata) 00269 printf("regiondata free error\n"); 00270 } 00271 else if(ar->type && ar->type->free) 00272 ar->type->free(ar); 00273 00274 if(ar->v2d.tab_offset) { 00275 MEM_freeN(ar->v2d.tab_offset); 00276 ar->v2d.tab_offset= NULL; 00277 } 00278 00279 BLI_freelistN(&ar->panels); 00280 } 00281 00282 /* not area itself */ 00283 void BKE_screen_area_free(ScrArea *sa) 00284 { 00285 SpaceType *st= BKE_spacetype_from_id(sa->spacetype); 00286 ARegion *ar; 00287 00288 for(ar=sa->regionbase.first; ar; ar=ar->next) 00289 BKE_area_region_free(st, ar); 00290 00291 BLI_freelistN(&sa->regionbase); 00292 00293 BKE_spacedata_freelist(&sa->spacedata); 00294 00295 BLI_freelistN(&sa->actionzones); 00296 } 00297 00298 /* don't free screen itself */ 00299 void free_screen(bScreen *sc) 00300 { 00301 ScrArea *sa, *san; 00302 ARegion *ar; 00303 00304 for(ar=sc->regionbase.first; ar; ar=ar->next) 00305 BKE_area_region_free(NULL, ar); 00306 00307 BLI_freelistN(&sc->regionbase); 00308 00309 for(sa= sc->areabase.first; sa; sa= san) { 00310 san= sa->next; 00311 BKE_screen_area_free(sa); 00312 } 00313 00314 BLI_freelistN(&sc->vertbase); 00315 BLI_freelistN(&sc->edgebase); 00316 BLI_freelistN(&sc->areabase); 00317 } 00318 00319 /* for depsgraph */ 00320 unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene) 00321 { 00322 ScrArea *sa; 00323 unsigned int layer= 0; 00324 00325 if(screen) { 00326 /* get all used view3d layers */ 00327 for(sa= screen->areabase.first; sa; sa= sa->next) 00328 if(sa->spacetype==SPACE_VIEW3D) 00329 layer |= ((View3D *)sa->spacedata.first)->lay; 00330 } 00331 00332 if(!layer) 00333 return scene->lay; 00334 00335 return layer; 00336 } 00337 00338 /* ***************** Utilities ********************** */ 00339 00340 /* Find a region of the specified type from the given area */ 00341 ARegion *BKE_area_find_region_type(ScrArea *sa, int type) 00342 { 00343 if (sa) { 00344 ARegion *ar; 00345 00346 for (ar=sa->regionbase.first; ar; ar= ar->next) { 00347 if (ar->regiontype == type) 00348 return ar; 00349 } 00350 } 00351 return NULL; 00352 } 00353 00354 /* note, using this function is generally a last resort, you really want to be 00355 * using the context when you can - campbell 00356 * -1 for any type */ 00357 struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min) 00358 { 00359 ScrArea *sa, *big= NULL; 00360 int size, maxsize= 0; 00361 00362 for(sa= sc->areabase.first; sa; sa= sa->next) { 00363 if ((spacetype == -1) || sa->spacetype == spacetype) { 00364 if (min <= sa->winx && min <= sa->winy) { 00365 size= sa->winx*sa->winy; 00366 if (size > maxsize) { 00367 maxsize= size; 00368 big= sa; 00369 } 00370 } 00371 } 00372 } 00373 00374 return big; 00375 } 00376 00377 void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene) 00378 { 00379 int bit; 00380 00381 if(v3d->scenelock && v3d->localvd==NULL) { 00382 v3d->lay= scene->lay; 00383 v3d->camera= scene->camera; 00384 00385 if(v3d->camera==NULL) { 00386 ARegion *ar; 00387 00388 for(ar=v3d->regionbase.first; ar; ar= ar->next) { 00389 if(ar->regiontype == RGN_TYPE_WINDOW) { 00390 RegionView3D *rv3d= ar->regiondata; 00391 if(rv3d->persp==RV3D_CAMOB) 00392 rv3d->persp= RV3D_PERSP; 00393 } 00394 } 00395 } 00396 00397 if((v3d->lay & v3d->layact) == 0) { 00398 for(bit= 0; bit<32; bit++) { 00399 if(v3d->lay & (1<<bit)) { 00400 v3d->layact= 1<<bit; 00401 break; 00402 } 00403 } 00404 } 00405 } 00406 } 00407 00408 void BKE_screen_view3d_scene_sync(bScreen *sc) 00409 { 00410 /* are there cameras in the views that are not in the scene? */ 00411 ScrArea *sa; 00412 for(sa= sc->areabase.first; sa; sa= sa->next) { 00413 SpaceLink *sl; 00414 for(sl= sa->spacedata.first; sl; sl= sl->next) { 00415 if(sl->spacetype==SPACE_VIEW3D) { 00416 View3D *v3d= (View3D*) sl; 00417 BKE_screen_view3d_sync(v3d, sc->scene); 00418 } 00419 } 00420 } 00421 } 00422 00423 void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene) 00424 { 00425 bScreen *sc; 00426 ScrArea *sa; 00427 SpaceLink *sl; 00428 00429 /* from scene copy to the other views */ 00430 for(sc=screen_lb->first; sc; sc=sc->id.next) { 00431 if(sc->scene!=scene) 00432 continue; 00433 00434 for(sa=sc->areabase.first; sa; sa=sa->next) 00435 for(sl=sa->spacedata.first; sl; sl=sl->next) 00436 if(sl->spacetype==SPACE_VIEW3D) 00437 BKE_screen_view3d_sync((View3D*)sl, scene); 00438 } 00439 } 00440 00441 /* magic zoom calculation, no idea what 00442 * it signifies, if you find out, tell me! -zr 00443 */ 00444 00445 /* simple, its magic dude! 00446 * well, to be honest, this gives a natural feeling zooming 00447 * with multiple keypad presses (ton) 00448 */ 00449 float BKE_screen_view3d_zoom_to_fac(float camzoom) 00450 { 00451 return powf(((float)M_SQRT2 + camzoom/50.0f), 2.0f) / 4.0f; 00452 } 00453 00454 float BKE_screen_view3d_zoom_from_fac(float zoomfac) 00455 { 00456 return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f); 00457 }