Blender V2.61 - r43446

screen.c

Go to the documentation of this file.
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 }