|
Blender
V2.59
|
00001 /* 00002 * $Id: space_action.c 37185 2011-06-04 17:03:46Z ton $ 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_action_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_screen.h" 00049 00050 #include "ED_screen.h" 00051 00052 #include "BIF_gl.h" 00053 00054 #include "WM_api.h" 00055 #include "WM_types.h" 00056 00057 #include "UI_resources.h" 00058 #include "UI_view2d.h" 00059 00060 #include "ED_space_api.h" 00061 #include "ED_screen.h" 00062 #include "ED_anim_api.h" 00063 #include "ED_markers.h" 00064 00065 #include "action_intern.h" // own include 00066 00067 /* ******************** default callbacks for action space ***************** */ 00068 00069 static SpaceLink *action_new(const bContext *C) 00070 { 00071 ScrArea *sa= CTX_wm_area(C); 00072 SpaceAction *saction; 00073 ARegion *ar; 00074 00075 saction= MEM_callocN(sizeof(SpaceAction), "initaction"); 00076 saction->spacetype= SPACE_ACTION; 00077 00078 saction->autosnap = SACTSNAP_FRAME; 00079 saction->mode= SACTCONT_DOPESHEET; 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_SPACE: 00409 switch (wmn->data) { 00410 case ND_SPACE_DOPESHEET: 00411 ED_area_tag_redraw(sa); 00412 break; 00413 case ND_SPACE_CHANGED: 00414 saction->flag |= SACTION_TEMP_NEEDCHANSYNC; 00415 ED_area_tag_refresh(sa); 00416 break; 00417 } 00418 break; 00419 } 00420 } 00421 00422 static void action_header_area_listener(ARegion *ar, wmNotifier *wmn) 00423 { 00424 /* context changes */ 00425 switch (wmn->category) { 00426 case NC_SCENE: 00427 switch (wmn->data) { 00428 case ND_OB_ACTIVE: 00429 ED_region_tag_redraw(ar); 00430 break; 00431 } 00432 break; 00433 case NC_ID: 00434 if(wmn->action == NA_RENAME) 00435 ED_region_tag_redraw(ar); 00436 break; 00437 } 00438 } 00439 00440 static void action_refresh(const bContext *C, ScrArea *sa) 00441 { 00442 SpaceAction *saction= (SpaceAction *)sa->spacedata.first; 00443 00444 /* update the state of the animchannels in response to changes from the data they represent 00445 * NOTE: the temp flag is used to indicate when this needs to be done, and will be cleared once handled 00446 */ 00447 if (saction->flag & SACTION_TEMP_NEEDCHANSYNC) { 00448 ANIM_sync_animchannels_to_data(C); 00449 saction->flag &= ~SACTION_TEMP_NEEDCHANSYNC; 00450 ED_area_tag_redraw(sa); 00451 } 00452 00453 /* region updates? */ 00454 // XXX resizing y-extents of tot should go here? 00455 } 00456 00457 /* only called once, from space/spacetypes.c */ 00458 void ED_spacetype_action(void) 00459 { 00460 SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype action"); 00461 ARegionType *art; 00462 00463 st->spaceid= SPACE_ACTION; 00464 strncpy(st->name, "Action", BKE_ST_MAXNAME); 00465 00466 st->new= action_new; 00467 st->free= action_free; 00468 st->init= action_init; 00469 st->duplicate= action_duplicate; 00470 st->operatortypes= action_operatortypes; 00471 st->keymap= action_keymap; 00472 st->listener= action_listener; 00473 st->refresh= action_refresh; 00474 00475 /* regions: main window */ 00476 art= MEM_callocN(sizeof(ARegionType), "spacetype action region"); 00477 art->regionid = RGN_TYPE_WINDOW; 00478 art->init= action_main_area_init; 00479 art->draw= action_main_area_draw; 00480 art->listener= action_main_area_listener; 00481 art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_MARKERS|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES; 00482 00483 BLI_addhead(&st->regiontypes, art); 00484 00485 /* regions: header */ 00486 art= MEM_callocN(sizeof(ARegionType), "spacetype action region"); 00487 art->regionid = RGN_TYPE_HEADER; 00488 art->prefsizey= HEADERY; 00489 art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; 00490 00491 art->init= action_header_area_init; 00492 art->draw= action_header_area_draw; 00493 art->listener= action_header_area_listener; 00494 00495 BLI_addhead(&st->regiontypes, art); 00496 00497 /* regions: channels */ 00498 art= MEM_callocN(sizeof(ARegionType), "spacetype action region"); 00499 art->regionid = RGN_TYPE_CHANNELS; 00500 art->prefsizex= 200; 00501 art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D; 00502 00503 art->init= action_channel_area_init; 00504 art->draw= action_channel_area_draw; 00505 art->listener= action_channel_area_listener; 00506 00507 BLI_addhead(&st->regiontypes, art); 00508 00509 00510 BKE_spacetype_register(st); 00511 } 00512