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