Camera tracking: backport refactoring made in local branches with masking and dopeshe...
[blender.git] / source / blender / editors / space_clip / clip_editor.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_clip/clip_editor.c
29  *  \ingroup spclip
30  */
31
32 #include <stddef.h>
33
34 #include "BKE_main.h"
35 #include "BKE_movieclip.h"
36 #include "BKE_context.h"
37 #include "BKE_tracking.h"
38
39 #include "DNA_object_types.h"   /* SELECT */
40
41 #include "BLI_utildefines.h"
42 #include "BLI_math.h"
43
44 #include "IMB_imbuf_types.h"
45 #include "IMB_imbuf.h"
46
47 #include "ED_screen.h"
48 #include "ED_clip.h"
49
50 #include "BIF_gl.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "UI_view2d.h"
56
57 #include "clip_intern.h"        // own include
58
59 /* ******** operactor poll functions ******** */
60
61 int ED_space_clip_poll(bContext *C)
62 {
63         SpaceClip *sc = CTX_wm_space_clip(C);
64
65         if (sc && sc->clip)
66                 return TRUE;
67
68         return FALSE;
69 }
70
71 int ED_space_clip_tracking_poll(bContext *C)
72 {
73         SpaceClip *sc= CTX_wm_space_clip(C);
74
75         if (sc && sc->clip)
76                 return ED_space_clip_show_trackedit(sc);
77
78         return FALSE;
79 }
80
81 int ED_space_clip_tracking_size_poll(bContext *C)
82 {
83         if (ED_space_clip_tracking_poll(C)) {
84                 MovieClip *clip = CTX_data_edit_movieclip(C);
85
86                 if (clip) {
87                         SpaceClip *sc = CTX_wm_space_clip(C);
88                         int width, height;
89
90                         BKE_movieclip_get_size(clip, &sc->user, &width, &height);
91
92                         return width > 0 && height > 0;
93                 }
94         }
95
96         return FALSE;
97 }
98
99 int ED_space_clip_tracking_frame_poll(bContext *C)
100 {
101         if (ED_space_clip_tracking_poll(C)) {
102                 MovieClip *clip = CTX_data_edit_movieclip(C);
103
104                 if (clip) {
105                         SpaceClip *sc = CTX_wm_space_clip(C);
106
107                         return BKE_movieclip_has_frame(clip, &sc->user);
108                 }
109         }
110
111         return FALSE;
112 }
113
114 /* ******** editing functions ******** */
115
116 void ED_space_clip_set(bContext *C, SpaceClip *sc, MovieClip *clip)
117 {
118         sc->clip = clip;
119
120         if (sc->clip && sc->clip->id.us==0)
121                 sc->clip->id.us = 1;
122
123         if (C)
124                 WM_event_add_notifier(C, NC_MOVIECLIP|NA_SELECTED, sc->clip);
125 }
126
127 MovieClip *ED_space_clip(SpaceClip *sc)
128 {
129         return sc->clip;
130 }
131
132 ImBuf *ED_space_clip_get_buffer(SpaceClip *sc)
133 {
134         if (sc->clip) {
135                 ImBuf *ibuf;
136
137                 ibuf = BKE_movieclip_get_postprocessed_ibuf(sc->clip, &sc->user, sc->postproc_flag);
138
139                 if (ibuf && (ibuf->rect || ibuf->rect_float))
140                         return ibuf;
141
142                 if (ibuf)
143                         IMB_freeImBuf(ibuf);
144         }
145
146         return NULL;
147 }
148
149 ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale, float *angle)
150 {
151         if (sc->clip) {
152                 ImBuf *ibuf;
153
154                 ibuf = BKE_movieclip_get_stable_ibuf(sc->clip, &sc->user, loc, scale, angle, sc->postproc_flag);
155
156                 if (ibuf && (ibuf->rect || ibuf->rect_float))
157                         return ibuf;
158
159                 if (ibuf)
160                         IMB_freeImBuf(ibuf);
161         }
162
163         return NULL;
164 }
165
166 void ED_space_clip_size(SpaceClip *sc, int *width, int *height)
167 {
168         if (!sc->clip) {
169                 *width = *height = 0;
170         }
171         else {
172                 BKE_movieclip_get_size(sc->clip, &sc->user, width, height);
173         }
174 }
175
176 void ED_space_clip_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy)
177 {
178         int width, height;
179
180         ED_space_clip_size(sc, &width, &height);
181
182         *zoomx = (float)(ar->winrct.xmax - ar->winrct.xmin + 1)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
183         *zoomy = (float)(ar->winrct.ymax - ar->winrct.ymin + 1)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
184 }
185
186 void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy)
187 {
188         MovieClip *clip = ED_space_clip(sc);
189
190         if (clip)
191                 BKE_movieclip_aspect(clip, aspx, aspy);
192         else
193                 *aspx = *aspy = 1.0f;
194 }
195
196 void ED_clip_update_frame(const Main *mainp, int cfra)
197 {
198         wmWindowManager *wm;
199         wmWindow *win;
200
201         /* image window, compo node users */
202         for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
203                 for (win = wm->windows.first; win; win = win->next) {
204                         ScrArea *sa;
205
206                         for (sa = win->screen->areabase.first; sa; sa = sa->next) {
207                                 if (sa->spacetype == SPACE_CLIP) {
208                                         SpaceClip *sc = sa->spacedata.first;
209
210                                         sc->scopes.ok = FALSE;
211
212                                         BKE_movieclip_user_set_frame(&sc->user, cfra);
213                                 }
214                         }
215                 }
216         }
217 }
218
219 static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
220 {
221         MovieClip *clip = ED_space_clip(sc);
222         MovieTrackingTrack *track;
223         int width, height, ok = FALSE;
224         ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
225
226         INIT_MINMAX2(min, max);
227
228         ED_space_clip_size(sc, &width, &height);
229
230         track = tracksbase->first;
231         while (track) {
232                 if (TRACK_VIEW_SELECTED(sc, track)) {
233                         MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
234
235                         if (marker) {
236                                 float pos[3];
237
238                                 pos[0] = marker->pos[0] + track->offset[0];
239                                 pos[1] = marker->pos[1] + track->offset[1];
240                                 pos[2] = 0.0f;
241
242                                 /* undistortion happens for normalized coords */
243                                 if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
244                                         /* undistortion happens for normalized coords */
245                                         ED_clip_point_undistorted_pos(sc, pos, pos);
246                                 }
247
248                                 pos[0] *= width;
249                                 pos[1] *= height;
250
251                                 mul_v3_m4v3(pos, sc->stabmat, pos);
252
253                                 DO_MINMAX2(pos, min, max);
254
255                                 ok = TRUE;
256                         }
257                 }
258
259                 track = track->next;
260         }
261
262         return ok;
263 }
264
265 int ED_clip_view_selection(SpaceClip *sc, ARegion *ar, int fit)
266 {
267         int w, h, frame_width, frame_height;
268         float min[2], max[2];
269
270         ED_space_clip_size(sc, &frame_width, &frame_height);
271
272         if (frame_width == 0 || frame_height == 0)
273                 return FALSE;
274
275         if (!selected_boundbox(sc, min, max))
276                 return FALSE;
277
278         /* center view */
279         clip_view_center_to_point(sc, (max[0]+min[0])/(2*frame_width), (max[1]+min[1])/(2*frame_height));
280
281         w = max[0] - min[0];
282         h = max[1] - min[1];
283
284         /* set zoom to see all selection */
285         if (w > 0 && h > 0) {
286                 int width, height;
287                 float zoomx, zoomy, newzoom, aspx, aspy;
288
289                 ED_space_clip_aspect(sc, &aspx, &aspy);
290
291                 width = ar->winrct.xmax - ar->winrct.xmin + 1;
292                 height = ar->winrct.ymax - ar->winrct.ymin + 1;
293
294                 zoomx = (float)width / w / aspx;
295                 zoomy = (float)height / h / aspy;
296
297                 newzoom = 1.0f / power_of_2(1.0f / MIN2(zoomx, zoomy));
298
299                 if (fit || sc->zoom>newzoom)
300                         sc->zoom = newzoom;
301         }
302
303         return TRUE;
304 }
305
306 void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2])
307 {
308         copy_v2_v2(nco, co);
309
310         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
311                 MovieClip *clip = ED_space_clip(sc);
312                 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
313                 int width, height;
314
315                 ED_space_clip_size(sc, &width, &height);
316
317                 nco[0] *= width;
318                 nco[1] *= height * aspy;
319
320                 BKE_tracking_invert_intrinsics(&clip->tracking, nco, nco);
321
322                 nco[0] /= width;
323                 nco[1] /= height * aspy;
324         }
325 }
326
327 void ED_clip_point_stable_pos(bContext *C, float x, float y, float *xr, float *yr)
328 {
329         ARegion *ar = CTX_wm_region(C);
330         SpaceClip *sc = CTX_wm_space_clip(C);
331         int sx, sy, width, height;
332         float zoomx, zoomy, pos[3] = {0.0f, 0.0f, 0.0f}, imat[4][4];
333
334         ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
335         ED_space_clip_size(sc, &width, &height);
336
337         UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
338
339         pos[0] = (x - sx) / zoomx;
340         pos[1] = (y - sy) / zoomy;
341
342         invert_m4_m4(imat, sc->stabmat);
343         mul_v3_m4v3(pos, imat, pos);
344
345         *xr = pos[0] / width;
346         *yr = pos[1] / height;
347
348         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
349                 MovieClip *clip = ED_space_clip(sc);
350                 MovieTracking *tracking = &clip->tracking;
351                 float aspy = 1.0f / tracking->camera.pixel_aspect;
352                 float tmp[2] = {*xr * width, *yr * height * aspy};
353
354                 BKE_tracking_apply_intrinsics(tracking, tmp, tmp);
355
356                 *xr = tmp[0] / width;
357                 *yr = tmp[1] / (height * aspy);
358         }
359 }
360
361 void ED_clip_mouse_pos(bContext *C, wmEvent *event, float co[2])
362 {
363         ED_clip_point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]);
364 }
365
366 int ED_space_clip_show_trackedit(SpaceClip *sc)
367 {
368         if (sc) {
369                 return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION);
370         }
371
372         return FALSE;
373 }