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