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