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