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