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