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