Blender V2.61 - r43446

space_action.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_action_types.h"
00036 #include "DNA_scene_types.h"
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "BLI_blenlib.h"
00041 #include "BLI_math.h"
00042 #include "BLI_rand.h"
00043 #include "BLI_utildefines.h"
00044 
00045 #include "BKE_context.h"
00046 #include "BKE_screen.h"
00047 
00048 #include "ED_screen.h"
00049 
00050 #include "BIF_gl.h"
00051 
00052 #include "WM_api.h"
00053 #include "WM_types.h"
00054 
00055 #include "UI_resources.h"
00056 #include "UI_view2d.h"
00057 
00058 #include "ED_space_api.h"
00059 #include "ED_screen.h"
00060 #include "ED_anim_api.h"
00061 #include "ED_markers.h"
00062 
00063 #include "action_intern.h"  // own include
00064 
00065 /* ******************** default callbacks for action space ***************** */
00066 
00067 static SpaceLink *action_new(const bContext *C)
00068 {
00069     ScrArea *sa= CTX_wm_area(C);
00070     SpaceAction *saction;
00071     ARegion *ar;
00072     
00073     saction= MEM_callocN(sizeof(SpaceAction), "initaction");
00074     saction->spacetype= SPACE_ACTION;
00075     
00076     saction->autosnap = SACTSNAP_FRAME;
00077     saction->mode= SACTCONT_DOPESHEET;
00078     
00079     saction->ads.filterflag |= ADS_FILTER_SUMMARY;
00080     
00081     /* header */
00082     ar= MEM_callocN(sizeof(ARegion), "header for action");
00083     
00084     BLI_addtail(&saction->regionbase, ar);
00085     ar->regiontype= RGN_TYPE_HEADER;
00086     ar->alignment= RGN_ALIGN_BOTTOM;
00087     
00088     /* channel list region */
00089     ar= MEM_callocN(sizeof(ARegion), "channel area for action");
00090     BLI_addtail(&saction->regionbase, ar);
00091     ar->regiontype= RGN_TYPE_CHANNELS;
00092     ar->alignment= RGN_ALIGN_LEFT;
00093     
00094         /* only need to set scroll settings, as this will use 'listview' v2d configuration */
00095     ar->v2d.scroll = V2D_SCROLL_BOTTOM;
00096     ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
00097     
00098     /* main area */
00099     ar= MEM_callocN(sizeof(ARegion), "main area for action");
00100     
00101     BLI_addtail(&saction->regionbase, ar);
00102     ar->regiontype= RGN_TYPE_WINDOW;
00103     
00104     ar->v2d.tot.xmin= -10.0f;
00105     ar->v2d.tot.ymin= (float)(-sa->winy)/3.0f;
00106     ar->v2d.tot.xmax= (float)(sa->winx);
00107     ar->v2d.tot.ymax= 0.0f;
00108     
00109     ar->v2d.cur = ar->v2d.tot;
00110     
00111     ar->v2d.min[0]= 0.0f;
00112     ar->v2d.min[1]= 0.0f;
00113     
00114     ar->v2d.max[0]= MAXFRAMEF;
00115     ar->v2d.max[1]= FLT_MAX;
00116 
00117     ar->v2d.minzoom= 0.01f;
00118     ar->v2d.maxzoom= 50;
00119     ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
00120     ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
00121     ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
00122     ar->v2d.keepofs= V2D_KEEPOFS_Y;
00123     ar->v2d.align= V2D_ALIGN_NO_POS_Y;
00124     ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
00125     
00126     return (SpaceLink *)saction;
00127 }
00128 
00129 /* not spacelink itself */
00130 static void action_free(SpaceLink *UNUSED(sl))
00131 {   
00132 //  SpaceAction *saction= (SpaceAction*) sl;
00133     
00134 }
00135 
00136 
00137 /* spacetype; init callback */
00138 static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
00139 {
00140     SpaceAction *saction = sa->spacedata.first;
00141     saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00142 }
00143 
00144 static SpaceLink *action_duplicate(SpaceLink *sl)
00145 {
00146     SpaceAction *sactionn= MEM_dupallocN(sl);
00147     
00148     /* clear or remove stuff from old */
00149     
00150     return (SpaceLink *)sactionn;
00151 }
00152 
00153 
00154 
00155 /* add handlers, stuff you only do once or on area/region changes */
00156 static void action_main_area_init(wmWindowManager *wm, ARegion *ar)
00157 {
00158     wmKeyMap *keymap;
00159     
00160     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
00161     
00162     /* own keymap */
00163     keymap= WM_keymap_find(wm->defaultconf, "Dopesheet", SPACE_ACTION, 0);
00164     WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00165 }
00166 
00167 static void action_main_area_draw(const bContext *C, ARegion *ar)
00168 {
00169     /* draw entirely, view changes should be handled here */
00170     SpaceAction *saction= CTX_wm_space_action(C);
00171     bAnimContext ac;
00172     View2D *v2d= &ar->v2d;
00173     View2DGrid *grid;
00174     View2DScrollers *scrollers;
00175     short unit=0, flag=0;
00176     
00177     /* clear and setup matrix */
00178     UI_ThemeClearColor(TH_BACK);
00179     glClear(GL_COLOR_BUFFER_BIT);
00180     
00181     UI_view2d_view_ortho(v2d);
00182     
00183     /* time grid */
00184     unit= (saction->flag & SACTION_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
00185     grid= UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
00186     UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
00187     UI_view2d_grid_free(grid);
00188     
00189     /* data */
00190     if (ANIM_animdata_get_context(C, &ac)) {
00191         draw_channel_strips(&ac, saction, ar);
00192     }
00193     
00194     /* current frame */
00195     if (saction->flag & SACTION_DRAWTIME)   flag |= DRAWCFRA_UNIT_SECONDS;
00196     if ((saction->flag & SACTION_NODRAWCFRANUM)==0)  flag |= DRAWCFRA_SHOW_NUMBOX;
00197     ANIM_draw_cfra(C, v2d, flag);
00198     
00199     /* markers */
00200     UI_view2d_view_orthoSpecial(ar, v2d, 1);
00201     
00202     flag = (ac.markers && (ac.markers != &ac.scene->markers))? DRAW_MARKERS_LOCAL : 0;
00203     draw_markers_time(C, flag);
00204     
00205     /* preview range */
00206     UI_view2d_view_ortho(v2d);
00207     ANIM_draw_previewrange(C, v2d);
00208     
00209     /* reset view matrix */
00210     UI_view2d_view_restore(C);
00211     
00212     /* scrollers */
00213     scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00214     UI_view2d_scrollers_draw(C, v2d, scrollers);
00215     UI_view2d_scrollers_free(scrollers);
00216 }
00217 
00218 /* add handlers, stuff you only do once or on area/region changes */
00219 static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
00220 {
00221     wmKeyMap *keymap;
00222     
00223     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
00224     
00225     /* own keymap */
00226     keymap= WM_keymap_find(wm->defaultconf, "Animation Channels", 0, 0);
00227     WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00228 }
00229 
00230 static void action_channel_area_draw(const bContext *C, ARegion *ar)
00231 {
00232     /* draw entirely, view changes should be handled here */
00233     bAnimContext ac;
00234     View2D *v2d= &ar->v2d;
00235     View2DScrollers *scrollers;
00236     
00237     /* clear and setup matrix */
00238     UI_ThemeClearColor(TH_BACK);
00239     glClear(GL_COLOR_BUFFER_BIT);
00240     
00241     UI_view2d_view_ortho(v2d);
00242     
00243     /* data */
00244     if (ANIM_animdata_get_context(C, &ac)) {
00245         draw_channel_names((bContext *)C, &ac, ar);
00246     }
00247     
00248     /* reset view matrix */
00249     UI_view2d_view_restore(C);
00250     
00251     /* scrollers */
00252     scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
00253     UI_view2d_scrollers_draw(C, v2d, scrollers);
00254     UI_view2d_scrollers_free(scrollers);
00255 }
00256 
00257 
00258 /* add handlers, stuff you only do once or on area/region changes */
00259 static void action_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
00260 {
00261     ED_region_header_init(ar);
00262 }
00263 
00264 static void action_header_area_draw(const bContext *C, ARegion *ar)
00265 {
00266     ED_region_header(C, ar);
00267 }
00268 
00269 static void action_channel_area_listener(ARegion *ar, wmNotifier *wmn)
00270 {
00271     /* context changes */
00272     switch(wmn->category) {
00273         case NC_ANIMATION:
00274             ED_region_tag_redraw(ar);
00275             break;
00276         case NC_SCENE:
00277             switch(wmn->data) {
00278                 case ND_OB_ACTIVE:
00279                 case ND_FRAME:
00280                     ED_region_tag_redraw(ar);
00281                     break;
00282             }
00283             break;
00284         case NC_OBJECT:
00285             switch(wmn->data) {
00286                 case ND_BONE_ACTIVE:
00287                 case ND_BONE_SELECT:
00288                 case ND_KEYS:
00289                     ED_region_tag_redraw(ar);
00290                     break;
00291                 case ND_MODIFIER:
00292                     if(wmn->action == NA_RENAME)
00293                         ED_region_tag_redraw(ar);
00294                     break;
00295             }
00296             break;
00297         case NC_ID:
00298             if(wmn->action == NA_RENAME)
00299                 ED_region_tag_redraw(ar);
00300             break;
00301         default:
00302             if(wmn->data==ND_KEYS)
00303                 ED_region_tag_redraw(ar);
00304     }
00305 }
00306 
00307 static void action_main_area_listener(ARegion *ar, wmNotifier *wmn)
00308 {
00309     /* context changes */
00310     switch(wmn->category) {
00311         case NC_ANIMATION:
00312             ED_region_tag_redraw(ar);
00313             break;
00314         case NC_SCENE:
00315             switch(wmn->data) {
00316                 case ND_RENDER_OPTIONS:
00317                 case ND_OB_ACTIVE:
00318                 case ND_FRAME:
00319                 case ND_MARKERS:
00320                     ED_region_tag_redraw(ar);
00321                     break;
00322             }
00323             break;
00324         case NC_OBJECT:
00325             switch(wmn->data) {
00326                 case ND_TRANSFORM:
00327                     /* moving object shouldn't need to redraw action */
00328                     break;
00329                 case ND_BONE_ACTIVE:
00330                 case ND_BONE_SELECT:
00331                 case ND_KEYS:
00332                     ED_region_tag_redraw(ar);
00333                     break;
00334             }
00335             break;
00336         case NC_NODE:
00337             switch(wmn->action) {
00338                 case NA_EDITED:
00339                     ED_region_tag_redraw(ar);
00340                     break;
00341             }
00342             break;
00343         case NC_ID:
00344             if(wmn->action == NA_RENAME)
00345                 ED_region_tag_redraw(ar);
00346             break;
00347                 
00348         default:
00349             if(wmn->data==ND_KEYS)
00350                 ED_region_tag_redraw(ar);
00351     }
00352 }
00353 
00354 /* editor level listener */
00355 static void action_listener(ScrArea *sa, wmNotifier *wmn)
00356 {
00357     SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
00358     
00359     /* context changes */
00360     switch (wmn->category) {
00361         case NC_SCREEN:
00362             if (wmn->data == ND_GPENCIL) {
00363                 /* only handle this event in GPencil mode for performance considerations */
00364                 if (saction->mode == SACTCONT_GPENCIL)  
00365                     ED_area_tag_redraw(sa);
00366             }
00367             break;
00368         case NC_ANIMATION:
00369             /* for NLA tweakmode enter/exit, need complete refresh */
00370             if (wmn->data == ND_NLA_ACTCHANGE) {
00371                 saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00372                 ED_area_tag_refresh(sa);
00373             }
00374             /* for selection changes of animation data, we can just redraw... otherwise autocolor might need to be done again */
00375             else if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED))
00376                 ED_area_tag_redraw(sa);
00377             else
00378                 ED_area_tag_refresh(sa);
00379             break;
00380         case NC_SCENE:
00381             switch (wmn->data) {    
00382                 case ND_OB_ACTIVE:  /* selection changed, so force refresh to flush (needs flag set to do syncing) */
00383                 case ND_OB_SELECT:
00384                     saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00385                     ED_area_tag_refresh(sa);
00386                     break;
00387                     
00388                 default: /* just redrawing the view will do */
00389                     ED_area_tag_redraw(sa);
00390                     break;
00391             }
00392             break;
00393         case NC_OBJECT:
00394             switch (wmn->data) {
00395                 case ND_BONE_SELECT:    /* selection changed, so force refresh to flush (needs flag set to do syncing) */
00396                 case ND_BONE_ACTIVE:
00397                     saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00398                     ED_area_tag_refresh(sa);
00399                     break;
00400                 case ND_TRANSFORM:
00401                     /* moving object shouldn't need to redraw action */
00402                     break;
00403                 default: /* just redrawing the view will do */
00404                     ED_area_tag_redraw(sa);
00405                     break;
00406             }
00407             break;
00408         case NC_NODE:
00409             if (wmn->action == NA_SELECTED) {
00410                 /* selection changed, so force refresh to flush (needs flag set to do syncing) */
00411                 saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00412                 ED_area_tag_refresh(sa);
00413             }
00414             break;
00415         case NC_SPACE:
00416             switch (wmn->data) {
00417                 case ND_SPACE_DOPESHEET:
00418                     ED_area_tag_redraw(sa);
00419                     break;
00420                 case ND_SPACE_CHANGED:
00421                     saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
00422                     ED_area_tag_refresh(sa);
00423                     break;
00424             }           
00425             break;
00426     }
00427 }
00428 
00429 static void action_header_area_listener(ARegion *ar, wmNotifier *wmn)
00430 {
00431     /* context changes */
00432     switch (wmn->category) {
00433         case NC_SCENE:
00434             switch (wmn->data) {
00435                 case ND_OB_ACTIVE:
00436                     ED_region_tag_redraw(ar);
00437                     break;
00438             }
00439             break;
00440         case NC_ID:
00441             if(wmn->action == NA_RENAME)
00442                 ED_region_tag_redraw(ar);
00443             break;
00444     }
00445 }
00446 
00447 static void action_refresh(const bContext *C, ScrArea *sa)
00448 {
00449     SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
00450     
00451     /* update the state of the animchannels in response to changes from the data they represent 
00452      * NOTE: the temp flag is used to indicate when this needs to be done, and will be cleared once handled
00453      */
00454     if (saction->flag & SACTION_TEMP_NEEDCHANSYNC) {
00455         ANIM_sync_animchannels_to_data(C);
00456         saction->flag &= ~SACTION_TEMP_NEEDCHANSYNC;
00457         ED_area_tag_redraw(sa);
00458     }
00459     
00460     /* region updates? */
00461     // XXX resizing y-extents of tot should go here?
00462 }
00463 
00464 /* only called once, from space/spacetypes.c */
00465 void ED_spacetype_action(void)
00466 {
00467     SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype action");
00468     ARegionType *art;
00469     
00470     st->spaceid= SPACE_ACTION;
00471     strncpy(st->name, "Action", BKE_ST_MAXNAME);
00472     
00473     st->new= action_new;
00474     st->free= action_free;
00475     st->init= action_init;
00476     st->duplicate= action_duplicate;
00477     st->operatortypes= action_operatortypes;
00478     st->keymap= action_keymap;
00479     st->listener= action_listener;
00480     st->refresh= action_refresh;
00481     
00482     /* regions: main window */
00483     art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
00484     art->regionid = RGN_TYPE_WINDOW;
00485     art->init= action_main_area_init;
00486     art->draw= action_main_area_draw;
00487     art->listener= action_main_area_listener;
00488     art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
00489 
00490     BLI_addhead(&st->regiontypes, art);
00491     
00492     /* regions: header */
00493     art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
00494     art->regionid = RGN_TYPE_HEADER;
00495     art->prefsizey= HEADERY;
00496     art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
00497     
00498     art->init= action_header_area_init;
00499     art->draw= action_header_area_draw;
00500     art->listener= action_header_area_listener;
00501     
00502     BLI_addhead(&st->regiontypes, art);
00503     
00504     /* regions: channels */
00505     art= MEM_callocN(sizeof(ARegionType), "spacetype action region");
00506     art->regionid = RGN_TYPE_CHANNELS;
00507     art->prefsizex= 200;
00508     art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
00509     
00510     art->init= action_channel_area_init;
00511     art->draw= action_channel_area_draw;
00512     art->listener= action_channel_area_listener;
00513     
00514     BLI_addhead(&st->regiontypes, art);
00515     
00516     
00517     BKE_spacetype_register(st);
00518 }
00519