Blender V2.61 - r43446

space_time.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2008 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * 
00022  * Contributor(s): Blender Foundation
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <string.h>
00033 #include <stdio.h>
00034 
00035 #include "DNA_object_types.h"
00036 #include "DNA_scene_types.h"
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "BLI_blenlib.h"
00041 #include "BLI_dlrbTree.h"
00042 #include "BLI_utildefines.h"
00043 
00044 #include "BKE_context.h"
00045 #include "BKE_global.h"
00046 #include "BKE_screen.h"
00047 #include "BKE_pointcache.h"
00048 
00049 #include "ED_anim_api.h"
00050 #include "ED_keyframes_draw.h"
00051 #include "ED_screen.h"
00052 
00053 #include "WM_api.h"
00054 #include "WM_types.h"
00055 
00056 #include "BIF_gl.h"
00057 #include "BIF_glutil.h"
00058 
00059 #include "UI_resources.h"
00060 #include "UI_view2d.h"
00061 
00062 #include "ED_space_api.h"
00063 #include "ED_markers.h"
00064 
00065 #include "time_intern.h"
00066 
00067 /* ************************ main time area region *********************** */
00068 
00069 static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
00070 {   
00071     /* draw darkened area outside of active timeline 
00072      * frame range used is preview range or scene range 
00073      */
00074     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00075     glEnable(GL_BLEND);
00076         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
00077         
00078         if (PSFRA < PEFRA) {
00079             glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
00080             glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
00081         }
00082         else {
00083             glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
00084         }
00085     glDisable(GL_BLEND);
00086 
00087     UI_ThemeColorShade(TH_BACK, -60);
00088     /* thin lines where the actual frames are */
00089     fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
00090     fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
00091 }
00092 
00093 #define CACHE_DRAW_HEIGHT   3.0f
00094 
00095 static void time_draw_cache(SpaceTime *stime, Object *ob)
00096 {
00097     PTCacheID *pid;
00098     ListBase pidlist;
00099     SpaceTimeCache *stc = stime->caches.first;
00100     float yoffs=0.f;
00101     
00102     if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
00103         return;
00104 
00105     BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
00106 
00107     /* iterate over pointcaches on the active object, 
00108      * add spacetimecache and vertex array for each */
00109     for(pid=pidlist.first; pid; pid=pid->next) {
00110         float col[4], *fp;
00111         int i, sta = pid->cache->startframe, end = pid->cache->endframe;
00112         int len = (end - sta + 1)*4;
00113 
00114         switch(pid->type) {
00115             case PTCACHE_TYPE_SOFTBODY:
00116                 if (!(stime->cache_display & TIME_CACHE_SOFTBODY)) continue;
00117                 break;
00118             case PTCACHE_TYPE_PARTICLES:
00119                 if (!(stime->cache_display & TIME_CACHE_PARTICLES)) continue;
00120                 break;
00121             case PTCACHE_TYPE_CLOTH:
00122                 if (!(stime->cache_display & TIME_CACHE_CLOTH)) continue;
00123                 break;
00124             case PTCACHE_TYPE_SMOKE_DOMAIN:
00125             case PTCACHE_TYPE_SMOKE_HIGHRES:
00126                 if (!(stime->cache_display & TIME_CACHE_SMOKE)) continue;
00127                 break;
00128             case PTCACHE_TYPE_DYNAMICPAINT:
00129                 if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT))  continue;
00130                 break;
00131         }
00132 
00133         if(pid->cache->cached_frames == NULL)
00134             continue;
00135 
00136         /* make sure we have stc with correct array length */
00137         if(stc == NULL || MEM_allocN_len(stc->array) != len*2*sizeof(float)) {
00138             if(stc) {
00139                 MEM_freeN(stc->array);
00140             }
00141             else {
00142                 stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache");
00143                 BLI_addtail(&stime->caches, stc);
00144             }
00145 
00146             stc->array = MEM_callocN(len*2*sizeof(float), "SpaceTimeCache array");
00147         }
00148 
00149         /* fill the vertex array with a quad for each cached frame */
00150         for (i=sta, fp=stc->array; i<=end; i++) {
00151             if (pid->cache->cached_frames[i-sta]) {
00152                 fp[0] = (float)i-0.5f;
00153                 fp[1] = 0.0;
00154                 fp+=2;
00155                 
00156                 fp[0] = (float)i-0.5f;
00157                 fp[1] = 1.0;
00158                 fp+=2;
00159                 
00160                 fp[0] = (float)i+0.5f;
00161                 fp[1] = 1.0;
00162                 fp+=2;
00163                 
00164                 fp[0] = (float)i+0.5f;
00165                 fp[1] = 0.0;
00166                 fp+=2;
00167             }
00168         }
00169         
00170         glPushMatrix();
00171         glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT+yoffs, 0.0);
00172         glScalef(1.0, CACHE_DRAW_HEIGHT, 0.0);
00173         
00174         switch(pid->type) {
00175             case PTCACHE_TYPE_SOFTBODY:
00176                 col[0] = 1.0;   col[1] = 0.4;   col[2] = 0.02;
00177                 col[3] = 0.1;
00178                 break;
00179             case PTCACHE_TYPE_PARTICLES:
00180                 col[0] = 1.0;   col[1] = 0.1;   col[2] = 0.02;
00181                 col[3] = 0.1;
00182                 break;
00183             case PTCACHE_TYPE_CLOTH:
00184                 col[0] = 0.1;   col[1] = 0.1;   col[2] = 0.75;
00185                 col[3] = 0.1;
00186                 break;
00187             case PTCACHE_TYPE_SMOKE_DOMAIN:
00188             case PTCACHE_TYPE_SMOKE_HIGHRES:
00189                 col[0] = 0.2;   col[1] = 0.2;   col[2] = 0.2;
00190                 col[3] = 0.1;
00191                 break;
00192             case PTCACHE_TYPE_DYNAMICPAINT:
00193                 col[0] = 1.0;   col[1] = 0.1;   col[2] = 0.75;
00194                 col[3] = 0.1;
00195                 break;
00196         }
00197         glColor4fv(col);
00198         
00199         glEnable(GL_BLEND);
00200         
00201         glRectf((float)sta, 0.0, (float)end, 1.0);
00202         
00203         col[3] = 0.4f;
00204         if (pid->cache->flag & PTCACHE_BAKED) {
00205             col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
00206         }
00207         glColor4fv(col);
00208         
00209         glEnableClientState(GL_VERTEX_ARRAY);
00210         glVertexPointer(2, GL_FLOAT, 0, stc->array);
00211         glDrawArrays(GL_QUADS, 0, (fp-stc->array)/2);
00212         glDisableClientState(GL_VERTEX_ARRAY);
00213         
00214         glDisable(GL_BLEND);
00215         
00216         glPopMatrix();
00217         
00218         yoffs += CACHE_DRAW_HEIGHT;
00219 
00220         stc = stc->next;
00221     }
00222 
00223     BLI_freelistN(&pidlist);
00224 
00225     /* free excessive caches */
00226     while(stc) {
00227         SpaceTimeCache *tmp = stc->next;
00228         BLI_remlink(&stime->caches, stc);
00229         MEM_freeN(stc->array);
00230         MEM_freeN(stc);
00231         stc = tmp;
00232     }
00233 }
00234 
00235 static void time_cache_free(SpaceTime *stime)
00236 {
00237     SpaceTimeCache *stc;
00238     
00239     for (stc= stime->caches.first; stc; stc=stc->next) {
00240         if (stc->array) {
00241             MEM_freeN(stc->array);
00242             stc->array = NULL;
00243         }
00244     }
00245     
00246     BLI_freelistN(&stime->caches);
00247 }
00248 
00249 static void time_cache_refresh(SpaceTime *stime)
00250 {
00251     /* Free previous caches to indicate full refresh */
00252     time_cache_free(stime);
00253 }
00254 
00255 /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
00256 static ActKeyColumn *time_cfra_find_ak (ActKeyColumn *ak, float cframe)
00257 {
00258     ActKeyColumn *akn= NULL;
00259     
00260     /* sanity checks */
00261     if (ak == NULL)
00262         return NULL;
00263     
00264     /* check if this is a match, or whether it is in some subtree */
00265     if (cframe < ak->cfra)
00266         akn= time_cfra_find_ak(ak->left, cframe);
00267     else if (cframe > ak->cfra)
00268         akn= time_cfra_find_ak(ak->right, cframe);
00269         
00270     /* if no match found (or found match), just use the current one */
00271     if (akn == NULL)
00272         return ak;
00273     else
00274         return akn;
00275 }
00276 
00277 /* helper for time_draw_keyframes() */
00278 static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
00279 {
00280     bDopeSheet ads= {NULL};
00281     DLRBT_Tree keys;
00282     ActKeyColumn *ak;
00283     
00284     /* init binarytree-list for getting keyframes */
00285     BLI_dlrbTree_init(&keys);
00286     
00287     /* init dopesheet settings */
00288     if (onlysel)
00289         ads.filterflag |= ADS_FILTER_ONLYSEL;
00290     
00291     /* populate tree with keyframe nodes */
00292     switch (GS(id->name)) {
00293         case ID_SCE:
00294             scene_to_keylist(&ads, (Scene *)id, &keys, NULL);
00295             break;
00296         case ID_OB:
00297             ob_to_keylist(&ads, (Object *)id, &keys, NULL);
00298             break;
00299     }
00300         
00301     /* build linked-list for searching */
00302     BLI_dlrbTree_linkedlist_sync(&keys);
00303     
00304     /* start drawing keyframes 
00305      *  - we use the binary-search capabilities of the tree to only start from 
00306      *    the first visible keyframe (last one can then be easily checked)
00307      *  - draw within a single GL block to be faster
00308      */
00309     glBegin(GL_LINES);
00310         for ( ak=time_cfra_find_ak(keys.root, v2d->cur.xmin); 
00311              (ak) && (ak->cfra <= v2d->cur.xmax); 
00312               ak=ak->next ) 
00313         {
00314             glVertex2f(ak->cfra, v2d->tot.ymin);
00315             glVertex2f(ak->cfra, v2d->tot.ymax);
00316         }
00317     glEnd(); // GL_LINES
00318         
00319     /* free temp stuff */
00320     BLI_dlrbTree_free(&keys);
00321 }
00322 
00323 /* draw keyframe lines for timeline */
00324 static void time_draw_keyframes(const bContext *C, SpaceTime *stime, ARegion *ar)
00325 {
00326     Scene *scene= CTX_data_scene(C);
00327     Object *ob= CTX_data_active_object(C);
00328     View2D *v2d= &ar->v2d;
00329     short onlysel= (stime->flag & TIME_ONLYACTSEL);
00330     
00331     /* draw scene keyframes first 
00332      *  - don't try to do this when only drawing active/selected data keyframes,
00333      *    since this can become quite slow
00334      */
00335     if (scene && onlysel==0) {
00336         /* set draw color */
00337         glColor3ub(0xDD, 0xA7, 0x00);
00338         time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel);
00339     }
00340     
00341     /* draw keyframes from selected objects 
00342      *  - only do the active object if in posemode (i.e. showing only keyframes for the bones)
00343      *    OR the onlysel flag was set, which means that only active object's keyframes should
00344      *    be considered
00345      */
00346     glColor3ub(0xDD, 0xD7, 0x00);
00347     
00348     if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) {
00349         /* draw keyframes for active object only */
00350         time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel);
00351     }
00352     else {
00353         short active_done = 0;
00354         
00355         /* draw keyframes from all selected objects */
00356         CTX_DATA_BEGIN(C, Object*, obsel, selected_objects) 
00357         {
00358             /* last arg is 0, since onlysel doesn't apply here... */
00359             time_draw_idblock_keyframes(v2d, (ID *)obsel, 0);
00360             
00361             /* if this object is the active one, set flag so that we don't draw again */
00362             if (obsel == ob)
00363                 active_done= 1;
00364         }
00365         CTX_DATA_END;
00366         
00367         /* if active object hasn't been done yet, draw it... */
00368         if (ob && (active_done == 0))
00369             time_draw_idblock_keyframes(v2d, (ID *)ob, 0);
00370     }
00371 }
00372 
00373 /* ---------------- */
00374 
00375 static void time_refresh(const bContext *UNUSED(C), ScrArea *sa)
00376 {
00377     /* find the main timeline region and refresh cache display*/
00378     ARegion *ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
00379     if(ar) {
00380         SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
00381         time_cache_refresh(stime);
00382     }
00383 }
00384 
00385 /* editor level listener */
00386 static void time_listener(ScrArea *sa, wmNotifier *wmn)
00387 {
00388 
00389     /* mainly for updating cache display */
00390     switch (wmn->category) {
00391         case NC_OBJECT:
00392             switch (wmn->data) {
00393                 case ND_BONE_ACTIVE:
00394                 case ND_POINTCACHE:
00395                 case ND_MODIFIER:
00396                 case ND_PARTICLE:
00397                     ED_area_tag_refresh(sa);
00398                     ED_area_tag_redraw(sa);
00399                     break;
00400             }
00401             break;
00402         case NC_SCENE:
00403             switch (wmn->data) {
00404                 case ND_OB_ACTIVE:
00405                 case ND_FRAME:
00406                     ED_area_tag_refresh(sa);
00407                     break;
00408                 case ND_FRAME_RANGE:
00409                     {
00410                         ARegion *ar;
00411                         Scene *scene = wmn->reference;
00412 
00413                         for (ar= sa->regionbase.first; ar; ar= ar->next) {
00414                             if (ar->regiontype==RGN_TYPE_WINDOW) {
00415                                 ar->v2d.tot.xmin= (float)(SFRA - 4);
00416                                 ar->v2d.tot.xmax= (float)(EFRA + 4);
00417                                 break;
00418                             }
00419                         }
00420                     }
00421                     break;
00422             }
00423         case NC_SPACE:
00424             switch (wmn->data) {
00425                 case ND_SPACE_CHANGED:
00426                     ED_area_tag_refresh(sa);
00427                     break;
00428             }
00429         case NC_WM:
00430             switch (wmn->data) {
00431                 case ND_FILEREAD:
00432                     ED_area_tag_refresh(sa);
00433                     break;
00434             }
00435     }
00436 }
00437 
00438 /* ---------------- */
00439 
00440 /* add handlers, stuff you only do once or on area/region changes */
00441 static void time_main_area_init(wmWindowManager *wm, ARegion *ar)
00442 {
00443     wmKeyMap *keymap;
00444     
00445     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
00446     
00447     /* own keymap */
00448     keymap= WM_keymap_find(wm->defaultconf, "Timeline", SPACE_TIME, 0);
00449     WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00450 }
00451 
00452 static void time_main_area_draw(const bContext *C, ARegion *ar)
00453 {
00454     /* draw entirely, view changes should be handled here */
00455     Scene *scene= CTX_data_scene(C);
00456     SpaceTime *stime= CTX_wm_space_time(C);
00457     Object *obact = CTX_data_active_object(C);
00458     View2D *v2d= &ar->v2d;
00459     View2DGrid *grid;
00460     View2DScrollers *scrollers;
00461     int unit, flag=0;
00462     
00463     /* clear and setup matrix */
00464     UI_ThemeClearColor(TH_BACK);
00465     glClear(GL_COLOR_BUFFER_BIT);
00466     
00467     UI_view2d_view_ortho(v2d);
00468     
00469     /* grid */
00470     unit= (stime->flag & TIME_DRAWFRAMES)? V2D_UNIT_FRAMES: V2D_UNIT_SECONDS;
00471     grid= UI_view2d_grid_calc(scene, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
00472     UI_view2d_grid_draw(v2d, grid, (V2D_VERTICAL_LINES|V2D_VERTICAL_AXIS));
00473     UI_view2d_grid_free(grid);
00474     
00475     /* start and end frame */
00476     time_draw_sfra_efra(scene, v2d);
00477     
00478     /* current frame */
00479     flag = DRAWCFRA_WIDE; /* this is only really needed on frames where there's a keyframe, but this will do... */
00480     if ((stime->flag & TIME_DRAWFRAMES)==0)     flag |= DRAWCFRA_UNIT_SECONDS;
00481     if (stime->flag & TIME_CFRA_NUM)            flag |= DRAWCFRA_SHOW_NUMBOX;
00482     ANIM_draw_cfra(C, v2d, flag);
00483     
00484     UI_view2d_view_ortho(v2d);
00485     
00486     /* keyframes */
00487     time_draw_keyframes(C, stime, ar);
00488     
00489     /* markers */
00490     UI_view2d_view_orthoSpecial(ar, v2d, 1);
00491     draw_markers_time(C, 0);
00492     
00493     /* caches */
00494     time_draw_cache(stime, obact);
00495     
00496     /* reset view matrix */
00497     UI_view2d_view_restore(C);
00498     
00499     /* scrollers */
00500     scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00501     UI_view2d_scrollers_draw(C, v2d, scrollers);
00502     UI_view2d_scrollers_free(scrollers);
00503 }
00504 
00505 static void time_main_area_listener(ARegion *ar, wmNotifier *wmn)
00506 {
00507     /* context changes */
00508     switch(wmn->category) {
00509         case NC_SPACE:
00510             if(wmn->data == ND_SPACE_TIME)
00511                 ED_region_tag_redraw(ar);
00512             break;
00513 
00514         case NC_ANIMATION:
00515             ED_region_tag_redraw(ar);
00516             break;
00517         
00518         case NC_SCENE:
00519             switch (wmn->data) {
00520                 case ND_OB_SELECT:
00521                 case ND_OB_ACTIVE:
00522                 case ND_FRAME:
00523                 case ND_FRAME_RANGE:
00524                 case ND_KEYINGSET:
00525                 case ND_RENDER_OPTIONS:
00526                     ED_region_tag_redraw(ar);
00527                 break;
00528             }
00529     }
00530 }
00531 
00532 /* ************************ header time area region *********************** */
00533 
00534 /* add handlers, stuff you only do once or on area/region changes */
00535 static void time_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
00536 {
00537     ED_region_header_init(ar);
00538 }
00539 
00540 static void time_header_area_draw(const bContext *C, ARegion *ar)
00541 {
00542     ED_region_header(C, ar);
00543 }
00544 
00545 static void time_header_area_listener(ARegion *ar, wmNotifier *wmn)
00546 {
00547     /* context changes */
00548     switch(wmn->category) {
00549         case NC_SCREEN:
00550             if(wmn->data==ND_ANIMPLAY)
00551                 ED_region_tag_redraw(ar);
00552             break;
00553 
00554         case NC_SCENE:
00555             switch (wmn->data) {
00556                 case ND_OB_SELECT:
00557                 case ND_FRAME:
00558                 case ND_FRAME_RANGE:
00559                 case ND_KEYINGSET:
00560                 case ND_RENDER_OPTIONS:
00561                     ED_region_tag_redraw(ar);
00562                 break;
00563             }
00564 
00565         case NC_SPACE:
00566             if(wmn->data == ND_SPACE_TIME)
00567                 ED_region_tag_redraw(ar);
00568             break;
00569     }
00570 }
00571 
00572 /* ******************** default callbacks for time space ***************** */
00573 
00574 static SpaceLink *time_new(const bContext *C)
00575 {
00576     Scene *scene= CTX_data_scene(C);
00577     ARegion *ar;
00578     SpaceTime *stime;
00579 
00580     stime= MEM_callocN(sizeof(SpaceTime), "inittime");
00581 
00582     stime->spacetype= SPACE_TIME;
00583     stime->flag |= TIME_DRAWFRAMES;
00584 
00585     /* header */
00586     ar= MEM_callocN(sizeof(ARegion), "header for time");
00587     
00588     BLI_addtail(&stime->regionbase, ar);
00589     ar->regiontype= RGN_TYPE_HEADER;
00590     ar->alignment= RGN_ALIGN_BOTTOM;
00591     
00592     /* main area */
00593     ar= MEM_callocN(sizeof(ARegion), "main area for time");
00594     
00595     BLI_addtail(&stime->regionbase, ar);
00596     ar->regiontype= RGN_TYPE_WINDOW;
00597     
00598     ar->v2d.tot.xmin= (float)(SFRA - 4);
00599     ar->v2d.tot.ymin= 0.0f;
00600     ar->v2d.tot.xmax= (float)(EFRA + 4);
00601     ar->v2d.tot.ymax= 50.0f;
00602     
00603     ar->v2d.cur= ar->v2d.tot;
00604 
00605     ar->v2d.min[0]= 1.0f;
00606     ar->v2d.min[1]= 50.0f;
00607 
00608     ar->v2d.max[0]= MAXFRAMEF;
00609     ar->v2d.max[1]= 50.0; 
00610 
00611     ar->v2d.minzoom= 0.1f;
00612     ar->v2d.maxzoom= 10.0;
00613 
00614     ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
00615     ar->v2d.align |= V2D_ALIGN_NO_NEG_Y;
00616     ar->v2d.keepofs |= V2D_LOCKOFS_Y;
00617     ar->v2d.keepzoom |= V2D_LOCKZOOM_Y;
00618 
00619 
00620     return (SpaceLink*)stime;
00621 }
00622 
00623 /* not spacelink itself */
00624 static void time_free(SpaceLink *sl)
00625 {
00626     SpaceTime *stime= (SpaceTime *)sl;
00627     
00628     time_cache_free(stime);
00629 }
00630 /* spacetype; init callback in ED_area_initialize() */
00631 /* init is called to (re)initialize an existing editor (file read, screen changes) */
00632 /* validate spacedata, add own area level handlers */
00633 static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
00634 {
00635     SpaceTime *stime= (SpaceTime *)sa->spacedata.first;
00636     
00637     time_cache_free(stime);
00638     
00639     /* enable all cache display */
00640     stime->cache_display |= TIME_CACHE_DISPLAY;
00641     stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES);
00642     stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE|TIME_CACHE_DYNAMICPAINT);
00643 }
00644 
00645 static SpaceLink *time_duplicate(SpaceLink *sl)
00646 {
00647     SpaceTime *stime= (SpaceTime *)sl;
00648     SpaceTime *stimen= MEM_dupallocN(stime);
00649     
00650     stimen->caches.first = stimen->caches.last = NULL;
00651     
00652     return (SpaceLink *)stimen;
00653 }
00654 
00655 /* only called once, from space_api/spacetypes.c */
00656 /* it defines all callbacks to maintain spaces */
00657 void ED_spacetype_time(void)
00658 {
00659     SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype time");
00660     ARegionType *art;
00661     
00662     st->spaceid= SPACE_TIME;
00663     strncpy(st->name, "Timeline", BKE_ST_MAXNAME);
00664     
00665     st->new= time_new;
00666     st->free= time_free;
00667     st->init= time_init;
00668     st->duplicate= time_duplicate;
00669     st->operatortypes= time_operatortypes;
00670     st->keymap= NULL;
00671     st->listener= time_listener;
00672     st->refresh= time_refresh;
00673     
00674     /* regions: main window */
00675     art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
00676     art->regionid = RGN_TYPE_WINDOW;
00677     art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
00678     
00679     art->init= time_main_area_init;
00680     art->draw= time_main_area_draw;
00681     art->listener= time_main_area_listener;
00682     art->keymap= time_keymap;
00683     BLI_addhead(&st->regiontypes, art);
00684     
00685     /* regions: header */
00686     art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
00687     art->regionid = RGN_TYPE_HEADER;
00688     art->prefsizey= HEADERY;
00689     art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
00690     
00691     art->init= time_header_area_init;
00692     art->draw= time_header_area_draw;
00693     art->listener= time_header_area_listener;
00694     BLI_addhead(&st->regiontypes, art);
00695         
00696     BKE_spacetype_register(st);
00697 }
00698