Blender  V2.59
space_nla.c
Go to the documentation of this file.
00001 /*
00002  * $Id: space_nla.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_anim_types.h"
00038 #include "DNA_scene_types.h"
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_blenlib.h"
00043 #include "BLI_math.h"
00044 #include "BLI_rand.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_context.h"
00048 #include "BKE_global.h"
00049 #include "BKE_main.h"
00050 #include "BKE_screen.h"
00051 
00052 #include "ED_space_api.h"
00053 #include "ED_anim_api.h"
00054 #include "ED_markers.h"
00055 #include "ED_screen.h"
00056 
00057 #include "BIF_gl.h"
00058 
00059 #include "WM_api.h"
00060 #include "WM_types.h"
00061 
00062 #include "UI_resources.h"
00063 #include "UI_view2d.h"
00064 
00065 #include "nla_intern.h" // own include
00066 
00067 /* ******************** manage regions ********************* */
00068 
00069 ARegion *nla_has_buttons_region(ScrArea *sa)
00070 {
00071         ARegion *ar, *arnew;
00072 
00073         ar= BKE_area_find_region_type(sa, RGN_TYPE_UI);
00074         if(ar) return ar;
00075 
00076         /* add subdiv level; after main */
00077         ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
00078 
00079         /* is error! */
00080         if (ar==NULL) return NULL;
00081         
00082         arnew= MEM_callocN(sizeof(ARegion), "buttons for nla");
00083         
00084         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
00085         arnew->regiontype= RGN_TYPE_UI;
00086         arnew->alignment= RGN_ALIGN_RIGHT;
00087         
00088         arnew->flag = RGN_FLAG_HIDDEN;
00089         
00090         return arnew;
00091 }
00092 
00093 
00094 
00095 /* ******************** default callbacks for nla space ***************** */
00096 
00097 static SpaceLink *nla_new(const bContext *C)
00098 {
00099         Scene *scene= CTX_data_scene(C);
00100         ScrArea *sa= CTX_wm_area(C);
00101         ARegion *ar;
00102         SpaceNla *snla;
00103         
00104         snla= MEM_callocN(sizeof(SpaceNla), "initnla");
00105         snla->spacetype= SPACE_NLA;
00106         
00107         /* allocate DopeSheet data for NLA Editor */
00108         snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
00109         snla->ads->source= (ID *)scene;
00110         
00111         /* set auto-snapping settings */
00112         snla->autosnap = SACTSNAP_FRAME;
00113         
00114         /* header */
00115         ar= MEM_callocN(sizeof(ARegion), "header for nla");
00116         
00117         BLI_addtail(&snla->regionbase, ar);
00118         ar->regiontype= RGN_TYPE_HEADER;
00119         ar->alignment= RGN_ALIGN_BOTTOM;
00120         
00121         /* channel list region */
00122         ar= MEM_callocN(sizeof(ARegion), "channel list for nla");
00123         BLI_addtail(&snla->regionbase, ar);
00124         ar->regiontype= RGN_TYPE_CHANNELS;
00125         ar->alignment= RGN_ALIGN_LEFT;
00126         
00127                 /* only need to set these settings since this will use the 'stack' configuration */
00128         ar->v2d.scroll = V2D_SCROLL_BOTTOM;
00129         ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
00130         
00131         /* ui buttons */
00132         ar= MEM_callocN(sizeof(ARegion), "buttons area for nla");
00133         
00134         BLI_addtail(&snla->regionbase, ar);
00135         ar->regiontype= RGN_TYPE_UI;
00136         ar->alignment= RGN_ALIGN_RIGHT;
00137         ar->flag = RGN_FLAG_HIDDEN;
00138         
00139         /* main area */
00140         ar= MEM_callocN(sizeof(ARegion), "main area for nla");
00141         
00142         BLI_addtail(&snla->regionbase, ar);
00143         ar->regiontype= RGN_TYPE_WINDOW;
00144         
00145         ar->v2d.tot.xmin= (float)(SFRA-10);
00146         ar->v2d.tot.ymin= (float)(-sa->winy)/3.0f;
00147         ar->v2d.tot.xmax= (float)(EFRA+10);
00148         ar->v2d.tot.ymax= 0.0f;
00149         
00150         ar->v2d.cur = ar->v2d.tot;
00151         
00152         ar->v2d.min[0]= 0.0f;
00153         ar->v2d.min[1]= 0.0f;
00154         
00155         ar->v2d.max[0]= MAXFRAMEF;
00156         ar->v2d.max[1]= 10000.0f;
00157 
00158         ar->v2d.minzoom= 0.01f;
00159         ar->v2d.maxzoom= 50;
00160         ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
00161         ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
00162         ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
00163         ar->v2d.keepofs= V2D_KEEPOFS_Y;
00164         ar->v2d.align= V2D_ALIGN_NO_POS_Y;
00165         ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
00166         
00167         return (SpaceLink *)snla;
00168 }
00169 
00170 /* not spacelink itself */
00171 static void nla_free(SpaceLink *sl)
00172 {       
00173         SpaceNla *snla= (SpaceNla*) sl;
00174         
00175         if (snla->ads) {
00176                 BLI_freelistN(&snla->ads->chanbase);
00177                 MEM_freeN(snla->ads);
00178         }
00179 }
00180 
00181 
00182 /* spacetype; init callback */
00183 static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
00184 {
00185         SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
00186         
00187         /* init dopesheet data if non-existant (i.e. for old files) */
00188         if (snla->ads == NULL) {
00189                 snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
00190                 snla->ads->source= (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct
00191         }
00192 
00193         ED_area_tag_refresh(sa);
00194 }
00195 
00196 static SpaceLink *nla_duplicate(SpaceLink *sl)
00197 {
00198         SpaceNla *snlan= MEM_dupallocN(sl);
00199         
00200         /* clear or remove stuff from old */
00201         snlan->ads= MEM_dupallocN(snlan->ads);
00202         
00203         return (SpaceLink *)snlan;
00204 }
00205 
00206 /* add handlers, stuff you only do once or on area/region changes */
00207 static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar)
00208 {
00209         wmKeyMap *keymap;
00210         
00211         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
00212         
00213         /* own keymap */
00214                 /* own channels map first to override some channel keymaps */
00215         keymap= WM_keymap_find(wm->defaultconf, "NLA Channels", SPACE_NLA, 0);
00216         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00217                 /* now generic channels map for everything else that can apply */
00218         keymap= WM_keymap_find(wm->defaultconf, "Animation Channels", 0, 0);
00219         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00220         
00221         keymap= WM_keymap_find(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
00222         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00223 }
00224 
00225 /* draw entirely, view changes should be handled here */
00226 static void nla_channel_area_draw(const bContext *C, ARegion *ar)
00227 {
00228         bAnimContext ac;
00229         View2D *v2d= &ar->v2d;
00230         View2DScrollers *scrollers;
00231         
00232         /* clear and setup matrix */
00233         UI_ThemeClearColor(TH_BACK);
00234         glClear(GL_COLOR_BUFFER_BIT);
00235         
00236         UI_view2d_view_ortho(v2d);
00237         
00238         /* data */
00239         if (ANIM_animdata_get_context(C, &ac)) {
00240                 draw_nla_channel_list((bContext *)C, &ac, ar);
00241         }
00242         
00243         /* reset view matrix */
00244         UI_view2d_view_restore(C);
00245         
00246         /* scrollers */
00247         scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00248         UI_view2d_scrollers_draw(C, v2d, scrollers);
00249         UI_view2d_scrollers_free(scrollers);
00250 }
00251 
00252 
00253 /* add handlers, stuff you only do once or on area/region changes */
00254 static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
00255 {
00256         wmKeyMap *keymap;
00257         
00258         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
00259         
00260         /* own keymap */
00261         keymap= WM_keymap_find(wm->defaultconf, "NLA Editor", SPACE_NLA, 0);
00262         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00263         keymap= WM_keymap_find(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
00264         WM_event_add_keymap_handler(&ar->handlers, keymap);
00265 }
00266 
00267 static void nla_main_area_draw(const bContext *C, ARegion *ar)
00268 {
00269         /* draw entirely, view changes should be handled here */
00270         SpaceNla *snla= CTX_wm_space_nla(C);
00271         bAnimContext ac;
00272         View2D *v2d= &ar->v2d;
00273         View2DGrid *grid;
00274         View2DScrollers *scrollers;
00275         short unit=0, flag=0;
00276         
00277         /* clear and setup matrix */
00278         UI_ThemeClearColor(TH_BACK);
00279         glClear(GL_COLOR_BUFFER_BIT);
00280         
00281         UI_view2d_view_ortho(v2d);
00282         
00283         /* time grid */
00284         unit= (snla->flag & SNLA_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
00285         grid= UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
00286         UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
00287         UI_view2d_grid_free(grid);
00288         
00289         /* data */
00290         if (ANIM_animdata_get_context(C, &ac)) {
00291                 /* strips and backdrops */
00292                 draw_nla_main_data(&ac, snla, ar);
00293                 
00294                 /* text draw cached, in pixelspace now */
00295                 UI_view2d_text_cache_draw(ar);
00296         }
00297         
00298         UI_view2d_view_ortho(v2d);
00299         
00300         /* current frame */
00301         if (snla->flag & SNLA_DRAWTIME)         flag |= DRAWCFRA_UNIT_SECONDS;
00302         if ((snla->flag & SNLA_NODRAWCFRANUM)==0)  flag |= DRAWCFRA_SHOW_NUMBOX;
00303         ANIM_draw_cfra(C, v2d, flag);
00304         
00305         /* markers */
00306         UI_view2d_view_orthoSpecial(ar, v2d, 1);
00307         draw_markers_time(C, 0);
00308         
00309         /* preview range */
00310         UI_view2d_view_ortho(v2d);
00311         ANIM_draw_previewrange(C, v2d);
00312         
00313         /* reset view matrix */
00314         UI_view2d_view_restore(C);
00315         
00316         /* scrollers */
00317         scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00318         UI_view2d_scrollers_draw(C, v2d, scrollers);
00319         UI_view2d_scrollers_free(scrollers);
00320 }
00321 
00322 
00323 /* add handlers, stuff you only do once or on area/region changes */
00324 static void nla_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
00325 {
00326         ED_region_header_init(ar);
00327 }
00328 
00329 static void nla_header_area_draw(const bContext *C, ARegion *ar)
00330 {
00331         ED_region_header(C, ar);
00332 }
00333 
00334 /* add handlers, stuff you only do once or on area/region changes */
00335 static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
00336 {
00337         wmKeyMap *keymap;
00338         
00339         ED_region_panels_init(wm, ar);
00340         
00341         keymap= WM_keymap_find(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
00342         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00343 }
00344 
00345 static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
00346 {
00347         ED_region_panels(C, ar, 1, NULL, -1);
00348 }
00349 
00350 static void nla_region_listener(ARegion *ar, wmNotifier *wmn)
00351 {
00352         /* context changes */
00353         switch(wmn->category) {
00354                 case NC_ANIMATION:
00355                         ED_region_tag_redraw(ar);
00356                         break;
00357                 case NC_SCENE:
00358                         switch(wmn->data) {
00359                                 case ND_OB_ACTIVE:
00360                                 case ND_FRAME:
00361                                 case ND_MARKERS:
00362                                         ED_region_tag_redraw(ar);
00363                                         break;
00364                         }
00365                         break;
00366                 case NC_OBJECT:
00367                         switch(wmn->data) {
00368                                 case ND_BONE_ACTIVE:
00369                                 case ND_BONE_SELECT:
00370                                 case ND_KEYS:
00371                                         ED_region_tag_redraw(ar);
00372                                         break;
00373                         }
00374                         break;
00375                 default:
00376                         if(wmn->data==ND_KEYS)
00377                                 ED_region_tag_redraw(ar);
00378                         break;
00379         }
00380 }
00381 
00382 
00383 static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn)
00384 {
00385         /* context changes */
00386         switch(wmn->category) {
00387                 case NC_ANIMATION:
00388                         ED_region_tag_redraw(ar);
00389                         break;
00390                 case NC_SCENE:
00391                         switch(wmn->data) {
00392                                 case ND_RENDER_OPTIONS:
00393                                 case ND_OB_ACTIVE:
00394                                 case ND_FRAME:
00395                                 case ND_MARKERS:
00396                                         ED_region_tag_redraw(ar);
00397                                         break;
00398                         }
00399                         break;
00400                 case NC_OBJECT:
00401                         switch(wmn->data) {
00402                                 case ND_BONE_ACTIVE:
00403                                 case ND_BONE_SELECT:
00404                                 case ND_KEYS:
00405                                 case ND_TRANSFORM:
00406                                         ED_region_tag_redraw(ar);
00407                                         break;
00408                         }
00409                         break;
00410                 case NC_NODE:
00411                         switch(wmn->action) {
00412                                 case NA_EDITED:
00413                                         ED_region_tag_redraw(ar);
00414                                         break;
00415                         }
00416                         break;
00417                 case NC_ID:
00418                         if(wmn->action == NA_RENAME)
00419                                 ED_region_tag_redraw(ar);
00420                         break;
00421                 default:
00422                         if(wmn->data==ND_KEYS)
00423                                 ED_region_tag_redraw(ar);
00424         }
00425 }
00426 
00427 static void nla_channel_area_listener(ARegion *ar, wmNotifier *wmn)
00428 {
00429         /* context changes */
00430         switch(wmn->category) {
00431                 case NC_ANIMATION:
00432                         ED_region_tag_redraw(ar);
00433                         break;
00434                 case NC_SCENE:
00435                         switch(wmn->data) {
00436                                 case ND_OB_ACTIVE:
00437                                         ED_region_tag_redraw(ar);
00438                                         break;
00439                         }
00440                         break;
00441                 case NC_OBJECT:
00442                         switch(wmn->data) {
00443                                 case ND_BONE_ACTIVE:
00444                                 case ND_BONE_SELECT:
00445                                 case ND_KEYS:
00446                                         ED_region_tag_redraw(ar);
00447                                         break;
00448                         }
00449                         break;
00450                 case NC_ID:
00451                         if(wmn->action == NA_RENAME)
00452                                 ED_region_tag_redraw(ar);
00453                         break;
00454 
00455                 default:
00456                         if(wmn->data==ND_KEYS)
00457                                 ED_region_tag_redraw(ar);
00458         }
00459 }
00460 
00461 /* editor level listener */
00462 static void nla_listener(ScrArea *sa, wmNotifier *wmn)
00463 {
00464         /* context changes */
00465         switch (wmn->category) {
00466                 case NC_ANIMATION:
00467                         // TODO: filter specific types of changes?
00468                         ED_area_tag_refresh(sa);
00469                         break;
00470                 case NC_SCENE:
00471                         /*switch (wmn->data) {
00472                                 case ND_OB_ACTIVE:
00473                                 case ND_OB_SELECT:
00474                                         ED_area_tag_refresh(sa);
00475                                         break;
00476                         }*/
00477                         ED_area_tag_refresh(sa);
00478                         break;
00479                 case NC_OBJECT:
00480                         switch (wmn->data) {
00481                                 case ND_TRANSFORM:
00482                                         /* do nothing */
00483                                         break;
00484                                 default:
00485                                         ED_area_tag_refresh(sa);
00486                                         break;
00487                         }
00488                         break;
00489                 case NC_SPACE:
00490                         if(wmn->data == ND_SPACE_NLA)
00491                                 ED_area_tag_redraw(sa);
00492                         break;
00493         }
00494 }
00495 
00496 /* only called once, from space/spacetypes.c */
00497 void ED_spacetype_nla(void)
00498 {
00499         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype nla");
00500         ARegionType *art;
00501         
00502         st->spaceid= SPACE_NLA;
00503         strncpy(st->name, "NLA", BKE_ST_MAXNAME);
00504         
00505         st->new= nla_new;
00506         st->free= nla_free;
00507         st->init= nla_init;
00508         st->duplicate= nla_duplicate;
00509         st->operatortypes= nla_operatortypes;
00510         st->listener= nla_listener;
00511         st->keymap= nla_keymap;
00512         
00513         /* regions: main window */
00514         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
00515         art->regionid = RGN_TYPE_WINDOW;
00516         art->init= nla_main_area_init;
00517         art->draw= nla_main_area_draw;
00518         art->listener= nla_main_area_listener;
00519         art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
00520 
00521         BLI_addhead(&st->regiontypes, art);
00522         
00523         /* regions: header */
00524         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
00525         art->regionid = RGN_TYPE_HEADER;
00526         art->prefsizey= HEADERY;
00527         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
00528         
00529         art->init= nla_header_area_init;
00530         art->draw= nla_header_area_draw;
00531         
00532         BLI_addhead(&st->regiontypes, art);
00533         
00534         /* regions: channels */
00535         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
00536         art->regionid = RGN_TYPE_CHANNELS;
00537         art->prefsizex= 200;
00538         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
00539         
00540         art->init= nla_channel_area_init;
00541         art->draw= nla_channel_area_draw;
00542         art->listener= nla_channel_area_listener;
00543         
00544         BLI_addhead(&st->regiontypes, art);
00545         
00546         /* regions: UI buttons */
00547         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
00548         art->regionid = RGN_TYPE_UI;
00549         art->prefsizex= 200;
00550         art->keymapflag= ED_KEYMAP_UI;
00551         art->listener= nla_region_listener;
00552         art->init= nla_buttons_area_init;
00553         art->draw= nla_buttons_area_draw;
00554         
00555         BLI_addhead(&st->regiontypes, art);
00556 
00557         nla_buttons_register(art);
00558         
00559         
00560         BKE_spacetype_register(st);
00561 }
00562