25364aed5ca412ce20b5e9688ba0b720c3d3b484
[blender.git] / source / blender / editors / space_sequencer / space_sequencer.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_object_types.h"
33 #include "DNA_space_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_screen_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_math.h"
41 #include "BLI_rand.h"
42
43 #include "BKE_colortools.h"
44 #include "BKE_context.h"
45 #include "BKE_screen.h"
46 #include "BKE_sequencer.h"
47
48 #include "ED_space_api.h"
49 #include "ED_screen.h"
50
51 #include "BIF_gl.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58 #include "UI_view2d.h"
59
60 #include "ED_markers.h"
61
62 #include "sequencer_intern.h"   // own include
63
64 /* ******************** manage regions ********************* */
65
66 ARegion *sequencer_has_buttons_region(ScrArea *sa)
67 {
68         ARegion *ar, *arnew;
69         
70         for(ar= sa->regionbase.first; ar; ar= ar->next)
71                 if(ar->regiontype==RGN_TYPE_UI)
72                         return ar;
73         
74         /* add subdiv level; after header */
75         for(ar= sa->regionbase.first; ar; ar= ar->next)
76                 if(ar->regiontype==RGN_TYPE_HEADER)
77                         break;
78         
79         /* is error! */
80         if(ar==NULL) return NULL;
81         
82         arnew= MEM_callocN(sizeof(ARegion), "buttons for sequencer");
83         
84         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
85         arnew->regiontype= RGN_TYPE_UI;
86         arnew->alignment= RGN_ALIGN_RIGHT;
87         
88         arnew->flag = RGN_FLAG_HIDDEN;
89         
90         return arnew;
91 }
92
93 ARegion *sequencer_find_region(ScrArea *sa, short type)
94 {
95         ARegion *ar=NULL;
96         
97         for(ar= sa->regionbase.first; ar; ar= ar->next)
98                 if(ar->regiontype==type)
99                         return ar;
100
101         return ar;
102 }
103
104 void ED_sequencer_update_view(bContext *C, int view)
105 {
106         ScrArea *sa= CTX_wm_area(C);
107         
108         ARegion *ar_main= sequencer_find_region(sa, RGN_TYPE_WINDOW);
109         ARegion *ar_preview= sequencer_find_region(sa, RGN_TYPE_PREVIEW);
110
111         switch (view) {
112                 case SEQ_VIEW_SEQUENCE:
113                         if (ar_main->flag & RGN_FLAG_HIDDEN) {
114                                 ar_main->flag &= ~RGN_FLAG_HIDDEN;
115                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
116                         }
117                         if (!(ar_preview->flag & RGN_FLAG_HIDDEN)) {
118                                 ar_preview->flag |= RGN_FLAG_HIDDEN;
119                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
120                                 WM_event_remove_handlers(C, &ar_preview->handlers);
121                         }
122                         ar_main->alignment= RGN_ALIGN_NONE;
123                         ar_preview->alignment= RGN_ALIGN_NONE;
124                         break;
125                 case SEQ_VIEW_PREVIEW:
126                         if (!(ar_main->flag & RGN_FLAG_HIDDEN)) {
127                                 ar_main->flag |= RGN_FLAG_HIDDEN;
128                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
129                                 WM_event_remove_handlers(C, &ar_main->handlers);
130                         }
131                         if (ar_preview->flag & RGN_FLAG_HIDDEN) {
132                                 ar_preview->flag &= ~RGN_FLAG_HIDDEN;
133                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
134                         }
135                         ar_main->alignment= RGN_ALIGN_NONE;
136                         ar_preview->alignment= RGN_ALIGN_NONE;
137                         break;
138                 case SEQ_VIEW_SEQUENCE_PREVIEW:
139                         if (ar_main->flag & RGN_FLAG_HIDDEN) {
140                                 ar_main->flag &= ~RGN_FLAG_HIDDEN;
141                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
142                         }
143                         if (ar_preview->flag & RGN_FLAG_HIDDEN) {
144                                 ar_preview->flag &= ~RGN_FLAG_HIDDEN;
145                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
146                         }
147                         ar_main->alignment= RGN_ALIGN_NONE;
148                         ar_preview->alignment= RGN_ALIGN_TOP;
149                         break;
150         }
151
152         ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
153         ED_area_tag_redraw(sa);
154 }
155
156
157 /* ******************** default callbacks for sequencer space ***************** */
158
159 static SpaceLink *sequencer_new(const bContext *C)
160 {
161         Scene *scene= CTX_data_scene(C);
162         ARegion *ar;
163         SpaceSeq *sseq;
164         
165         sseq= MEM_callocN(sizeof(SpaceSeq), "initsequencer");
166         sseq->spacetype= SPACE_SEQ;
167         sseq->zoom= 4;
168         sseq->chanshown = 0;
169         sseq->view = SEQ_VIEW_SEQUENCE;
170         sseq->mainb = SEQ_DRAW_IMG_IMBUF;
171         /* header */
172         ar= MEM_callocN(sizeof(ARegion), "header for sequencer");
173         
174         BLI_addtail(&sseq->regionbase, ar);
175         ar->regiontype= RGN_TYPE_HEADER;
176         ar->alignment= RGN_ALIGN_BOTTOM;
177         
178         /* buttons/list view */
179         ar= MEM_callocN(sizeof(ARegion), "buttons for sequencer");
180         
181         BLI_addtail(&sseq->regionbase, ar);
182         ar->regiontype= RGN_TYPE_UI;
183         ar->alignment= RGN_ALIGN_RIGHT;
184         ar->flag = RGN_FLAG_HIDDEN;
185         
186         /* preview area */
187         ar= MEM_callocN(sizeof(ARegion), "preview area for sequencer");
188         BLI_addtail(&sseq->regionbase, ar);
189         ar->regiontype= RGN_TYPE_PREVIEW;
190         ar->alignment= RGN_ALIGN_TOP;
191         ar->flag |= RGN_FLAG_HIDDEN;
192
193         /* main area */
194         ar= MEM_callocN(sizeof(ARegion), "main area for sequencer");
195         
196         BLI_addtail(&sseq->regionbase, ar);
197         ar->regiontype= RGN_TYPE_WINDOW;
198         
199         
200         /* seq space goes from (0,8) to (0, efra) */
201         
202         ar->v2d.tot.xmin= 0.0f;
203         ar->v2d.tot.ymin= 0.0f;
204         ar->v2d.tot.xmax= scene->r.efra;
205         ar->v2d.tot.ymax= 8.0f;
206         
207         ar->v2d.cur= ar->v2d.tot;
208         
209         ar->v2d.min[0]= 10.0f;
210         ar->v2d.min[1]= 4.0f;
211         
212         ar->v2d.max[0]= MAXFRAMEF;
213         ar->v2d.max[1]= MAXSEQ;
214         
215         ar->v2d.minzoom= 0.01f;
216         ar->v2d.maxzoom= 100.0f;
217         
218         ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
219         ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
220         ar->v2d.keepzoom= 0;
221         ar->v2d.keeptot= 0;
222         ar->v2d.align= V2D_ALIGN_NO_NEG_Y;
223
224         return (SpaceLink *)sseq;
225 }
226
227 /* not spacelink itself */
228 static void sequencer_free(SpaceLink *sl)
229 {       
230 //      SpaceSeq *sseq= (SpaceSequencer*) sl;
231         
232 // XXX  if(sseq->gpd) free_gpencil_data(sseq->gpd);
233
234 }
235
236
237 /* spacetype; init callback */
238 static void sequencer_init(struct wmWindowManager *wm, ScrArea *sa)
239 {
240
241 }
242
243 static SpaceLink *sequencer_duplicate(SpaceLink *sl)
244 {
245         SpaceSeq *sseqn= MEM_dupallocN(sl);
246         
247         /* clear or remove stuff from old */
248 // XXX  sseq->gpd= gpencil_data_duplicate(sseq->gpd);
249
250         return (SpaceLink *)sseqn;
251 }
252
253
254 /* *********************** sequencer (main) region ************************ */
255 /* add handlers, stuff you only do once or on area/region changes */
256 static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
257 {
258         wmKeyMap *keymap;
259         
260         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
261         
262         keymap= WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
263         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
264         
265         /* own keymap */
266         keymap= WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
267         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
268 }
269
270 static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
271 {
272 //      ScrArea *sa= CTX_wm_area(C);
273         
274         /* NLE - strip editing timeline interface */
275         draw_timeline_seq(C, ar);
276 }
277
278
279 /* add handlers, stuff you only do once or on area/region changes */
280 static void sequencer_header_area_init(wmWindowManager *wm, ARegion *ar)
281 {
282         ED_region_header_init(ar);
283 }
284
285 static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
286 {
287         ED_region_header(C, ar);
288 }
289
290 static void sequencer_main_area_listener(ARegion *ar, wmNotifier *wmn)
291 {
292         /* context changes */
293         switch(wmn->category) {
294                 case NC_SCENE:
295                         switch(wmn->data) {
296                                 case ND_FRAME:
297                                 case ND_MARKERS:
298                                 case ND_SEQUENCER:
299                                 case ND_SEQUENCER_SELECT:
300                                         ED_region_tag_redraw(ar);
301                                         break;
302                         }
303                         break;
304                 case NC_SPACE:
305                         if(wmn->data == ND_SPACE_SEQUENCER)
306                                 ED_region_tag_redraw(ar);
307                         break;
308                 case NC_ID:
309                         if(wmn->action == NA_RENAME)
310                                 ED_region_tag_redraw(ar);
311                         break;
312         }
313 }
314
315 /* *********************** preview region ************************ */
316 static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
317 {
318         wmKeyMap *keymap;
319         
320         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
321         
322         keymap= WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
323         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
324
325         /* own keymap */
326         keymap= WM_keymap_find(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
327         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
328 }
329
330 static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
331 {
332         ScrArea *sa= CTX_wm_area(C);
333         SpaceSeq *sseq= sa->spacedata.first;
334         Scene *scene= CTX_data_scene(C);
335         
336         /* XXX temp fix for wrong setting in sseq->mainb */
337         if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
338         draw_image_seq(scene, ar, sseq);
339 }
340
341 static void sequencer_preview_area_listener(ARegion *ar, wmNotifier *wmn)
342 {
343         /* context changes */
344         switch(wmn->category) {
345                 case NC_SCENE:
346                         switch(wmn->data) {
347                                 case ND_FRAME:
348                                 case ND_MARKERS:
349                                 case ND_SEQUENCER:
350                                 case ND_SEQUENCER_SELECT:
351                                         ED_region_tag_redraw(ar);
352                                         break;
353                         }
354                         break;
355                 case NC_SPACE:
356                         if(wmn->data == ND_SPACE_SEQUENCER)
357                                 ED_region_tag_redraw(ar);
358                         break;
359                 case NC_ID:
360                         switch(wmn->data) {
361                                 case NA_RENAME:
362                                         ED_region_tag_redraw(ar);
363                                         break;
364                         }
365                         break;
366         }
367 }
368
369 /* *********************** buttons region ************************ */
370
371 /* add handlers, stuff you only do once or on area/region changes */
372 static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
373 {
374         
375         ED_region_panels_init(wm, ar);
376         
377 }
378
379 static void sequencer_buttons_area_draw(const bContext *C, ARegion *ar)
380 {
381         ED_region_panels(C, ar, 1, NULL, -1);
382 }
383
384 static void sequencer_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
385 {
386         /* context changes */
387         switch(wmn->category) {
388                 case NC_SCENE:
389                 switch(wmn->data) {
390                         case ND_FRAME:
391                         case ND_SEQUENCER:
392                         case ND_SEQUENCER_SELECT:
393                                 ED_region_tag_redraw(ar);
394                                 break;
395                 }
396                 break;
397                 case NC_SPACE:
398                         if(wmn->data == ND_SPACE_SEQUENCER)
399                                 ED_region_tag_redraw(ar);
400                         break;
401                 case NC_ID:
402                         if(wmn->action == NA_RENAME)
403                                 ED_region_tag_redraw(ar);
404                         break;
405         }
406 }
407 /* ************************************* */
408
409 /* only called once, from space/spacetypes.c */
410 void ED_spacetype_sequencer(void)
411 {
412         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
413         ARegionType *art;
414         
415         st->spaceid= SPACE_SEQ;
416         strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
417         
418         st->new= sequencer_new;
419         st->free= sequencer_free;
420         st->init= sequencer_init;
421         st->duplicate= sequencer_duplicate;
422         st->operatortypes= sequencer_operatortypes;
423         st->keymap= sequencer_keymap;
424         
425         /* regions: main window */
426         art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
427         art->regionid = RGN_TYPE_WINDOW;
428         art->init= sequencer_main_area_init;
429         art->draw= sequencer_main_area_draw;
430         art->listener= sequencer_main_area_listener;
431         art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_ANIMATION;
432
433         BLI_addhead(&st->regiontypes, art);
434
435         /* preview */
436         art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
437         art->regionid = RGN_TYPE_PREVIEW;
438         art->minsizey = 240; // XXX
439         art->init= sequencer_preview_area_init;
440         art->draw= sequencer_preview_area_draw;
441         art->listener= sequencer_preview_area_listener;
442         art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_ANIMATION;
443         BLI_addhead(&st->regiontypes, art);
444         
445         /* regions: listview/buttons */
446         art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
447         art->regionid = RGN_TYPE_UI;
448         art->minsizex= 220; // XXX
449         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
450         art->listener= sequencer_buttons_area_listener;
451         art->init= sequencer_buttons_area_init;
452         art->draw= sequencer_buttons_area_draw;
453         BLI_addhead(&st->regiontypes, art);
454         
455         /* Keep as python only for now
456         sequencer_buttons_register(art);
457         */
458
459         /* regions: header */
460         art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
461         art->regionid = RGN_TYPE_HEADER;
462         art->minsizey= HEADERY;
463         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
464         
465         art->init= sequencer_header_area_init;
466         art->draw= sequencer_header_area_draw;
467         art->listener= sequencer_main_area_listener;
468         
469         BLI_addhead(&st->regiontypes, art);
470         
471         BKE_spacetype_register(st);
472 }
473