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