2.5: Buttons View
[blender-staging.git] / source / blender / editors / space_nla / space_nla.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "DNA_anim_types.h"
33 #include "DNA_nla_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_screen_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43 #include "BLI_rand.h"
44
45 #include "BKE_animsys.h"
46 #include "BKE_action.h"
47 #include "BKE_nla.h"
48 #include "BKE_colortools.h"
49 #include "BKE_context.h"
50 #include "BKE_screen.h"
51 #include "BKE_utildefines.h"
52
53 #include "ED_anim_api.h"
54 #include "ED_markers.h"
55 #include "ED_space_api.h"
56 #include "ED_screen.h"
57
58 #include "BIF_gl.h"
59
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63 #include "UI_interface.h"
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
66
67 #include "nla_intern.h" // own include
68
69 /* ******************** manage regions ********************* */
70
71 ARegion *nla_has_buttons_region(ScrArea *sa)
72 {
73         ARegion *ar, *arnew;
74         
75         for (ar= sa->regionbase.first; ar; ar= ar->next) {
76                 if (ar->regiontype==RGN_TYPE_UI)
77                         return ar;
78         }
79         
80         /* add subdiv level; after main */
81         for (ar= sa->regionbase.first; ar; ar= ar->next) {
82                 if (ar->regiontype==RGN_TYPE_WINDOW)
83                         break;
84         }
85         
86         /* is error! */
87         if (ar==NULL) return NULL;
88         
89         arnew= MEM_callocN(sizeof(ARegion), "buttons for nla");
90         
91         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
92         arnew->regiontype= RGN_TYPE_UI;
93         arnew->alignment= RGN_ALIGN_RIGHT;
94         
95         arnew->flag = RGN_FLAG_HIDDEN;
96         
97         return arnew;
98 }
99
100
101
102 /* ******************** default callbacks for nla space ***************** */
103
104 static SpaceLink *nla_new(const bContext *C)
105 {
106         Scene *scene= CTX_data_scene(C);
107         ARegion *ar;
108         SpaceNla *snla;
109         
110         snla= MEM_callocN(sizeof(SpaceNla), "initnla");
111         snla->spacetype= SPACE_NLA;
112         
113         /* allocate DopeSheet data for NLA Editor */
114         snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
115         
116         /* set auto-snapping settings */
117         snla->autosnap = SACTSNAP_FRAME;
118         
119         /* header */
120         ar= MEM_callocN(sizeof(ARegion), "header for nla");
121         
122         BLI_addtail(&snla->regionbase, ar);
123         ar->regiontype= RGN_TYPE_HEADER;
124         ar->alignment= RGN_ALIGN_BOTTOM;
125         
126         /* channel list region */
127         ar= MEM_callocN(sizeof(ARegion), "channel list for nla");
128         BLI_addtail(&snla->regionbase, ar);
129         ar->regiontype= RGN_TYPE_CHANNELS;
130         ar->alignment= RGN_ALIGN_LEFT;
131         
132                 /* only need to set these settings since this will use the 'stack' configuration */
133         ar->v2d.scroll = V2D_SCROLL_BOTTOM;
134         ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
135         
136         /* ui buttons */
137         ar= MEM_callocN(sizeof(ARegion), "buttons area for nla");
138         
139         BLI_addtail(&snla->regionbase, ar);
140         ar->regiontype= RGN_TYPE_UI;
141         ar->alignment= RGN_ALIGN_RIGHT;
142         ar->flag = RGN_FLAG_HIDDEN;
143         
144         /* main area */
145         ar= MEM_callocN(sizeof(ARegion), "main area for nla");
146         
147         BLI_addtail(&snla->regionbase, ar);
148         ar->regiontype= RGN_TYPE_WINDOW;
149         
150         ar->v2d.tot.xmin= (float)(SFRA-10);
151         ar->v2d.tot.ymin= -500.0f;
152         ar->v2d.tot.xmax= (float)(EFRA+10);
153         ar->v2d.tot.ymax= 0.0f;
154         
155         ar->v2d.cur = ar->v2d.tot;
156         
157         ar->v2d.min[0]= 0.0f;
158         ar->v2d.min[1]= 0.0f;
159         
160         ar->v2d.max[0]= MAXFRAMEF;
161         ar->v2d.max[1]= 10000.0f;
162         
163         ar->v2d.minzoom= 0.01f;
164         ar->v2d.maxzoom= 50;
165         ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
166         ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
167         ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
168         ar->v2d.align= V2D_ALIGN_NO_POS_Y;
169         ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
170         
171         return (SpaceLink *)snla;
172 }
173
174 /* not spacelink itself */
175 static void nla_free(SpaceLink *sl)
176 {       
177         SpaceNla *snla= (SpaceNla*) sl;
178         
179         if (snla->ads) {
180                 BLI_freelistN(&snla->ads->chanbase);
181                 MEM_freeN(snla->ads);
182         }
183 }
184
185
186 /* spacetype; init callback */
187 static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
188 {
189         SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
190         
191         /* init dopesheet data if non-existant (i.e. for old files) */
192         if (snla->ads == NULL)
193                 snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
194
195         ED_area_tag_refresh(sa);
196 }
197
198 static SpaceLink *nla_duplicate(SpaceLink *sl)
199 {
200         SpaceNla *snlan= MEM_dupallocN(sl);
201         
202         /* clear or remove stuff from old */
203         snlan->ads= MEM_dupallocN(snlan->ads);
204         
205         return (SpaceLink *)snlan;
206 }
207
208 /* add handlers, stuff you only do once or on area/region changes */
209 static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar)
210 {
211         ListBase *keymap;
212         
213         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
214         
215         /* own keymap */
216         // TODO: cannot use generic copy, need special NLA version
217         keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0);   /* XXX weak? */
218         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
219         keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
220         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
221 }
222
223 /* draw entirely, view changes should be handled here */
224 static void nla_channel_area_draw(const bContext *C, ARegion *ar)
225 {
226         SpaceNla *snla= CTX_wm_space_nla(C);
227         bAnimContext ac;
228         View2D *v2d= &ar->v2d;
229         View2DScrollers *scrollers;
230         float col[3];
231         
232         /* clear and setup matrix */
233         UI_GetThemeColor3fv(TH_BACK, col);
234         glClearColor(col[0], col[1], col[2], 0.0);
235         glClear(GL_COLOR_BUFFER_BIT);
236         
237         UI_view2d_view_ortho(C, v2d);
238         
239         /* data */
240         if (ANIM_animdata_get_context(C, &ac)) {
241                 draw_nla_channel_list(&ac, snla, ar);
242         }
243         
244         /* reset view matrix */
245         UI_view2d_view_restore(C);
246         
247         /* scrollers */
248         scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
249         UI_view2d_scrollers_draw(C, v2d, scrollers);
250         UI_view2d_scrollers_free(scrollers);
251 }
252
253
254 /* add handlers, stuff you only do once or on area/region changes */
255 static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
256 {
257         ListBase *keymap;
258         
259         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
260         
261         /* own keymap */
262         keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0);       /* XXX weak? */
263         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
264         keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
265         WM_event_add_keymap_handler(&ar->handlers, keymap);
266 }
267
268 static void nla_main_area_draw(const bContext *C, ARegion *ar)
269 {
270         /* draw entirely, view changes should be handled here */
271         SpaceNla *snla= CTX_wm_space_nla(C);
272         bAnimContext ac;
273         View2D *v2d= &ar->v2d;
274         View2DGrid *grid;
275         View2DScrollers *scrollers;
276         float col[3];
277         short unit=0, flag=0;
278         
279         /* clear and setup matrix */
280         UI_GetThemeColor3fv(TH_BACK, col);
281         glClearColor(col[0], col[1], col[2], 0.0);
282         glClear(GL_COLOR_BUFFER_BIT);
283         
284         UI_view2d_view_ortho(C, v2d);
285         
286         /* time grid */
287         unit= (snla->flag & SNLA_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
288         grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
289         UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
290         UI_view2d_grid_free(grid);
291         
292         /* data */
293         if (ANIM_animdata_get_context(C, &ac)) {
294                 /* strips and backdrops */
295                 draw_nla_main_data(&ac, snla, ar);
296                 
297                 /* text draw cached, in pixelspace now */
298                 UI_view2d_text_cache_draw(ar);
299         }
300         
301         UI_view2d_view_ortho(C, v2d);
302         
303         /* current frame */
304         if (snla->flag & SNLA_DRAWTIME)         flag |= DRAWCFRA_UNIT_SECONDS;
305         if ((snla->flag & SNLA_NODRAWCFRANUM)==0)  flag |= DRAWCFRA_SHOW_NUMBOX;
306         ANIM_draw_cfra(C, v2d, flag);
307         
308         /* markers */
309         UI_view2d_view_orthoSpecial(C, v2d, 1);
310         draw_markers_time(C, 0);
311         
312         /* preview range */
313         UI_view2d_view_ortho(C, v2d);
314         ANIM_draw_previewrange(C, v2d);
315         
316         /* reset view matrix */
317         UI_view2d_view_restore(C);
318         
319         /* scrollers */
320         scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
321         UI_view2d_scrollers_draw(C, v2d, scrollers);
322         UI_view2d_scrollers_free(scrollers);
323 }
324
325
326 /* add handlers, stuff you only do once or on area/region changes */
327 static void nla_header_area_init(wmWindowManager *wm, ARegion *ar)
328 {
329         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
330 }
331
332 static void nla_header_area_draw(const bContext *C, ARegion *ar)
333 {
334         float col[3];
335         
336         /* clear */
337         if(ED_screen_area_active(C))
338                 UI_GetThemeColor3fv(TH_HEADER, col);
339         else
340                 UI_GetThemeColor3fv(TH_HEADERDESEL, col);
341         
342         glClearColor(col[0], col[1], col[2], 0.0);
343         glClear(GL_COLOR_BUFFER_BIT);
344         
345         /* set view2d view matrix for scrolling (without scrollers) */
346         UI_view2d_view_ortho(C, &ar->v2d);
347         
348         nla_header_buttons(C, ar);
349         
350         /* restore view matrix? */
351         UI_view2d_view_restore(C);
352 }
353
354 /* add handlers, stuff you only do once or on area/region changes */
355 static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
356 {
357         ListBase *keymap;
358         
359         ED_region_panels_init(wm, ar);
360         
361         keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
362         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
363 }
364
365 static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
366 {
367         ED_region_panels(C, ar, 1, NULL, -1);
368 }
369
370 static void nla_region_listener(ARegion *ar, wmNotifier *wmn)
371 {
372         /* context changes */
373         switch(wmn->category) {
374                 case NC_ANIMATION:
375                         ED_region_tag_redraw(ar);
376                         break;
377                 case NC_SCENE:
378                         switch(wmn->data) {
379                                 case ND_OB_ACTIVE:
380                                 case ND_FRAME:
381                                 case ND_MARKERS:
382                                         ED_region_tag_redraw(ar);
383                                         break;
384                         }
385                         break;
386                 case NC_OBJECT:
387                         switch(wmn->data) {
388                                 case ND_BONE_ACTIVE:
389                                 case ND_BONE_SELECT:
390                                 case ND_KEYS:
391                                         ED_region_tag_redraw(ar);
392                                         break;
393                         }
394                         break;
395                 default:
396                         if(wmn->data==ND_KEYS)
397                                 ED_region_tag_redraw(ar);
398                         break;
399         }
400 }
401
402
403 static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn)
404 {
405         /* context changes */
406         switch(wmn->category) {
407                 case NC_ANIMATION:
408                         ED_region_tag_redraw(ar);
409                         break;
410                 case NC_SCENE:
411                         switch(wmn->data) {
412                                 case ND_OB_ACTIVE:
413                                 case ND_FRAME:
414                                 case ND_MARKERS:
415                                         ED_region_tag_redraw(ar);
416                                         break;
417                         }
418                         break;
419                 case NC_OBJECT:
420                         switch(wmn->data) {
421                                 case ND_BONE_ACTIVE:
422                                 case ND_BONE_SELECT:
423                                 case ND_KEYS:
424                                 case ND_TRANSFORM:
425                                         ED_region_tag_redraw(ar);
426                                         break;
427                         }
428                         break;
429                 default:
430                         if(wmn->data==ND_KEYS)
431                                 ED_region_tag_redraw(ar);
432         }
433 }
434
435 static void nla_channel_area_listener(ARegion *ar, wmNotifier *wmn)
436 {
437         /* context changes */
438         switch(wmn->category) {
439                 case NC_ANIMATION:
440                         ED_region_tag_redraw(ar);
441                         break;
442                 case NC_SCENE:
443                         switch(wmn->data) {
444                                 case ND_OB_ACTIVE:
445                                         ED_region_tag_redraw(ar);
446                                         break;
447                         }
448                         break;
449                 case NC_OBJECT:
450                         switch(wmn->data) {
451                                 case ND_BONE_ACTIVE:
452                                 case ND_BONE_SELECT:
453                                 case ND_KEYS:
454                                         ED_region_tag_redraw(ar);
455                                         break;
456                         }
457                         break;
458                 default:
459                         if(wmn->data==ND_KEYS)
460                                 ED_region_tag_redraw(ar);
461         }
462 }
463
464 /* editor level listener */
465 static void nla_listener(ScrArea *sa, wmNotifier *wmn)
466 {
467         /* context changes */
468         switch (wmn->category) {
469                 case NC_ANIMATION:
470                         // TODO: filter specific types of changes?
471                         ED_area_tag_refresh(sa);
472                         break;
473                 case NC_SCENE:
474                         /*switch (wmn->data) {
475                                 case ND_OB_ACTIVE:
476                                 case ND_OB_SELECT:
477                                         ED_area_tag_refresh(sa);
478                                         break;
479                         }*/
480                         ED_area_tag_refresh(sa);
481                         break;
482                 case NC_OBJECT:
483                         /*switch (wmn->data) {
484                                 case ND_BONE_SELECT:
485                                 case ND_BONE_ACTIVE:
486                                         ED_area_tag_refresh(sa);
487                                         break;
488                         }*/
489                         ED_area_tag_refresh(sa);
490                         break;
491         }
492 }
493
494 /* only called once, from space/spacetypes.c */
495 void ED_spacetype_nla(void)
496 {
497         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype nla");
498         ARegionType *art;
499         
500         st->spaceid= SPACE_NLA;
501         
502         st->new= nla_new;
503         st->free= nla_free;
504         st->init= nla_init;
505         st->duplicate= nla_duplicate;
506         st->operatortypes= nla_operatortypes;
507         st->listener= nla_listener;
508         st->keymap= nla_keymap;
509         
510         /* regions: main window */
511         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
512         art->regionid = RGN_TYPE_WINDOW;
513         art->init= nla_main_area_init;
514         art->draw= nla_main_area_draw;
515         art->listener= nla_main_area_listener;
516         art->keymapflag= ED_KEYMAP_VIEW2D/*|ED_KEYMAP_MARKERS*/|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
517
518         BLI_addhead(&st->regiontypes, art);
519         
520         /* regions: header */
521         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
522         art->regionid = RGN_TYPE_HEADER;
523         art->minsizey= HEADERY;
524         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
525         
526         art->init= nla_header_area_init;
527         art->draw= nla_header_area_draw;
528         
529         BLI_addhead(&st->regiontypes, art);
530         
531         /* regions: channels */
532         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
533         art->regionid = RGN_TYPE_CHANNELS;
534         art->minsizex= 200;
535         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
536         
537         art->init= nla_channel_area_init;
538         art->draw= nla_channel_area_draw;
539         art->listener= nla_channel_area_listener;
540         
541         BLI_addhead(&st->regiontypes, art);
542         
543         /* regions: UI buttons */
544         art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
545         art->regionid = RGN_TYPE_UI;
546         art->minsizex= 200;
547         art->keymapflag= ED_KEYMAP_UI;
548         art->listener= nla_region_listener;
549         art->init= nla_buttons_area_init;
550         art->draw= nla_buttons_area_draw;
551         
552         BLI_addhead(&st->regiontypes, art);
553
554         nla_buttons_register(art);
555         
556         
557         BKE_spacetype_register(st);
558 }
559