Blender V2.61 - r43446
|
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