Blender  V2.59
screen.c
Go to the documentation of this file.
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 }