Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / space_clip / space_clip.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup spclip
22  */
23
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "DNA_scene_types.h"
28 #include "DNA_mask_types.h"
29 #include "DNA_movieclip_types.h"
30 #include "DNA_view3d_types.h" /* for pivot point */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_utildefines.h"
36 #include "BLI_math.h"
37
38 #include "BKE_context.h"
39 #include "BKE_library.h"
40 #include "BKE_movieclip.h"
41 #include "BKE_tracking.h"
42 #include "BKE_screen.h"
43
44 #include "IMB_imbuf_types.h"
45
46 #include "ED_anim_api.h" /* for timeline cursor drawing */
47 #include "ED_mask.h"
48 #include "ED_space_api.h"
49 #include "ED_screen.h"
50 #include "ED_select_utils.h"
51 #include "ED_clip.h"
52 #include "ED_transform.h"
53 #include "ED_uvedit.h" /* just for ED_image_draw_cursor */
54
55 #include "IMB_imbuf.h"
56
57 #include "GPU_glew.h"
58 #include "GPU_matrix.h"
59 #include "GPU_framebuffer.h"
60
61 #include "WM_api.h"
62 #include "WM_types.h"
63
64 #include "UI_interface.h"
65 #include "UI_resources.h"
66 #include "UI_view2d.h"
67
68 #include "RNA_access.h"
69
70 #include "clip_intern.h" /* own include */
71
72 static void init_preview_region(const Scene *scene,
73                                 const ScrArea *sa,
74                                 const SpaceClip *sc,
75                                 ARegion *ar)
76 {
77   ar->regiontype = RGN_TYPE_PREVIEW;
78   ar->alignment = RGN_ALIGN_TOP;
79   ar->flag |= RGN_FLAG_HIDDEN;
80
81   if (sc->view == SC_VIEW_DOPESHEET) {
82     ar->v2d.tot.xmin = -10.0f;
83     ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
84     ar->v2d.tot.xmax = (float)(sa->winx);
85     ar->v2d.tot.ymax = 0.0f;
86
87     ar->v2d.cur = ar->v2d.tot;
88
89     ar->v2d.min[0] = 0.0f;
90     ar->v2d.min[1] = 0.0f;
91
92     ar->v2d.max[0] = MAXFRAMEF;
93     ar->v2d.max[1] = FLT_MAX;
94
95     ar->v2d.minzoom = 0.01f;
96     ar->v2d.maxzoom = 50;
97     ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
98     ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
99     ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
100     ar->v2d.keepofs = V2D_KEEPOFS_Y;
101     ar->v2d.align = V2D_ALIGN_NO_POS_Y;
102     ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
103   }
104   else {
105     ar->v2d.tot.xmin = 0.0f;
106     ar->v2d.tot.ymin = -10.0f;
107     ar->v2d.tot.xmax = (float)scene->r.efra;
108     ar->v2d.tot.ymax = 10.0f;
109
110     ar->v2d.cur = ar->v2d.tot;
111
112     ar->v2d.min[0] = FLT_MIN;
113     ar->v2d.min[1] = FLT_MIN;
114
115     ar->v2d.max[0] = MAXFRAMEF;
116     ar->v2d.max[1] = FLT_MAX;
117
118     ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
119     ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
120
121     ar->v2d.minzoom = 0.0f;
122     ar->v2d.maxzoom = 0.0f;
123     ar->v2d.keepzoom = 0;
124     ar->v2d.keepofs = 0;
125     ar->v2d.align = 0;
126     ar->v2d.flag = 0;
127
128     ar->v2d.keeptot = 0;
129   }
130 }
131
132 static void reinit_preview_region(const bContext *C, ARegion *ar)
133 {
134   Scene *scene = CTX_data_scene(C);
135   ScrArea *sa = CTX_wm_area(C);
136   SpaceClip *sc = CTX_wm_space_clip(C);
137
138   if (sc->view == SC_VIEW_DOPESHEET) {
139     if ((ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) == 0) {
140       init_preview_region(scene, sa, sc, ar);
141     }
142   }
143   else {
144     if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
145       init_preview_region(scene, sa, sc, ar);
146     }
147   }
148 }
149
150 static ARegion *ED_clip_has_preview_region(const bContext *C, ScrArea *sa)
151 {
152   ARegion *ar, *arnew;
153
154   ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
155   if (ar) {
156     return ar;
157   }
158
159   /* add subdiv level; after header */
160   ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
161
162   /* is error! */
163   if (ar == NULL) {
164     return NULL;
165   }
166
167   arnew = MEM_callocN(sizeof(ARegion), "clip preview region");
168
169   BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
170   init_preview_region(CTX_data_scene(C), sa, CTX_wm_space_clip(C), arnew);
171
172   return arnew;
173 }
174
175 static ARegion *ED_clip_has_channels_region(ScrArea *sa)
176 {
177   ARegion *ar, *arnew;
178
179   ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
180   if (ar) {
181     return ar;
182   }
183
184   /* add subdiv level; after header */
185   ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
186
187   /* is error! */
188   if (ar == NULL) {
189     return NULL;
190   }
191
192   arnew = MEM_callocN(sizeof(ARegion), "clip channels region");
193
194   BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
195   arnew->regiontype = RGN_TYPE_CHANNELS;
196   arnew->alignment = RGN_ALIGN_LEFT;
197
198   arnew->v2d.scroll = V2D_SCROLL_BOTTOM;
199   arnew->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
200
201   return arnew;
202 }
203
204 static void clip_scopes_tag_refresh(ScrArea *sa)
205 {
206   SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
207   ARegion *ar;
208
209   if (sc->mode != SC_MODE_TRACKING) {
210     return;
211   }
212
213   /* only while properties are visible */
214   for (ar = sa->regionbase.first; ar; ar = ar->next) {
215     if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN) {
216       return;
217     }
218   }
219
220   sc->scopes.ok = false;
221 }
222
223 static void clip_scopes_check_gpencil_change(ScrArea *sa)
224 {
225   SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
226
227   if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
228     clip_scopes_tag_refresh(sa);
229   }
230 }
231
232 static void clip_area_sync_frame_from_scene(ScrArea *sa, Scene *scene)
233 {
234   SpaceClip *space_clip = (SpaceClip *)sa->spacedata.first;
235   BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra);
236 }
237
238 /* ******************** default callbacks for clip space ***************** */
239
240 static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
241 {
242   ARegion *ar;
243   SpaceClip *sc;
244
245   sc = MEM_callocN(sizeof(SpaceClip), "initclip");
246   sc->spacetype = SPACE_CLIP;
247   sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH | SC_SHOW_GRAPH_TRACKS_MOTION |
248              SC_SHOW_GRAPH_FRAMES | SC_SHOW_ANNOTATION;
249   sc->zoom = 1.0f;
250   sc->path_length = 20;
251   sc->scopes.track_preview_height = 120;
252   sc->around = V3D_AROUND_LOCAL_ORIGINS;
253
254   /* header */
255   ar = MEM_callocN(sizeof(ARegion), "header for clip");
256
257   BLI_addtail(&sc->regionbase, ar);
258   ar->regiontype = RGN_TYPE_HEADER;
259   ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
260
261   /* tools view */
262   ar = MEM_callocN(sizeof(ARegion), "tools for clip");
263
264   BLI_addtail(&sc->regionbase, ar);
265   ar->regiontype = RGN_TYPE_TOOLS;
266   ar->alignment = RGN_ALIGN_LEFT;
267
268   /* properties view */
269   ar = MEM_callocN(sizeof(ARegion), "properties for clip");
270
271   BLI_addtail(&sc->regionbase, ar);
272   ar->regiontype = RGN_TYPE_UI;
273   ar->alignment = RGN_ALIGN_RIGHT;
274
275   /* channels view */
276   ar = MEM_callocN(sizeof(ARegion), "channels for clip");
277
278   BLI_addtail(&sc->regionbase, ar);
279   ar->regiontype = RGN_TYPE_CHANNELS;
280   ar->alignment = RGN_ALIGN_LEFT;
281
282   ar->v2d.scroll = V2D_SCROLL_BOTTOM;
283   ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
284
285   /* preview view */
286   ar = MEM_callocN(sizeof(ARegion), "preview for clip");
287
288   BLI_addtail(&sc->regionbase, ar);
289   init_preview_region(scene, sa, sc, ar);
290
291   /* main region */
292   ar = MEM_callocN(sizeof(ARegion), "main region for clip");
293
294   BLI_addtail(&sc->regionbase, ar);
295   ar->regiontype = RGN_TYPE_WINDOW;
296
297   return (SpaceLink *)sc;
298 }
299
300 /* not spacelink itself */
301 static void clip_free(SpaceLink *sl)
302 {
303   SpaceClip *sc = (SpaceClip *)sl;
304
305   sc->clip = NULL;
306
307   if (sc->scopes.track_preview) {
308     IMB_freeImBuf(sc->scopes.track_preview);
309   }
310
311   if (sc->scopes.track_search) {
312     IMB_freeImBuf(sc->scopes.track_search);
313   }
314 }
315
316 /* spacetype; init callback */
317 static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
318 {
319   ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
320
321   /* add drop boxes */
322   WM_event_add_dropbox_handler(&sa->handlers, lb);
323 }
324
325 static SpaceLink *clip_duplicate(SpaceLink *sl)
326 {
327   SpaceClip *scn = MEM_dupallocN(sl);
328
329   /* clear or remove stuff from old */
330   scn->scopes.track_search = NULL;
331   scn->scopes.track_preview = NULL;
332   scn->scopes.ok = false;
333
334   return (SpaceLink *)scn;
335 }
336
337 static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *scene)
338 {
339   /* context changes */
340   switch (wmn->category) {
341     case NC_SCENE:
342       switch (wmn->data) {
343         case ND_FRAME:
344           clip_scopes_tag_refresh(sa);
345           ATTR_FALLTHROUGH;
346
347         case ND_FRAME_RANGE:
348           ED_area_tag_redraw(sa);
349           break;
350       }
351       break;
352     case NC_MOVIECLIP:
353       switch (wmn->data) {
354         case ND_DISPLAY:
355         case ND_SELECT:
356           clip_scopes_tag_refresh(sa);
357           ED_area_tag_redraw(sa);
358           break;
359       }
360       switch (wmn->action) {
361         case NA_REMOVED:
362         case NA_EDITED:
363         case NA_EVALUATED:
364           /* fall-through */
365
366         case NA_SELECTED:
367           clip_scopes_tag_refresh(sa);
368           ED_area_tag_redraw(sa);
369           break;
370       }
371       break;
372     case NC_MASK:
373       switch (wmn->data) {
374         case ND_SELECT:
375         case ND_DATA:
376         case ND_DRAW:
377           ED_area_tag_redraw(sa);
378           break;
379       }
380       switch (wmn->action) {
381         case NA_SELECTED:
382           ED_area_tag_redraw(sa);
383           break;
384         case NA_EDITED:
385           ED_area_tag_redraw(sa);
386           break;
387       }
388       break;
389     case NC_GEOM:
390       switch (wmn->data) {
391         case ND_SELECT:
392           clip_scopes_tag_refresh(sa);
393           ED_area_tag_redraw(sa);
394           break;
395       }
396       break;
397     case NC_SCREEN:
398       switch (wmn->data) {
399         case ND_ANIMPLAY:
400           ED_area_tag_redraw(sa);
401           break;
402         case ND_LAYOUTSET:
403           clip_area_sync_frame_from_scene(sa, scene);
404           break;
405       }
406       break;
407     case NC_SPACE:
408       if (wmn->data == ND_SPACE_CLIP) {
409         clip_scopes_tag_refresh(sa);
410         ED_area_tag_redraw(sa);
411       }
412       break;
413     case NC_GPENCIL:
414       if (wmn->action == NA_EDITED) {
415         clip_scopes_check_gpencil_change(sa);
416         ED_area_tag_redraw(sa);
417       }
418       else if (wmn->data & ND_GPENCIL_EDITMODE) {
419         ED_area_tag_redraw(sa);
420       }
421       break;
422   }
423 }
424
425 static void clip_operatortypes(void)
426 {
427   /* ** clip_ops.c ** */
428   WM_operatortype_append(CLIP_OT_open);
429   WM_operatortype_append(CLIP_OT_reload);
430   WM_operatortype_append(CLIP_OT_view_pan);
431   WM_operatortype_append(CLIP_OT_view_zoom);
432   WM_operatortype_append(CLIP_OT_view_zoom_in);
433   WM_operatortype_append(CLIP_OT_view_zoom_out);
434   WM_operatortype_append(CLIP_OT_view_zoom_ratio);
435   WM_operatortype_append(CLIP_OT_view_all);
436   WM_operatortype_append(CLIP_OT_view_selected);
437   WM_operatortype_append(CLIP_OT_change_frame);
438   WM_operatortype_append(CLIP_OT_rebuild_proxy);
439   WM_operatortype_append(CLIP_OT_mode_set);
440 #ifdef WITH_INPUT_NDOF
441   WM_operatortype_append(CLIP_OT_view_ndof);
442 #endif
443   WM_operatortype_append(CLIP_OT_prefetch);
444   WM_operatortype_append(CLIP_OT_set_scene_frames);
445   WM_operatortype_append(CLIP_OT_cursor_set);
446
447   /* ** tracking_ops.c ** */
448
449   /* navigation */
450   WM_operatortype_append(CLIP_OT_frame_jump);
451
452   /* set optical center to frame center */
453   WM_operatortype_append(CLIP_OT_set_center_principal);
454
455   /* selection */
456   WM_operatortype_append(CLIP_OT_select);
457   WM_operatortype_append(CLIP_OT_select_all);
458   WM_operatortype_append(CLIP_OT_select_box);
459   WM_operatortype_append(CLIP_OT_select_lasso);
460   WM_operatortype_append(CLIP_OT_select_circle);
461   WM_operatortype_append(CLIP_OT_select_grouped);
462
463   /* markers */
464   WM_operatortype_append(CLIP_OT_add_marker);
465   WM_operatortype_append(CLIP_OT_add_marker_at_click);
466   WM_operatortype_append(CLIP_OT_slide_marker);
467   WM_operatortype_append(CLIP_OT_delete_track);
468   WM_operatortype_append(CLIP_OT_delete_marker);
469
470   /* track */
471   WM_operatortype_append(CLIP_OT_track_markers);
472   WM_operatortype_append(CLIP_OT_refine_markers);
473
474   /* solving */
475   WM_operatortype_append(CLIP_OT_solve_camera);
476   WM_operatortype_append(CLIP_OT_clear_solution);
477
478   WM_operatortype_append(CLIP_OT_disable_markers);
479   WM_operatortype_append(CLIP_OT_hide_tracks);
480   WM_operatortype_append(CLIP_OT_hide_tracks_clear);
481   WM_operatortype_append(CLIP_OT_lock_tracks);
482
483   WM_operatortype_append(CLIP_OT_set_solver_keyframe);
484
485   /* orientation */
486   WM_operatortype_append(CLIP_OT_set_origin);
487   WM_operatortype_append(CLIP_OT_set_plane);
488   WM_operatortype_append(CLIP_OT_set_axis);
489   WM_operatortype_append(CLIP_OT_set_scale);
490   WM_operatortype_append(CLIP_OT_set_solution_scale);
491   WM_operatortype_append(CLIP_OT_apply_solution_scale);
492
493   /* detect */
494   WM_operatortype_append(CLIP_OT_detect_features);
495
496   /* stabilization */
497   WM_operatortype_append(CLIP_OT_stabilize_2d_add);
498   WM_operatortype_append(CLIP_OT_stabilize_2d_remove);
499   WM_operatortype_append(CLIP_OT_stabilize_2d_select);
500   WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_add);
501   WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_remove);
502   WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_select);
503
504   /* clean-up */
505   WM_operatortype_append(CLIP_OT_clear_track_path);
506   WM_operatortype_append(CLIP_OT_join_tracks);
507   WM_operatortype_append(CLIP_OT_track_copy_color);
508
509   WM_operatortype_append(CLIP_OT_clean_tracks);
510
511   /* object tracking */
512   WM_operatortype_append(CLIP_OT_tracking_object_new);
513   WM_operatortype_append(CLIP_OT_tracking_object_remove);
514
515   /* clipboard */
516   WM_operatortype_append(CLIP_OT_copy_tracks);
517   WM_operatortype_append(CLIP_OT_paste_tracks);
518
519   /* Plane tracker */
520   WM_operatortype_append(CLIP_OT_create_plane_track);
521   WM_operatortype_append(CLIP_OT_slide_plane_marker);
522
523   WM_operatortype_append(CLIP_OT_keyframe_insert);
524   WM_operatortype_append(CLIP_OT_keyframe_delete);
525
526   /* ** clip_graph_ops.c  ** */
527
528   /* graph editing */
529
530   /* selection */
531   WM_operatortype_append(CLIP_OT_graph_select);
532   WM_operatortype_append(CLIP_OT_graph_select_box);
533   WM_operatortype_append(CLIP_OT_graph_select_all_markers);
534
535   WM_operatortype_append(CLIP_OT_graph_delete_curve);
536   WM_operatortype_append(CLIP_OT_graph_delete_knot);
537   WM_operatortype_append(CLIP_OT_graph_view_all);
538   WM_operatortype_append(CLIP_OT_graph_center_current_frame);
539
540   WM_operatortype_append(CLIP_OT_graph_disable_markers);
541
542   /* ** clip_dopesheet_ops.c  ** */
543
544   WM_operatortype_append(CLIP_OT_dopesheet_select_channel);
545   WM_operatortype_append(CLIP_OT_dopesheet_view_all);
546 }
547
548 static void clip_keymap(struct wmKeyConfig *keyconf)
549 {
550   /* ******** Global hotkeys avalaible for all regions ******** */
551   WM_keymap_ensure(keyconf, "Clip", SPACE_CLIP, 0);
552
553   /* ******** Hotkeys avalaible for main region only ******** */
554   WM_keymap_ensure(keyconf, "Clip Editor", SPACE_CLIP, 0);
555   //  keymap->poll = ED_space_clip_tracking_poll;
556
557   /* ******** Hotkeys avalaible for preview region only ******** */
558   WM_keymap_ensure(keyconf, "Clip Graph Editor", SPACE_CLIP, 0);
559
560   /* ******** Hotkeys avalaible for channels region only ******** */
561   WM_keymap_ensure(keyconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
562 }
563
564 /* DO NOT make this static, this hides the symbol and breaks API generation script. */
565 extern const char *clip_context_dir[]; /* quiet warning. */
566 const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL};
567
568 static int clip_context(const bContext *C, const char *member, bContextDataResult *result)
569 {
570   SpaceClip *sc = CTX_wm_space_clip(C);
571
572   if (CTX_data_dir(member)) {
573     CTX_data_dir_set(result, clip_context_dir);
574
575     return true;
576   }
577   else if (CTX_data_equals(member, "edit_movieclip")) {
578     if (sc->clip) {
579       CTX_data_id_pointer_set(result, &sc->clip->id);
580     }
581     return true;
582   }
583   else if (CTX_data_equals(member, "edit_mask")) {
584     if (sc->mask_info.mask) {
585       CTX_data_id_pointer_set(result, &sc->mask_info.mask->id);
586     }
587     return true;
588   }
589
590   return false;
591 }
592
593 /* dropboxes */
594 static bool clip_drop_poll(bContext *UNUSED(C),
595                            wmDrag *drag,
596                            const wmEvent *UNUSED(event),
597                            const char **UNUSED(tooltip))
598 {
599   if (drag->type == WM_DRAG_PATH) {
600     /* rule might not work? */
601     if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) {
602       return true;
603     }
604   }
605
606   return false;
607 }
608
609 static void clip_drop_copy(wmDrag *drag, wmDropBox *drop)
610 {
611   PointerRNA itemptr;
612   char dir[FILE_MAX], file[FILE_MAX];
613
614   BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
615
616   RNA_string_set(drop->ptr, "directory", dir);
617
618   RNA_collection_clear(drop->ptr, "files");
619   RNA_collection_add(drop->ptr, "files", &itemptr);
620   RNA_string_set(&itemptr, "name", file);
621 }
622
623 /* area+region dropbox definition */
624 static void clip_dropboxes(void)
625 {
626   ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
627
628   WM_dropbox_add(lb, "CLIP_OT_open", clip_drop_poll, clip_drop_copy);
629 }
630
631 static void clip_refresh(const bContext *C, ScrArea *sa)
632 {
633   wmWindowManager *wm = CTX_wm_manager(C);
634   wmWindow *window = CTX_wm_window(C);
635   Scene *scene = CTX_data_scene(C);
636   SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
637   ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
638   ARegion *ar_tools = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
639   ARegion *ar_preview = ED_clip_has_preview_region(C, sa);
640   ARegion *ar_properties = ED_clip_has_properties_region(sa);
641   ARegion *ar_channels = ED_clip_has_channels_region(sa);
642   bool main_visible = false, preview_visible = false, tools_visible = false;
643   bool properties_visible = false, channels_visible = false;
644   bool view_changed = false;
645
646   switch (sc->view) {
647     case SC_VIEW_CLIP:
648       main_visible = true;
649       preview_visible = false;
650       tools_visible = true;
651       properties_visible = true;
652       channels_visible = false;
653       break;
654     case SC_VIEW_GRAPH:
655       main_visible = false;
656       preview_visible = true;
657       tools_visible = false;
658       properties_visible = false;
659       channels_visible = false;
660
661       reinit_preview_region(C, ar_preview);
662       break;
663     case SC_VIEW_DOPESHEET:
664       main_visible = false;
665       preview_visible = true;
666       tools_visible = false;
667       properties_visible = false;
668       channels_visible = true;
669
670       reinit_preview_region(C, ar_preview);
671       break;
672   }
673
674   if (main_visible) {
675     if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
676       ar_main->flag &= ~RGN_FLAG_HIDDEN;
677       ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
678       view_changed = true;
679     }
680
681     if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
682       ar_main->alignment = RGN_ALIGN_NONE;
683       view_changed = true;
684     }
685   }
686   else {
687     if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) {
688       ar_main->flag |= RGN_FLAG_HIDDEN;
689       ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
690       WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
691       view_changed = true;
692     }
693     if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
694       ar_main->alignment = RGN_ALIGN_NONE;
695       view_changed = true;
696     }
697   }
698
699   if (properties_visible) {
700     if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) {
701       ar_properties->flag &= ~RGN_FLAG_HIDDEN;
702       ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
703       view_changed = true;
704     }
705     if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
706       ar_properties->alignment = RGN_ALIGN_RIGHT;
707       view_changed = true;
708     }
709   }
710   else {
711     if (ar_properties && !(ar_properties->flag & RGN_FLAG_HIDDEN)) {
712       ar_properties->flag |= RGN_FLAG_HIDDEN;
713       ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
714       WM_event_remove_handlers((bContext *)C, &ar_properties->handlers);
715       view_changed = true;
716     }
717     if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
718       ar_properties->alignment = RGN_ALIGN_NONE;
719       view_changed = true;
720     }
721   }
722
723   if (tools_visible) {
724     if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) {
725       ar_tools->flag &= ~RGN_FLAG_HIDDEN;
726       ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
727       view_changed = true;
728     }
729     if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
730       ar_tools->alignment = RGN_ALIGN_LEFT;
731       view_changed = true;
732     }
733   }
734   else {
735     if (ar_tools && !(ar_tools->flag & RGN_FLAG_HIDDEN)) {
736       ar_tools->flag |= RGN_FLAG_HIDDEN;
737       ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
738       WM_event_remove_handlers((bContext *)C, &ar_tools->handlers);
739       view_changed = true;
740     }
741     if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
742       ar_tools->alignment = RGN_ALIGN_NONE;
743       view_changed = true;
744     }
745   }
746
747   if (preview_visible) {
748     if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
749       ar_preview->flag &= ~RGN_FLAG_HIDDEN;
750       ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
751       ar_preview->v2d.cur = ar_preview->v2d.tot;
752       view_changed = true;
753     }
754     if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
755       ar_preview->alignment = RGN_ALIGN_NONE;
756       view_changed = true;
757     }
758   }
759   else {
760     if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
761       ar_preview->flag |= RGN_FLAG_HIDDEN;
762       ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
763       WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
764       view_changed = true;
765     }
766     if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
767       ar_preview->alignment = RGN_ALIGN_NONE;
768       view_changed = true;
769     }
770   }
771
772   if (channels_visible) {
773     if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) {
774       ar_channels->flag &= ~RGN_FLAG_HIDDEN;
775       ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
776       view_changed = true;
777     }
778     if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
779       ar_channels->alignment = RGN_ALIGN_LEFT;
780       view_changed = true;
781     }
782   }
783   else {
784     if (ar_channels && !(ar_channels->flag & RGN_FLAG_HIDDEN)) {
785       ar_channels->flag |= RGN_FLAG_HIDDEN;
786       ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
787       WM_event_remove_handlers((bContext *)C, &ar_channels->handlers);
788       view_changed = true;
789     }
790     if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
791       ar_channels->alignment = RGN_ALIGN_NONE;
792       view_changed = true;
793     }
794   }
795
796   if (view_changed) {
797     ED_area_initialize(wm, window, sa);
798     ED_area_tag_redraw(sa);
799   }
800
801   BKE_movieclip_user_set_frame(&sc->user, scene->r.cfra);
802 }
803
804 /********************* main region ********************/
805
806 /* sets up the fields of the View2D from zoom and offset */
807 static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
808 {
809   SpaceClip *sc = CTX_wm_space_clip(C);
810   float x1, y1, w, h, aspx, aspy;
811   int width, height, winx, winy;
812
813   ED_space_clip_get_size(sc, &width, &height);
814   ED_space_clip_get_aspect(sc, &aspx, &aspy);
815
816   w = width * aspx;
817   h = height * aspy;
818
819   winx = BLI_rcti_size_x(&ar->winrct) + 1;
820   winy = BLI_rcti_size_y(&ar->winrct) + 1;
821
822   ar->v2d.tot.xmin = 0;
823   ar->v2d.tot.ymin = 0;
824   ar->v2d.tot.xmax = w;
825   ar->v2d.tot.ymax = h;
826
827   ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
828   ar->v2d.mask.xmax = winx;
829   ar->v2d.mask.ymax = winy;
830
831   /* which part of the image space do we see? */
832   x1 = ar->winrct.xmin + (winx - sc->zoom * w) / 2.0f;
833   y1 = ar->winrct.ymin + (winy - sc->zoom * h) / 2.0f;
834
835   x1 -= sc->zoom * sc->xof;
836   y1 -= sc->zoom * sc->yof;
837
838   /* relative display right */
839   ar->v2d.cur.xmin = (ar->winrct.xmin - (float)x1) / sc->zoom;
840   ar->v2d.cur.xmax = ar->v2d.cur.xmin + ((float)winx / sc->zoom);
841
842   /* relative display left */
843   ar->v2d.cur.ymin = (ar->winrct.ymin - (float)y1) / sc->zoom;
844   ar->v2d.cur.ymax = ar->v2d.cur.ymin + ((float)winy / sc->zoom);
845
846   /* normalize 0.0..1.0 */
847   ar->v2d.cur.xmin /= w;
848   ar->v2d.cur.xmax /= w;
849   ar->v2d.cur.ymin /= h;
850   ar->v2d.cur.ymax /= h;
851 }
852
853 /* add handlers, stuff you only do once or on area/region changes */
854 static void clip_main_region_init(wmWindowManager *wm, ARegion *ar)
855 {
856   wmKeyMap *keymap;
857
858   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
859
860   /* mask polls mode */
861   keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
862   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
863
864   /* own keymap */
865   keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
866   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
867
868   keymap = WM_keymap_ensure(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0);
869   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
870 }
871
872 static void clip_main_region_draw(const bContext *C, ARegion *ar)
873 {
874   /* draw entirely, view changes should be handled here */
875   SpaceClip *sc = CTX_wm_space_clip(C);
876   MovieClip *clip = ED_space_clip_get_clip(sc);
877   float aspx, aspy, zoomx, zoomy, x, y;
878   int width, height;
879   bool show_cursor = false;
880
881   /* if tracking is in progress, we should synchronize framenr from clipuser
882    * so latest tracked frame would be shown */
883   if (clip && clip->tracking_context) {
884     BKE_autotrack_context_sync_user(clip->tracking_context, &sc->user);
885   }
886
887   if (sc->flag & SC_LOCK_SELECTION) {
888     ImBuf *tmpibuf = NULL;
889
890     if (clip && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
891       tmpibuf = ED_space_clip_get_stable_buffer(sc, NULL, NULL, NULL);
892     }
893
894     if (ED_clip_view_selection(C, ar, 0)) {
895       sc->xof += sc->xlockof;
896       sc->yof += sc->ylockof;
897     }
898
899     if (tmpibuf) {
900       IMB_freeImBuf(tmpibuf);
901     }
902   }
903
904   /* clear and setup matrix */
905   UI_ThemeClearColor(TH_BACK);
906   GPU_clear(GPU_COLOR_BIT);
907
908   /* data... */
909   movieclip_main_area_set_view2d(C, ar);
910
911   /* callback */
912   ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
913
914   clip_draw_main(C, sc, ar);
915
916   /* TODO(sergey): would be nice to find a way to de-duplicate all this space conversions */
917   UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
918   ED_space_clip_get_size(sc, &width, &height);
919   ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
920   ED_space_clip_get_aspect(sc, &aspx, &aspy);
921
922   if (sc->mode == SC_MODE_MASKEDIT) {
923     Mask *mask = CTX_data_edit_mask(C);
924     if (mask && clip) {
925       ScrArea *sa = CTX_wm_area(C);
926       int mask_width, mask_height;
927       ED_mask_get_size(sa, &mask_width, &mask_height);
928       ED_mask_draw_region(mask,
929                           ar,
930                           sc->mask_info.draw_flag,
931                           sc->mask_info.draw_type,
932                           sc->mask_info.overlay_mode,
933                           mask_width,
934                           mask_height,
935                           aspx,
936                           aspy,
937                           true,
938                           true,
939                           sc->stabmat,
940                           C);
941     }
942   }
943
944   show_cursor |= sc->mode == SC_MODE_MASKEDIT;
945   show_cursor |= sc->around == V3D_AROUND_CURSOR;
946
947   if (show_cursor) {
948     GPU_matrix_push();
949     GPU_matrix_translate_2f(x, y);
950     GPU_matrix_scale_2f(zoomx, zoomy);
951     GPU_matrix_mul(sc->stabmat);
952     GPU_matrix_scale_2f(width, height);
953     ED_image_draw_cursor(ar, sc->cursor);
954     GPU_matrix_pop();
955   }
956
957   clip_draw_cache_and_notes(C, sc, ar);
958
959   if (sc->flag & SC_SHOW_ANNOTATION) {
960     /* Grease Pencil */
961     clip_draw_grease_pencil((bContext *)C, true);
962   }
963
964   /* callback */
965   ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
966
967   /* reset view matrix */
968   UI_view2d_view_restore(C);
969
970   if (sc->flag & SC_SHOW_ANNOTATION) {
971     /* draw Grease Pencil - screen space only */
972     clip_draw_grease_pencil((bContext *)C, false);
973   }
974 }
975
976 static void clip_main_region_listener(wmWindow *UNUSED(win),
977                                       ScrArea *UNUSED(sa),
978                                       ARegion *ar,
979                                       wmNotifier *wmn,
980                                       const Scene *UNUSED(scene))
981 {
982   /* context changes */
983   switch (wmn->category) {
984     case NC_GPENCIL:
985       if (wmn->action == NA_EDITED) {
986         ED_region_tag_redraw(ar);
987       }
988       else if (wmn->data & ND_GPENCIL_EDITMODE) {
989         ED_region_tag_redraw(ar);
990       }
991       break;
992   }
993 }
994
995 /****************** preview region ******************/
996
997 static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
998 {
999   wmKeyMap *keymap;
1000
1001   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
1002
1003   /* own keymap */
1004   keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
1005   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
1006
1007   keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
1008   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
1009
1010   keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
1011   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
1012 }
1013
1014 static void graph_region_draw(const bContext *C, ARegion *ar)
1015 {
1016   View2D *v2d = &ar->v2d;
1017   View2DScrollers *scrollers;
1018   SpaceClip *sc = CTX_wm_space_clip(C);
1019   Scene *scene = CTX_data_scene(C);
1020   short unitx, unity;
1021   short cfra_flag = 0;
1022
1023   if (sc->flag & SC_LOCK_TIMECURSOR) {
1024     ED_clip_graph_center_current_frame(scene, ar);
1025   }
1026
1027   /* clear and setup matrix */
1028   UI_ThemeClearColor(TH_BACK);
1029   GPU_clear(GPU_COLOR_BIT);
1030
1031   UI_view2d_view_ortho(v2d);
1032
1033   /* data... */
1034   clip_draw_graph(sc, ar, scene);
1035
1036   /* current frame indicator line */
1037   if (sc->flag & SC_SHOW_SECONDS) {
1038     cfra_flag |= DRAWCFRA_UNIT_SECONDS;
1039   }
1040   ANIM_draw_cfra(C, v2d, cfra_flag);
1041
1042   /* reset view matrix */
1043   UI_view2d_view_restore(C);
1044
1045   /* scrollers */
1046   unitx = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
1047   unity = V2D_UNIT_VALUES;
1048   scrollers = UI_view2d_scrollers_calc(
1049       C, v2d, NULL, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP);
1050   UI_view2d_scrollers_draw(C, v2d, scrollers);
1051   UI_view2d_scrollers_free(scrollers);
1052
1053   /* current frame indicator */
1054   if (sc->flag & SC_SHOW_SECONDS) {
1055     cfra_flag |= DRAWCFRA_UNIT_SECONDS;
1056   }
1057   UI_view2d_view_orthoSpecial(ar, v2d, 1);
1058   ANIM_draw_cfra_number(C, v2d, cfra_flag);
1059 }
1060
1061 static void dopesheet_region_draw(const bContext *C, ARegion *ar)
1062 {
1063   Scene *scene = CTX_data_scene(C);
1064   SpaceClip *sc = CTX_wm_space_clip(C);
1065   MovieClip *clip = ED_space_clip_get_clip(sc);
1066   View2D *v2d = &ar->v2d;
1067   View2DGrid *grid;
1068   View2DScrollers *scrollers;
1069   short unit = 0, cfra_flag = 0;
1070
1071   if (clip) {
1072     BKE_tracking_dopesheet_update(&clip->tracking);
1073   }
1074
1075   /* clear and setup matrix */
1076   UI_ThemeClearColor(TH_BACK);
1077   GPU_clear(GPU_COLOR_BIT);
1078
1079   UI_view2d_view_ortho(v2d);
1080
1081   /* time grid */
1082   unit = (sc->flag & SC_SHOW_SECONDS) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
1083   grid = UI_view2d_grid_calc(
1084       scene, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
1085   UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
1086   UI_view2d_grid_free(grid);
1087
1088   /* data... */
1089   clip_draw_dopesheet_main(sc, ar, scene);
1090
1091   /* current frame indicator line */
1092   if (sc->flag & SC_SHOW_SECONDS) {
1093     cfra_flag |= DRAWCFRA_UNIT_SECONDS;
1094   }
1095   ANIM_draw_cfra(C, v2d, cfra_flag);
1096
1097   /* reset view matrix */
1098   UI_view2d_view_restore(C);
1099
1100   /* scrollers */
1101   scrollers = UI_view2d_scrollers_calc(
1102       C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
1103   UI_view2d_scrollers_draw(C, v2d, scrollers);
1104   UI_view2d_scrollers_free(scrollers);
1105
1106   /* current frame number indicator */
1107   UI_view2d_view_orthoSpecial(ar, v2d, 1);
1108   ANIM_draw_cfra_number(C, v2d, cfra_flag);
1109 }
1110
1111 static void clip_preview_region_draw(const bContext *C, ARegion *ar)
1112 {
1113   SpaceClip *sc = CTX_wm_space_clip(C);
1114
1115   if (sc->view == SC_VIEW_GRAPH) {
1116     graph_region_draw(C, ar);
1117   }
1118   else if (sc->view == SC_VIEW_DOPESHEET) {
1119     dopesheet_region_draw(C, ar);
1120   }
1121 }
1122
1123 static void clip_preview_region_listener(wmWindow *UNUSED(win),
1124                                          ScrArea *UNUSED(sa),
1125                                          ARegion *UNUSED(ar),
1126                                          wmNotifier *UNUSED(wmn),
1127                                          const Scene *UNUSED(scene))
1128 {
1129 }
1130
1131 /****************** channels region ******************/
1132
1133 static void clip_channels_region_init(wmWindowManager *wm, ARegion *ar)
1134 {
1135   wmKeyMap *keymap;
1136
1137   /* ensure the 2d view sync works - main region has bottom scroller */
1138   ar->v2d.scroll = V2D_SCROLL_BOTTOM;
1139
1140   UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
1141
1142   keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
1143   WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
1144 }
1145
1146 static void clip_channels_region_draw(const bContext *C, ARegion *ar)
1147 {
1148   SpaceClip *sc = CTX_wm_space_clip(C);
1149   MovieClip *clip = ED_space_clip_get_clip(sc);
1150   View2D *v2d = &ar->v2d;
1151
1152   if (clip) {
1153     BKE_tracking_dopesheet_update(&clip->tracking);
1154   }
1155
1156   /* clear and setup matrix */
1157   UI_ThemeClearColor(TH_BACK);
1158   GPU_clear(GPU_COLOR_BIT);
1159
1160   UI_view2d_view_ortho(v2d);
1161
1162   /* data... */
1163   clip_draw_dopesheet_channels(C, ar);
1164
1165   /* reset view matrix */
1166   UI_view2d_view_restore(C);
1167 }
1168
1169 static void clip_channels_region_listener(wmWindow *UNUSED(win),
1170                                           ScrArea *UNUSED(sa),
1171                                           ARegion *UNUSED(ar),
1172                                           wmNotifier *UNUSED(wmn),
1173                                           const Scene *UNUSED(scene))
1174 {
1175 }
1176
1177 /****************** header region ******************/
1178
1179 /* add handlers, stuff you only do once or on area/region changes */
1180 static void clip_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
1181 {
1182   ED_region_header_init(ar);
1183 }
1184
1185 static void clip_header_region_draw(const bContext *C, ARegion *ar)
1186 {
1187   ED_region_header(C, ar);
1188 }
1189
1190 static void clip_header_region_listener(wmWindow *UNUSED(win),
1191                                         ScrArea *UNUSED(sa),
1192                                         ARegion *ar,
1193                                         wmNotifier *wmn,
1194                                         const Scene *UNUSED(scene))
1195 {
1196   /* context changes */
1197   switch (wmn->category) {
1198     case NC_SCENE:
1199       switch (wmn->data) {
1200         /* for proportional editmode only */
1201         case ND_TOOLSETTINGS:
1202           /* TODO - should do this when in mask mode only but no datas available */
1203           // if (sc->mode == SC_MODE_MASKEDIT)
1204           {
1205             ED_region_tag_redraw(ar);
1206             break;
1207           }
1208       }
1209       break;
1210   }
1211 }
1212
1213 /****************** tools region ******************/
1214
1215 /* add handlers, stuff you only do once or on area/region changes */
1216 static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
1217 {
1218   wmKeyMap *keymap;
1219
1220   ED_region_panels_init(wm, ar);
1221
1222   keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
1223   WM_event_add_keymap_handler(&ar->handlers, keymap);
1224 }
1225
1226 static void clip_tools_region_draw(const bContext *C, ARegion *ar)
1227 {
1228   ED_region_panels(C, ar);
1229 }
1230
1231 /****************** tool properties region ******************/
1232
1233 static void clip_props_region_listener(wmWindow *UNUSED(win),
1234                                        ScrArea *UNUSED(sa),
1235                                        ARegion *ar,
1236                                        wmNotifier *wmn,
1237                                        const Scene *UNUSED(scene))
1238 {
1239   /* context changes */
1240   switch (wmn->category) {
1241     case NC_WM:
1242       if (wmn->data == ND_HISTORY) {
1243         ED_region_tag_redraw(ar);
1244       }
1245       break;
1246     case NC_SCENE:
1247       if (wmn->data == ND_MODE) {
1248         ED_region_tag_redraw(ar);
1249       }
1250       break;
1251     case NC_SPACE:
1252       if (wmn->data == ND_SPACE_CLIP) {
1253         ED_region_tag_redraw(ar);
1254       }
1255       break;
1256     case NC_GPENCIL:
1257       if (wmn->action == NA_EDITED) {
1258         ED_region_tag_redraw(ar);
1259       }
1260       break;
1261   }
1262 }
1263
1264 /****************** properties region ******************/
1265
1266 /* add handlers, stuff you only do once or on area/region changes */
1267 static void clip_properties_region_init(wmWindowManager *wm, ARegion *ar)
1268 {
1269   wmKeyMap *keymap;
1270
1271   ED_region_panels_init(wm, ar);
1272
1273   keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
1274   WM_event_add_keymap_handler(&ar->handlers, keymap);
1275 }
1276
1277 static void clip_properties_region_draw(const bContext *C, ARegion *ar)
1278 {
1279   SpaceClip *sc = CTX_wm_space_clip(C);
1280
1281   BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
1282
1283   ED_region_panels(C, ar);
1284 }
1285
1286 static void clip_properties_region_listener(wmWindow *UNUSED(win),
1287                                             ScrArea *UNUSED(sa),
1288                                             ARegion *ar,
1289                                             wmNotifier *wmn,
1290                                             const Scene *UNUSED(scene))
1291 {
1292   /* context changes */
1293   switch (wmn->category) {
1294     case NC_GPENCIL:
1295       if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE)) {
1296         ED_region_tag_redraw(ar);
1297       }
1298       break;
1299     case NC_BRUSH:
1300       if (wmn->action == NA_EDITED) {
1301         ED_region_tag_redraw(ar);
1302       }
1303       break;
1304   }
1305 }
1306
1307 /********************* registration ********************/
1308
1309 static void clip_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
1310 {
1311   SpaceClip *sclip = (SpaceClip *)slink;
1312
1313   if (!ELEM(GS(old_id->name), ID_MC, ID_MSK)) {
1314     return;
1315   }
1316
1317   if ((ID *)sclip->clip == old_id) {
1318     sclip->clip = (MovieClip *)new_id;
1319     id_us_ensure_real(new_id);
1320   }
1321
1322   if ((ID *)sclip->mask_info.mask == old_id) {
1323     sclip->mask_info.mask = (Mask *)new_id;
1324     id_us_ensure_real(new_id);
1325   }
1326 }
1327
1328 /* only called once, from space/spacetypes.c */
1329 void ED_spacetype_clip(void)
1330 {
1331   SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype clip");
1332   ARegionType *art;
1333
1334   st->spaceid = SPACE_CLIP;
1335   strncpy(st->name, "Clip", BKE_ST_MAXNAME);
1336
1337   st->new = clip_new;
1338   st->free = clip_free;
1339   st->init = clip_init;
1340   st->duplicate = clip_duplicate;
1341   st->operatortypes = clip_operatortypes;
1342   st->keymap = clip_keymap;
1343   st->listener = clip_listener;
1344   st->context = clip_context;
1345   st->dropboxes = clip_dropboxes;
1346   st->refresh = clip_refresh;
1347   st->id_remap = clip_id_remap;
1348
1349   /* regions: main window */
1350   art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
1351   art->regionid = RGN_TYPE_WINDOW;
1352   art->init = clip_main_region_init;
1353   art->draw = clip_main_region_draw;
1354   art->listener = clip_main_region_listener;
1355   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_GPENCIL;
1356
1357   BLI_addhead(&st->regiontypes, art);
1358
1359   /* preview */
1360   art = MEM_callocN(sizeof(ARegionType), "spacetype clip region preview");
1361   art->regionid = RGN_TYPE_PREVIEW;
1362   art->prefsizey = 240;
1363   art->init = clip_preview_region_init;
1364   art->draw = clip_preview_region_draw;
1365   art->listener = clip_preview_region_listener;
1366   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
1367
1368   BLI_addhead(&st->regiontypes, art);
1369
1370   /* regions: properties */
1371   art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties");
1372   art->regionid = RGN_TYPE_UI;
1373   art->prefsizex = UI_COMPACT_PANEL_WIDTH;
1374   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
1375   art->init = clip_properties_region_init;
1376   art->draw = clip_properties_region_draw;
1377   art->listener = clip_properties_region_listener;
1378   BLI_addhead(&st->regiontypes, art);
1379   ED_clip_buttons_register(art);
1380
1381   /* regions: tools */
1382   art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools");
1383   art->regionid = RGN_TYPE_TOOLS;
1384   art->prefsizex = UI_COMPACT_PANEL_WIDTH;
1385   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
1386   art->listener = clip_props_region_listener;
1387   art->init = clip_tools_region_init;
1388   art->draw = clip_tools_region_draw;
1389
1390   BLI_addhead(&st->regiontypes, art);
1391
1392   /* regions: header */
1393   art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
1394   art->regionid = RGN_TYPE_HEADER;
1395   art->prefsizey = HEADERY;
1396   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
1397
1398   art->init = clip_header_region_init;
1399   art->draw = clip_header_region_draw;
1400   art->listener = clip_header_region_listener;
1401
1402   BLI_addhead(&st->regiontypes, art);
1403
1404   BKE_spacetype_register(st);
1405
1406   /* channels */
1407   art = MEM_callocN(sizeof(ARegionType), "spacetype clip channels region");
1408   art->regionid = RGN_TYPE_CHANNELS;
1409   art->prefsizex = UI_COMPACT_PANEL_WIDTH;
1410   art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
1411   art->listener = clip_channels_region_listener;
1412   art->init = clip_channels_region_init;
1413   art->draw = clip_channels_region_draw;
1414
1415   BLI_addhead(&st->regiontypes, art);
1416
1417   /* regions: hud */
1418   art = ED_area_type_hud(st->spaceid);
1419   BLI_addhead(&st->regiontypes, art);
1420 }