VSE: Cache rewrite
[blender.git] / source / blender / editors / space_sequencer / space_sequencer.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup spseq
22  */
23
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "DNA_gpencil_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_mask_types.h"
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_utildefines.h"
35
36 #include "BKE_context.h"
37 #include "BKE_global.h"
38 #include "BKE_library.h"
39 #include "BKE_screen.h"
40 #include "BKE_sequencer.h"
41
42 #include "ED_space_api.h"
43 #include "ED_screen.h"
44 #include "ED_view3d.h" /* only for sequencer view3d drawing callback */
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48 #include "WM_message.h"
49
50 #include "RNA_access.h"
51
52 #include "UI_interface.h"
53 #include "UI_resources.h"
54 #include "UI_view2d.h"
55
56 #include "IMB_imbuf.h"
57
58 #include "sequencer_intern.h"  // own include
59
60 /**************************** common state *****************************/
61
62 static void sequencer_scopes_tag_refresh(ScrArea *sa)
63 {
64   SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
65
66   sseq->scopes.reference_ibuf = NULL;
67 }
68
69 /* ******************** manage regions ********************* */
70
71 static ARegion *sequencer_find_region(ScrArea *sa, short type)
72 {
73   ARegion *ar = NULL;
74
75   for (ar = sa->regionbase.first; ar; ar = ar->next) {
76     if (ar->regiontype == type) {
77       return ar;
78     }
79   }
80
81   return ar;
82 }
83
84 /* ******************** default callbacks for sequencer space ***************** */
85
86 static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
87 {
88   ARegion *ar;
89   SpaceSeq *sseq;
90
91   sseq = MEM_callocN(sizeof(SpaceSeq), "initsequencer");
92   sseq->spacetype = SPACE_SEQ;
93   sseq->chanshown = 0;
94   sseq->view = SEQ_VIEW_SEQUENCE;
95   sseq->mainb = SEQ_DRAW_IMG_IMBUF;
96   sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKER_LINES;
97
98   /* header */
99   ar = MEM_callocN(sizeof(ARegion), "header for sequencer");
100
101   BLI_addtail(&sseq->regionbase, ar);
102   ar->regiontype = RGN_TYPE_HEADER;
103   ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
104
105   /* buttons/list view */
106   ar = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
107
108   BLI_addtail(&sseq->regionbase, ar);
109   ar->regiontype = RGN_TYPE_UI;
110   ar->alignment = RGN_ALIGN_RIGHT;
111   ar->flag = RGN_FLAG_HIDDEN;
112
113   /* preview region */
114   /* NOTE: if you change values here, also change them in sequencer_init_preview_region */
115   ar = MEM_callocN(sizeof(ARegion), "preview region for sequencer");
116   BLI_addtail(&sseq->regionbase, ar);
117   ar->regiontype = RGN_TYPE_PREVIEW;
118   ar->alignment = RGN_ALIGN_TOP;
119   ar->flag |= RGN_FLAG_HIDDEN;
120   /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
121   ar->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM | V2D_LIMITZOOM;
122   ar->v2d.minzoom = 0.001f;
123   ar->v2d.maxzoom = 1000.0f;
124   ar->v2d.tot.xmin = -960.0f; /* 1920 width centered */
125   ar->v2d.tot.ymin = -540.0f; /* 1080 height centered */
126   ar->v2d.tot.xmax = 960.0f;
127   ar->v2d.tot.ymax = 540.0f;
128   ar->v2d.min[0] = 0.0f;
129   ar->v2d.min[1] = 0.0f;
130   ar->v2d.max[0] = 12000.0f;
131   ar->v2d.max[1] = 12000.0f;
132   ar->v2d.cur = ar->v2d.tot;
133   ar->v2d.align = V2D_ALIGN_FREE;
134   ar->v2d.keeptot = V2D_KEEPTOT_FREE;
135
136   /* main region */
137   ar = MEM_callocN(sizeof(ARegion), "main region for sequencer");
138
139   BLI_addtail(&sseq->regionbase, ar);
140   ar->regiontype = RGN_TYPE_WINDOW;
141
142   /* seq space goes from (0,8) to (0, efra) */
143
144   ar->v2d.tot.xmin = 0.0f;
145   ar->v2d.tot.ymin = 0.0f;
146   ar->v2d.tot.xmax = scene->r.efra;
147   ar->v2d.tot.ymax = 8.0f;
148
149   ar->v2d.cur = ar->v2d.tot;
150
151   ar->v2d.min[0] = 10.0f;
152   ar->v2d.min[1] = 0.5f;
153
154   ar->v2d.max[0] = MAXFRAMEF;
155   ar->v2d.max[1] = MAXSEQ;
156
157   ar->v2d.minzoom = 0.01f;
158   ar->v2d.maxzoom = 100.0f;
159
160   ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
161   ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
162   ar->v2d.keepzoom = 0;
163   ar->v2d.keeptot = 0;
164   ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
165
166   return (SpaceLink *)sseq;
167 }
168
169 /* not spacelink itself */
170 static void sequencer_free(SpaceLink *sl)
171 {
172   SpaceSeq *sseq = (SpaceSeq *)sl;
173   SequencerScopes *scopes = &sseq->scopes;
174
175   // XXX  if (sseq->gpd) BKE_gpencil_free(sseq->gpd);
176
177   if (scopes->zebra_ibuf) {
178     IMB_freeImBuf(scopes->zebra_ibuf);
179   }
180
181   if (scopes->waveform_ibuf) {
182     IMB_freeImBuf(scopes->waveform_ibuf);
183   }
184
185   if (scopes->sep_waveform_ibuf) {
186     IMB_freeImBuf(scopes->sep_waveform_ibuf);
187   }
188
189   if (scopes->vector_ibuf) {
190     IMB_freeImBuf(scopes->vector_ibuf);
191   }
192
193   if (scopes->histogram_ibuf) {
194     IMB_freeImBuf(scopes->histogram_ibuf);
195   }
196 }
197
198 /* spacetype; init callback */
199 static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
200 {
201 }
202
203 static void sequencer_refresh(const bContext *C, ScrArea *sa)
204 {
205   wmWindowManager *wm = CTX_wm_manager(C);
206   wmWindow *window = CTX_wm_window(C);
207   SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
208   ARegion *ar_main = sequencer_find_region(sa, RGN_TYPE_WINDOW);
209   ARegion *ar_preview = sequencer_find_region(sa, RGN_TYPE_PREVIEW);
210   bool view_changed = false;
211
212   switch (sseq->view) {
213     case SEQ_VIEW_SEQUENCE:
214       if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
215         ar_main->flag &= ~RGN_FLAG_HIDDEN;
216         ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
217         view_changed = true;
218       }
219       if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
220         ar_preview->flag |= RGN_FLAG_HIDDEN;
221         ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
222         WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
223         view_changed = true;
224       }
225       if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
226         ar_main->alignment = RGN_ALIGN_NONE;
227         view_changed = true;
228       }
229       if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
230         ar_preview->alignment = RGN_ALIGN_NONE;
231         view_changed = true;
232       }
233       break;
234     case SEQ_VIEW_PREVIEW:
235       if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) {
236         ar_main->flag |= RGN_FLAG_HIDDEN;
237         ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
238         WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
239         view_changed = true;
240       }
241       if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
242         ar_preview->flag &= ~RGN_FLAG_HIDDEN;
243         ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
244         ar_preview->v2d.cur = ar_preview->v2d.tot;
245         view_changed = true;
246       }
247       if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
248         ar_main->alignment = RGN_ALIGN_NONE;
249         view_changed = true;
250       }
251       if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
252         ar_preview->alignment = RGN_ALIGN_NONE;
253         view_changed = true;
254       }
255       break;
256     case SEQ_VIEW_SEQUENCE_PREVIEW:
257       if (ar_main && ar_preview) {
258         /* Get available height (without DPI correction). */
259         const float height = (sa->winy - ED_area_headersize()) / UI_DPI_FAC;
260
261         /* We reuse hidden region's size, allows to find same layout as before if we just switch
262          * between one 'full window' view and the combined one. This gets lost if we switch to both
263          * 'full window' views before, though... Better than nothing. */
264         if (ar_main->flag & RGN_FLAG_HIDDEN) {
265           ar_main->flag &= ~RGN_FLAG_HIDDEN;
266           ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
267           ar_preview->sizey = (int)(height - ar_main->sizey);
268           view_changed = true;
269         }
270         if (ar_preview->flag & RGN_FLAG_HIDDEN) {
271           ar_preview->flag &= ~RGN_FLAG_HIDDEN;
272           ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
273           ar_preview->v2d.cur = ar_preview->v2d.tot;
274           ar_main->sizey = (int)(height - ar_preview->sizey);
275           view_changed = true;
276         }
277         if (ar_main->alignment != RGN_ALIGN_NONE) {
278           ar_main->alignment = RGN_ALIGN_NONE;
279           view_changed = true;
280         }
281         if (ar_preview->alignment != RGN_ALIGN_TOP) {
282           ar_preview->alignment = RGN_ALIGN_TOP;
283           view_changed = true;
284         }
285         /* Final check that both preview and main height are reasonable! */
286         if (ar_preview->sizey < 10 || ar_main->sizey < 10 ||
287             ar_preview->sizey + ar_main->sizey > height) {
288           ar_preview->sizey = (int)(height * 0.4f + 0.5f);
289           ar_main->sizey = (int)(height - ar_preview->sizey);
290           view_changed = true;
291         }
292       }
293       break;
294   }
295
296   if (view_changed) {
297     ED_area_initialize(wm, window, sa);
298     ED_area_tag_redraw(sa);
299   }
300 }
301
302 static SpaceLink *sequencer_duplicate(SpaceLink *sl)
303 {
304   SpaceSeq *sseqn = MEM_dupallocN(sl);
305
306   /* clear or remove stuff from old */
307   // XXX  sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
308
309   memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
310
311   return (SpaceLink *)sseqn;
312 }
313
314 static void sequencer_listener(wmWindow *UNUSED(win),
315                                ScrArea *sa,
316                                wmNotifier *wmn,
317                                Scene *UNUSED(scene))
318 {
319   /* context changes */
320   switch (wmn->category) {
321     case NC_SCENE:
322       switch (wmn->data) {
323         case ND_FRAME:
324         case ND_SEQUENCER:
325           sequencer_scopes_tag_refresh(sa);
326           break;
327       }
328       break;
329     case NC_WINDOW:
330     case NC_SPACE:
331       if (wmn->data == ND_SPACE_SEQUENCER) {
332         sequencer_scopes_tag_refresh(sa);
333       }
334       break;
335     case NC_GPENCIL:
336       if (wmn->data & ND_GPENCIL_EDITMODE) {
337         ED_area_tag_redraw(sa);
338       }
339       break;
340   }
341 }
342
343 /* ************* dropboxes ************* */
344
345 static bool image_drop_poll(bContext *C,
346                             wmDrag *drag,
347                             const wmEvent *event,
348                             const char **UNUSED(tooltip))
349 {
350   ARegion *ar = CTX_wm_region(C);
351   Scene *scene = CTX_data_scene(C);
352   int hand;
353
354   if (drag->type == WM_DRAG_PATH) {
355     if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* rule might not work? */
356       if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
357         return 1;
358       }
359     }
360   }
361
362   return 0;
363 }
364
365 static bool movie_drop_poll(bContext *C,
366                             wmDrag *drag,
367                             const wmEvent *event,
368                             const char **UNUSED(tooltip))
369 {
370   ARegion *ar = CTX_wm_region(C);
371   Scene *scene = CTX_data_scene(C);
372   int hand;
373
374   if (drag->type == WM_DRAG_PATH) {
375     if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* rule might not work? */
376       if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
377         return 1;
378       }
379     }
380   }
381   return 0;
382 }
383
384 static bool sound_drop_poll(bContext *C,
385                             wmDrag *drag,
386                             const wmEvent *event,
387                             const char **UNUSED(tooltip))
388 {
389   ARegion *ar = CTX_wm_region(C);
390   Scene *scene = CTX_data_scene(C);
391   int hand;
392
393   if (drag->type == WM_DRAG_PATH) {
394     if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* rule might not work? */
395       if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
396         return 1;
397       }
398     }
399   }
400   return 0;
401 }
402
403 static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
404 {
405   /* copy drag path to properties */
406   if (RNA_struct_find_property(drop->ptr, "filepath")) {
407     RNA_string_set(drop->ptr, "filepath", drag->path);
408   }
409
410   if (RNA_struct_find_property(drop->ptr, "directory")) {
411     PointerRNA itemptr;
412     char dir[FILE_MAX], file[FILE_MAX];
413
414     BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
415
416     RNA_string_set(drop->ptr, "directory", dir);
417
418     RNA_collection_clear(drop->ptr, "files");
419     RNA_collection_add(drop->ptr, "files", &itemptr);
420     RNA_string_set(&itemptr, "name", file);
421   }
422 }
423
424 /* this region dropbox definition */
425 static void sequencer_dropboxes(void)
426 {
427   ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
428
429   WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
430   WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
431   WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
432 }
433
434 /* ************* end drop *********** */
435
436 /* DO NOT make this static, this hides the symbol and breaks API generation script. */
437 extern const char *sequencer_context_dir[]; /* quiet warning. */
438 const char *sequencer_context_dir[] = {"edit_mask", NULL};
439
440 static int sequencer_context(const bContext *C, const char *member, bContextDataResult *result)
441 {
442   Scene *scene = CTX_data_scene(C);
443
444   if (CTX_data_dir(member)) {
445     CTX_data_dir_set(result, sequencer_context_dir);
446
447     return true;
448   }
449   else if (CTX_data_equals(member, "edit_mask")) {
450     Mask *mask = BKE_sequencer_mask_get(scene);
451     if (mask) {
452       CTX_data_id_pointer_set(result, &mask->id);
453     }
454     return true;
455   }
456
457   return false;
458 }
459
460 /* *********************** sequencer (main) region ************************ */
461 /* add handlers, stuff you only do once or on area/region changes */
462 static void sequencer_main_region_init(wmWindowManager *wm, ARegion *ar)
463 {
464   wmKeyMap *keymap;
465   ListBase *lb;
466
467   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
468
469 #if 0
470   keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
471   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
472 #endif
473
474   keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
475   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
476
477   /* own keymap */
478   keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
479   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
480
481   /* add drop boxes */
482   lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
483
484   WM_event_add_dropbox_handler(&ar->handlers, lb);
485 }
486
487 static void sequencer_main_region_draw(const bContext *C, ARegion *ar)
488 {
489   /* NLE - strip editing timeline interface */
490   draw_timeline_seq(C, ar);
491 }
492
493 static void sequencer_main_region_listener(wmWindow *UNUSED(win),
494                                            ScrArea *UNUSED(sa),
495                                            ARegion *ar,
496                                            wmNotifier *wmn,
497                                            const Scene *UNUSED(scene))
498 {
499   /* context changes */
500   switch (wmn->category) {
501     case NC_SCENE:
502       switch (wmn->data) {
503         case ND_FRAME:
504         case ND_FRAME_RANGE:
505         case ND_MARKERS:
506         case ND_RENDER_OPTIONS: /* for FPS and FPS Base */
507         case ND_SEQUENCER:
508         case ND_RENDER_RESULT:
509           ED_region_tag_redraw(ar);
510           break;
511       }
512       break;
513     case NC_ANIMATION:
514       switch (wmn->data) {
515         case ND_KEYFRAME:
516           ED_region_tag_redraw(ar);
517           break;
518       }
519       break;
520     case NC_SPACE:
521       if (wmn->data == ND_SPACE_SEQUENCER) {
522         ED_region_tag_redraw(ar);
523       }
524       break;
525     case NC_ID:
526       if (wmn->action == NA_RENAME) {
527         ED_region_tag_redraw(ar);
528       }
529       break;
530     case NC_SCREEN:
531       if (ELEM(wmn->data, ND_ANIMPLAY)) {
532         ED_region_tag_redraw(ar);
533       }
534       break;
535   }
536 }
537
538 static void sequencer_main_region_message_subscribe(const struct bContext *UNUSED(C),
539                                                     struct WorkSpace *UNUSED(workspace),
540                                                     struct Scene *scene,
541                                                     struct bScreen *UNUSED(screen),
542                                                     struct ScrArea *UNUSED(sa),
543                                                     struct ARegion *ar,
544                                                     struct wmMsgBus *mbus)
545 {
546   wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
547       .owner = ar,
548       .user_data = ar,
549       .notify = ED_region_do_msg_notify_tag_redraw,
550   };
551
552   /* Timeline depends on scene properties. */
553   {
554     bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
555     extern PropertyRNA rna_Scene_frame_start;
556     extern PropertyRNA rna_Scene_frame_end;
557     extern PropertyRNA rna_Scene_frame_preview_start;
558     extern PropertyRNA rna_Scene_frame_preview_end;
559     extern PropertyRNA rna_Scene_use_preview_range;
560     extern PropertyRNA rna_Scene_frame_current;
561     const PropertyRNA *props[] = {
562         use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
563         use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
564         &rna_Scene_use_preview_range,
565         &rna_Scene_frame_current,
566     };
567
568     PointerRNA idptr;
569     RNA_id_pointer_create(&scene->id, &idptr);
570
571     for (int i = 0; i < ARRAY_SIZE(props); i++) {
572       WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
573     }
574   }
575
576   {
577     StructRNA *type_array[] = {
578         &RNA_SequenceEditor,
579
580         &RNA_Sequence,
581         /* Members of 'Sequence'. */
582         &RNA_SequenceCrop,
583         &RNA_SequenceTransform,
584         &RNA_SequenceModifier,
585         &RNA_SequenceColorBalanceData,
586     };
587     wmMsgParams_RNA msg_key_params = {{{0}}};
588     for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
589       msg_key_params.ptr.type = type_array[i];
590       WM_msg_subscribe_rna_params(
591           mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
592     }
593   }
594 }
595
596 /* *********************** header region ************************ */
597 /* add handlers, stuff you only do once or on area/region changes */
598 static void sequencer_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
599 {
600   ED_region_header_init(ar);
601 }
602
603 static void sequencer_header_region_draw(const bContext *C, ARegion *ar)
604 {
605   ED_region_header(C, ar);
606 }
607
608 /* *********************** preview region ************************ */
609 static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *ar)
610 {
611   wmKeyMap *keymap;
612
613   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
614
615 #if 0
616   keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
617   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
618 #endif
619
620   keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
621   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
622
623   /* own keymap */
624   keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
625   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
626 }
627
628 static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
629 {
630   ScrArea *sa = CTX_wm_area(C);
631   SpaceSeq *sseq = sa->spacedata.first;
632   Scene *scene = CTX_data_scene(C);
633   wmWindowManager *wm = CTX_wm_manager(C);
634   const bool show_split = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
635                            (sseq->mainb == SEQ_DRAW_IMG_IMBUF));
636
637   /* XXX temp fix for wrong setting in sseq->mainb */
638   if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
639     sseq->mainb = SEQ_DRAW_IMG_IMBUF;
640   }
641
642   if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE) {
643     sequencer_draw_preview(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
644   }
645
646   if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
647     int over_cfra;
648
649     if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) {
650       over_cfra = scene->ed->over_cfra;
651     }
652     else {
653       over_cfra = scene->r.cfra + scene->ed->over_ofs;
654     }
655
656     if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT) {
657       sequencer_draw_preview(
658           C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
659     }
660   }
661
662   if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
663     rcti rect;
664     ED_region_visible_rect(ar, &rect);
665     int xoffset = rect.xmin + U.widget_unit;
666     int yoffset = rect.ymax;
667     ED_scene_draw_fps(scene, xoffset, &yoffset);
668   }
669 }
670
671 static void sequencer_preview_region_listener(wmWindow *UNUSED(win),
672                                               ScrArea *UNUSED(sa),
673                                               ARegion *ar,
674                                               wmNotifier *wmn,
675                                               const Scene *UNUSED(scene))
676 {
677   /* context changes */
678   switch (wmn->category) {
679     case NC_GPENCIL:
680       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
681         ED_region_tag_redraw(ar);
682       }
683       break;
684     case NC_SCENE:
685       switch (wmn->data) {
686         case ND_FRAME:
687         case ND_MARKERS:
688         case ND_SEQUENCER:
689         case ND_RENDER_OPTIONS:
690         case ND_DRAW_RENDER_VIEWPORT:
691           ED_region_tag_redraw(ar);
692           break;
693       }
694       break;
695     case NC_ANIMATION:
696       switch (wmn->data) {
697         case ND_KEYFRAME:
698           ED_region_tag_redraw(ar);
699           break;
700       }
701       break;
702     case NC_SPACE:
703       if (wmn->data == ND_SPACE_SEQUENCER) {
704         ED_region_tag_redraw(ar);
705       }
706       break;
707     case NC_ID:
708       switch (wmn->data) {
709         case NA_RENAME:
710           ED_region_tag_redraw(ar);
711           break;
712       }
713       break;
714     case NC_MASK:
715       if (wmn->action == NA_EDITED) {
716         ED_region_tag_redraw(ar);
717       }
718       break;
719   }
720 }
721
722 /* *********************** buttons region ************************ */
723
724 /* add handlers, stuff you only do once or on area/region changes */
725 static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
726 {
727   wmKeyMap *keymap;
728
729   keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
730   WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
731
732   ED_region_panels_init(wm, ar);
733 }
734
735 static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
736 {
737   ED_region_panels(C, ar);
738 }
739
740 static void sequencer_buttons_region_listener(wmWindow *UNUSED(win),
741                                               ScrArea *UNUSED(sa),
742                                               ARegion *ar,
743                                               wmNotifier *wmn,
744                                               const Scene *UNUSED(scene))
745 {
746   /* context changes */
747   switch (wmn->category) {
748     case NC_GPENCIL:
749       if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
750         ED_region_tag_redraw(ar);
751       }
752       break;
753     case NC_SCENE:
754       switch (wmn->data) {
755         case ND_FRAME:
756         case ND_SEQUENCER:
757           ED_region_tag_redraw(ar);
758           break;
759       }
760       break;
761     case NC_SPACE:
762       if (wmn->data == ND_SPACE_SEQUENCER) {
763         ED_region_tag_redraw(ar);
764       }
765       break;
766     case NC_ID:
767       if (wmn->action == NA_RENAME) {
768         ED_region_tag_redraw(ar);
769       }
770       break;
771   }
772 }
773
774 static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
775 {
776   SpaceSeq *sseq = (SpaceSeq *)slink;
777
778   if (!ELEM(GS(old_id->name), ID_GD)) {
779     return;
780   }
781
782   if ((ID *)sseq->gpd == old_id) {
783     sseq->gpd = (bGPdata *)new_id;
784     id_us_min(old_id);
785     id_us_plus(new_id);
786   }
787 }
788
789 /* ************************************* */
790
791 /* only called once, from space/spacetypes.c */
792 void ED_spacetype_sequencer(void)
793 {
794   SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
795   ARegionType *art;
796
797   st->spaceid = SPACE_SEQ;
798   strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
799
800   st->new = sequencer_new;
801   st->free = sequencer_free;
802   st->init = sequencer_init;
803   st->duplicate = sequencer_duplicate;
804   st->operatortypes = sequencer_operatortypes;
805   st->keymap = sequencer_keymap;
806   st->context = sequencer_context;
807   st->dropboxes = sequencer_dropboxes;
808   st->refresh = sequencer_refresh;
809   st->listener = sequencer_listener;
810   st->id_remap = sequencer_id_remap;
811
812   /* regions: main window */
813   art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
814   art->regionid = RGN_TYPE_WINDOW;
815   art->init = sequencer_main_region_init;
816   art->draw = sequencer_main_region_draw;
817   art->listener = sequencer_main_region_listener;
818   art->message_subscribe = sequencer_main_region_message_subscribe;
819   art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
820
821   BLI_addhead(&st->regiontypes, art);
822
823   /* preview */
824   art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
825   art->regionid = RGN_TYPE_PREVIEW;
826   art->init = sequencer_preview_region_init;
827   art->draw = sequencer_preview_region_draw;
828   art->listener = sequencer_preview_region_listener;
829   art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
830   BLI_addhead(&st->regiontypes, art);
831
832   /* regions: listview/buttons */
833   art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
834   art->regionid = RGN_TYPE_UI;
835   art->prefsizex = 220;  // XXX
836   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
837   art->listener = sequencer_buttons_region_listener;
838   art->init = sequencer_buttons_region_init;
839   art->draw = sequencer_buttons_region_draw;
840   BLI_addhead(&st->regiontypes, art);
841
842   sequencer_buttons_register(art);
843
844   /* regions: header */
845   art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
846   art->regionid = RGN_TYPE_HEADER;
847   art->prefsizey = HEADERY;
848   art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
849
850   art->init = sequencer_header_region_init;
851   art->draw = sequencer_header_region_draw;
852   art->listener = sequencer_main_region_listener;
853
854   BLI_addhead(&st->regiontypes, art);
855
856   BKE_spacetype_register(st);
857
858   /* set the sequencer callback when not in background mode */
859   if (G.background == 0) {
860     sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple;
861   }
862 }