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