Support metadata display in clip editor
[blender.git] / source / blender / editors / space_clip / clip_draw.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_draw.c
29  *  \ingroup spclip
30  */
31
32 #include "DNA_gpencil_types.h"
33 #include "DNA_movieclip_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "IMB_colormanagement.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_math.h"
44 #include "BLI_string.h"
45 #include "BLI_math_base.h"
46 #include "BLI_rect.h"
47
48 #include "BKE_context.h"
49 #include "BKE_image.h"
50 #include "BKE_movieclip.h"
51 #include "BKE_tracking.h"
52
53 #include "ED_screen.h"
54 #include "ED_clip.h"
55 #include "ED_mask.h"
56 #include "ED_gpencil.h"
57
58 #include "BIF_gl.h"
59 #include "BIF_glutil.h"
60
61 #include "WM_types.h"
62
63 #include "UI_interface.h"
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
66
67
68 #include "BLF_api.h"
69
70 #include "clip_intern.h"    // own include
71
72 /*********************** main area drawing *************************/
73
74 static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width)
75 {
76         int height = (frame == cfra) ? 22 : 10;
77         int x = (frame - sfra) * framelen;
78
79         if (width == 1) {
80                 glBegin(GL_LINES);
81                 glVertex2i(x, 0);
82                 glVertex2i(x, height * UI_DPI_FAC);
83                 glEnd();
84         }
85         else {
86                 glRecti(x, 0, x + width, height * UI_DPI_FAC);
87         }
88 }
89
90 static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
91 {
92         if (track) {
93                 return track->markersnr;
94         }
95         else if (plane_track) {
96                 return plane_track->markersnr;
97         }
98
99         return 0;
100 }
101
102 static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
103                                             int marker_index)
104 {
105         if (track) {
106                 BLI_assert(marker_index < track->markersnr);
107                 return track->markers[marker_index].framenr;
108         }
109         else if (plane_track) {
110                 BLI_assert(marker_index < plane_track->markersnr);
111                 return plane_track->markers[marker_index].framenr;
112         }
113
114         return 0;
115 }
116
117 static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
118                                             int marker_index)
119 {
120         if (track) {
121                 BLI_assert(marker_index < track->markersnr);
122                 return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
123         }
124         else if (plane_track) {
125                 return true;
126         }
127
128         return false;
129 }
130
131 static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
132                                               int marker_index)
133 {
134         if (track) {
135                 BLI_assert(marker_index < track->markersnr);
136                 return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
137         }
138         else if (plane_track) {
139                 BLI_assert(marker_index < plane_track->markersnr);
140                 return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
141         }
142
143         return false;
144 }
145
146 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
147 {
148         float x;
149         int *points, totseg, i, a;
150         float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
151         MovieTracking *tracking = &clip->tracking;
152         MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
153         MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
154         MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
155         MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
156
157         glEnable(GL_BLEND);
158         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
159
160         /* cache background */
161         ED_region_cache_draw_background(ar);
162
163         /* cached segments -- could be usefu lto debug caching strategies */
164         BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
165         ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
166
167         /* track */
168         if (act_track || act_plane_track) {
169                 for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
170                         int framenr;
171                         int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
172
173                         while (a < markersnr) {
174                                 int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
175
176                                 if (marker_framenr >= i)
177                                         break;
178
179                                 if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
180                                         break;
181
182                                 a++;
183                         }
184
185                         a = min_ii(a, markersnr - 1);
186
187                         if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
188                                 framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
189
190                                 if (framenr != i)
191                                         glColor4ub(128, 128, 0, 96);
192                                 else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
193                                         glColor4ub(255, 255, 0, 196);
194                                 else
195                                         glColor4ub(255, 255, 0, 96);
196
197                                 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
198                         }
199                 }
200         }
201
202         /* failed frames */
203         if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
204                 int n = reconstruction->camnr;
205                 MovieReconstructedCamera *cameras = reconstruction->cameras;
206
207                 glColor4ub(255, 0, 0, 96);
208
209                 for (i = sfra, a = 0; i <= efra; i++) {
210                         bool ok = false;
211
212                         while (a < n) {
213                                 if (cameras[a].framenr == i) {
214                                         ok = true;
215                                         break;
216                                 }
217                                 else if (cameras[a].framenr > i) {
218                                         break;
219                                 }
220
221                                 a++;
222                         }
223
224                         if (!ok)
225                                 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
226                 }
227         }
228
229         glDisable(GL_BLEND);
230
231         /* current frame */
232         x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
233
234         UI_ThemeColor(TH_CFRAME);
235         glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
236
237         ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
238
239         /* solver keyframes */
240         glColor4ub(175, 255, 0, 255);
241         draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
242         draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
243
244         /* movie clip animation */
245         if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
246                 ED_mask_draw_frames(sc->mask_info.mask, ar, CFRA, sfra, efra);
247         }
248 }
249
250 static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
251 {
252         MovieClip *clip = ED_space_clip_get_clip(sc);
253         MovieTracking *tracking = &clip->tracking;
254         char str[256] = {0};
255         bool block = false;
256
257         if (tracking->stats) {
258                 BLI_strncpy(str, tracking->stats->message, sizeof(str));
259                 block = true;
260         }
261         else {
262                 if (sc->flag & SC_LOCK_SELECTION)
263                         strcpy(str, "Locked");
264         }
265
266         if (str[0]) {
267                 float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.6f};
268                 ED_region_info_draw(ar, str, block, fill_color);
269         }
270 }
271
272 static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx, float zoomy)
273 {
274         int x, y;
275
276         /* find window pixel coordinates of origin */
277         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
278
279         glColor3f(0.0f, 0.0f, 0.0f);
280         glRectf(x, y, x + zoomx * width, y + zoomy * height);
281 }
282
283 static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
284                                   int width, int height, float zoomx, float zoomy)
285 {
286         MovieClip *clip = ED_space_clip_get_clip(sc);
287         int filter = GL_LINEAR;
288         int x, y;
289         rctf frame;
290
291         /* find window pixel coordinates of origin */
292         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
293
294         /* checkerboard for case alpha */
295         if (ibuf->planes == 32) {
296                 glEnable(GL_BLEND);
297                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
298
299                 fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
300         }
301
302         /* non-scaled proxy shouldn't use filtering */
303         if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
304             ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
305         {
306                 filter = GL_NEAREST;
307         }
308
309         /* set zoom */
310         glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
311
312         glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
313         /* reset zoom */
314         glPixelZoom(1.0f, 1.0f);
315
316         BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
317
318         if (sc->flag & SC_SHOW_METADATA)
319                 ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
320
321         if (ibuf->planes == 32)
322                 glDisable(GL_BLEND);
323 }
324
325 static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
326 {
327         int x, y;
328         MovieClip *clip = ED_space_clip_get_clip(sc);
329
330         /* find window pixel coordinates of origin */
331         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
332
333         /* draw boundary border for frame if stabilization is enabled */
334         if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
335                 glColor3f(0.0f, 0.0f, 0.0f);
336                 glLineStipple(3, 0xaaaa);
337                 glEnable(GL_LINE_STIPPLE);
338                 glEnable(GL_COLOR_LOGIC_OP);
339                 glLogicOp(GL_NOR);
340
341                 glPushMatrix();
342                 glTranslatef(x, y, 0.0f);
343
344                 glScalef(zoomx, zoomy, 1.0f);
345                 glMultMatrixf(sc->stabmat);
346
347                 glBegin(GL_LINE_LOOP);
348                 glVertex2f(0.0f, 0.0f);
349                 glVertex2f(width, 0.0f);
350                 glVertex2f(width, height);
351                 glVertex2f(0.0f, height);
352                 glEnd();
353
354                 glPopMatrix();
355
356                 glDisable(GL_COLOR_LOGIC_OP);
357                 glDisable(GL_LINE_STIPPLE);
358         }
359 }
360
361 static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
362 {
363         int count = sc->path_length;
364         int i, a, b, curindex = -1;
365         float path[102][2];
366         int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
367         MovieTrackingMarker *marker;
368
369         if (count == 0)
370                 return;
371
372         start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);
373
374         marker = BKE_tracking_marker_get(track, framenr);
375         if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
376                 return;
377
378         a = count;
379         i = framenr - 1;
380         while (i >= framenr - count) {
381                 marker = BKE_tracking_marker_get(track, i);
382
383                 if (!marker || marker->flag & MARKER_DISABLED)
384                         break;
385
386                 if (marker->framenr == i) {
387                         add_v2_v2v2(path[--a], marker->pos, track->offset);
388                         ED_clip_point_undistorted_pos(sc, path[a], path[a]);
389
390                         if (marker->framenr == start_frame)
391                                 curindex = a;
392                 }
393                 else {
394                         break;
395                 }
396
397                 i--;
398         }
399
400         b = count;
401         i = framenr;
402         while (i <= framenr + count) {
403                 marker = BKE_tracking_marker_get(track, i);
404
405                 if (!marker || marker->flag & MARKER_DISABLED)
406                         break;
407
408                 if (marker->framenr == i) {
409                         if (marker->framenr == start_frame)
410                                 curindex = b;
411
412                         add_v2_v2v2(path[b++], marker->pos, track->offset);
413                         ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
414                 }
415                 else
416                         break;
417
418                 i++;
419         }
420
421         if (!tiny) {
422                 UI_ThemeColor(TH_MARKER_OUTLINE);
423
424                 if (TRACK_VIEW_SELECTED(sc, track)) {
425                         glPointSize(5.0f);
426                         glBegin(GL_POINTS);
427                         for (i = a; i < b; i++) {
428                                 if (i != curindex)
429                                         glVertex2f(path[i][0], path[i][1]);
430                         }
431                         glEnd();
432                 }
433
434                 glLineWidth(3.0f);
435                 glBegin(GL_LINE_STRIP);
436                 for (i = a; i < b; i++)
437                         glVertex2f(path[i][0], path[i][1]);
438                 glEnd();
439                 glLineWidth(1.0f);
440         }
441
442         UI_ThemeColor(TH_PATH_BEFORE);
443
444         if (TRACK_VIEW_SELECTED(sc, track)) {
445                 glPointSize(3.0f);
446                 glBegin(GL_POINTS);
447                 for (i = a; i < b; i++) {
448                         if (i == count + 1)
449                                 UI_ThemeColor(TH_PATH_AFTER);
450
451                         if (i != curindex)
452                                 glVertex2f(path[i][0], path[i][1]);
453                 }
454                 glEnd();
455         }
456
457         UI_ThemeColor(TH_PATH_BEFORE);
458
459         glBegin(GL_LINE_STRIP);
460         for (i = a; i < b; i++) {
461                 if (i == count + 1)
462                         UI_ThemeColor(TH_PATH_AFTER);
463
464                 glVertex2f(path[i][0], path[i][1]);
465         }
466         glEnd();
467         glPointSize(1.0f);
468 }
469
470 static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
471                                 const float marker_pos[2], int width, int height)
472 {
473         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
474         bool show_search = false;
475         float px[2];
476
477         UI_ThemeColor(TH_MARKER_OUTLINE);
478
479         px[0] = 1.0f / width / sc->zoom;
480         px[1] = 1.0f / height / sc->zoom;
481
482         if ((marker->flag & MARKER_DISABLED) == 0) {
483                 float pos[2];
484                 float p[2];
485
486                 add_v2_v2v2(pos, marker->pos, track->offset);
487
488                 ED_clip_point_undistorted_pos(sc, pos, pos);
489
490                 sub_v2_v2v2(p, pos, marker_pos);
491
492                 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
493                                         marker->pattern_corners[2], marker->pattern_corners[3]))
494                 {
495                         if (tiny) glPointSize(3.0f);
496                         else glPointSize(4.0f);
497                         glBegin(GL_POINTS);
498                         glVertex2f(pos[0], pos[1]);
499                         glEnd();
500                         glPointSize(1.0f);
501                 }
502                 else {
503                         if (!tiny) glLineWidth(3.0f);
504                         glBegin(GL_LINES);
505                         glVertex2f(pos[0] + px[0] * 2, pos[1]);
506                         glVertex2f(pos[0] + px[0] * 8, pos[1]);
507
508                         glVertex2f(pos[0] - px[0] * 2, pos[1]);
509                         glVertex2f(pos[0] - px[0] * 8, pos[1]);
510
511                         glVertex2f(pos[0], pos[1] - px[1] * 2);
512                         glVertex2f(pos[0], pos[1] - px[1] * 8);
513
514                         glVertex2f(pos[0], pos[1] + px[1] * 2);
515                         glVertex2f(pos[0], pos[1] + px[1] * 8);
516                         glEnd();
517                         if (!tiny) glLineWidth(1.0f);
518                 }
519         }
520
521         /* pattern and search outline */
522         glPushMatrix();
523         glTranslatef(marker_pos[0], marker_pos[1], 0);
524
525         if (!tiny)
526                 glLineWidth(3.0f);
527
528         if (sc->flag & SC_SHOW_MARKER_PATTERN) {
529                 glBegin(GL_LINE_LOOP);
530                 glVertex2fv(marker->pattern_corners[0]);
531                 glVertex2fv(marker->pattern_corners[1]);
532                 glVertex2fv(marker->pattern_corners[2]);
533                 glVertex2fv(marker->pattern_corners[3]);
534                 glEnd();
535         }
536
537         show_search = (TRACK_VIEW_SELECTED(sc, track) &&
538                        ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
539         if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
540                 glBegin(GL_LINE_LOOP);
541                 glVertex2f(marker->search_min[0], marker->search_min[1]);
542                 glVertex2f(marker->search_max[0], marker->search_min[1]);
543                 glVertex2f(marker->search_max[0], marker->search_max[1]);
544                 glVertex2f(marker->search_min[0], marker->search_max[1]);
545                 glEnd();
546         }
547         glPopMatrix();
548
549         if (!tiny)
550                 glLineWidth(1.0f);
551 }
552
553 static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
554 {
555         if (track->flag & TRACK_CUSTOMCOLOR) {
556                 if (act)
557                         UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
558                 else
559                         copy_v3_v3(scol, track->color);
560
561                 mul_v3_v3fl(col, track->color, 0.5f);
562         }
563         else {
564                 UI_GetThemeColor3fv(TH_MARKER, col);
565
566                 if (act)
567                         UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
568                 else
569                         UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
570         }
571 }
572
573 static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
574                               const float marker_pos[2], int width, int height, int act, int sel)
575 {
576         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
577         bool show_search = false;
578         float col[3], scol[3], px[2];
579
580         track_colors(track, act, col, scol);
581
582         px[0] = 1.0f / width / sc->zoom;
583         px[1] = 1.0f / height / sc->zoom;
584
585         /* marker position and offset position */
586         if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
587                 float pos[2], p[2];
588
589                 if (track->flag & TRACK_LOCKED) {
590                         if (act)
591                                 UI_ThemeColor(TH_ACT_MARKER);
592                         else if (track->flag & SELECT)
593                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
594                         else
595                                 UI_ThemeColor(TH_LOCK_MARKER);
596                 }
597                 else {
598                         if (track->flag & SELECT)
599                                 glColor3fv(scol);
600                         else
601                                 glColor3fv(col);
602                 }
603
604                 add_v2_v2v2(pos, marker->pos, track->offset);
605                 ED_clip_point_undistorted_pos(sc, pos, pos);
606
607                 sub_v2_v2v2(p, pos, marker_pos);
608
609                 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
610                                         marker->pattern_corners[2], marker->pattern_corners[3]))
611                 {
612                         if (!tiny)
613                                 glPointSize(2.0f);
614
615                         glBegin(GL_POINTS);
616                         glVertex2f(pos[0], pos[1]);
617                         glEnd();
618
619                         if (!tiny)
620                                 glPointSize(1.0f);
621                 }
622                 else {
623                         glBegin(GL_LINES);
624                         glVertex2f(pos[0] + px[0] * 3, pos[1]);
625                         glVertex2f(pos[0] + px[0] * 7, pos[1]);
626
627                         glVertex2f(pos[0] - px[0] * 3, pos[1]);
628                         glVertex2f(pos[0] - px[0] * 7, pos[1]);
629
630                         glVertex2f(pos[0], pos[1] - px[1] * 3);
631                         glVertex2f(pos[0], pos[1] - px[1] * 7);
632
633                         glVertex2f(pos[0], pos[1] + px[1] * 3);
634                         glVertex2f(pos[0], pos[1] + px[1] * 7);
635                         glEnd();
636
637                         glColor3f(0.0f, 0.0f, 0.0f);
638                         glLineStipple(3, 0xaaaa);
639                         glEnable(GL_LINE_STIPPLE);
640                         glEnable(GL_COLOR_LOGIC_OP);
641                         glLogicOp(GL_NOR);
642
643                         glBegin(GL_LINES);
644                         glVertex2fv(pos);
645                         glVertex2fv(marker_pos);
646                         glEnd();
647
648                         glDisable(GL_COLOR_LOGIC_OP);
649                         glDisable(GL_LINE_STIPPLE);
650                 }
651         }
652
653         /* pattern */
654         glPushMatrix();
655         glTranslatef(marker_pos[0], marker_pos[1], 0);
656
657         if (tiny) {
658                 glLineStipple(3, 0xaaaa);
659                 glEnable(GL_LINE_STIPPLE);
660         }
661
662         if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
663                 if (track->flag & TRACK_LOCKED) {
664                         if (act)
665                                 UI_ThemeColor(TH_ACT_MARKER);
666                         else if (track->pat_flag & SELECT)
667                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
668                         else UI_ThemeColor(TH_LOCK_MARKER);
669                 }
670                 else if (marker->flag & MARKER_DISABLED) {
671                         if (act)
672                                 UI_ThemeColor(TH_ACT_MARKER);
673                         else if (track->pat_flag & SELECT)
674                                 UI_ThemeColorShade(TH_DIS_MARKER, 128);
675                         else UI_ThemeColor(TH_DIS_MARKER);
676                 }
677                 else {
678                         if (track->pat_flag & SELECT)
679                                 glColor3fv(scol);
680                         else glColor3fv(col);
681                 }
682
683                 glBegin(GL_LINE_LOOP);
684                 glVertex2fv(marker->pattern_corners[0]);
685                 glVertex2fv(marker->pattern_corners[1]);
686                 glVertex2fv(marker->pattern_corners[2]);
687                 glVertex2fv(marker->pattern_corners[3]);
688                 glEnd();
689         }
690
691         /* search */
692         show_search = (TRACK_VIEW_SELECTED(sc, track) &&
693                        ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
694         if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
695                 if (track->flag & TRACK_LOCKED) {
696                         if (act)
697                                 UI_ThemeColor(TH_ACT_MARKER);
698                         else if (track->search_flag & SELECT)
699                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
700                         else UI_ThemeColor(TH_LOCK_MARKER);
701                 }
702                 else if (marker->flag & MARKER_DISABLED) {
703                         if (act)
704                                 UI_ThemeColor(TH_ACT_MARKER);
705                         else if (track->search_flag & SELECT)
706                                 UI_ThemeColorShade(TH_DIS_MARKER, 128);
707                         else UI_ThemeColor(TH_DIS_MARKER);
708                 }
709                 else {
710                         if (track->search_flag & SELECT)
711                                 glColor3fv(scol);
712                         else
713                                 glColor3fv(col);
714                 }
715
716                 glBegin(GL_LINE_LOOP);
717                 glVertex2f(marker->search_min[0], marker->search_min[1]);
718                 glVertex2f(marker->search_max[0], marker->search_min[1]);
719                 glVertex2f(marker->search_max[0], marker->search_max[1]);
720                 glVertex2f(marker->search_min[0], marker->search_max[1]);
721                 glEnd();
722         }
723
724         if (tiny)
725                 glDisable(GL_LINE_STIPPLE);
726
727         glPopMatrix();
728 }
729
730 static float get_shortest_pattern_side(MovieTrackingMarker *marker)
731 {
732         int i, next;
733         float len_sq = FLT_MAX;
734
735         for (i = 0; i < 4; i++) {
736                 float cur_len;
737
738                 next = (i + 1) % 4;
739
740                 cur_len = len_squared_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
741
742                 len_sq = min_ff(cur_len, len_sq);
743         }
744
745         return sqrtf(len_sq);
746 }
747
748 static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
749 {
750         float tdx, tdy;
751
752         tdx = dx;
753         tdy = dy;
754
755         if (outline) {
756                 tdx += px[0];
757                 tdy += px[1];
758         }
759
760         glBegin(GL_QUADS);
761         glVertex3f(x - tdx, y + tdy, 0.0f);
762         glVertex3f(x + tdx, y + tdy, 0.0f);
763         glVertex3f(x + tdx, y - tdy, 0.0f);
764         glVertex3f(x - tdx, y - tdy, 0.0f);
765         glEnd();
766 }
767
768 static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
769 {
770         float tdx, tdy;
771
772         tdx = dx * 2.0f;
773         tdy = dy * 2.0f;
774
775         if (outline) {
776                 tdx += px[0];
777                 tdy += px[1];
778         }
779
780         glBegin(GL_TRIANGLES);
781         glVertex3f(x,       y,       0.0f);
782         glVertex3f(x - tdx, y,       0.0f);
783         glVertex3f(x,       y + tdy, 0.0f);
784         glEnd();
785 }
786
787 static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
788                                     const float marker_pos[2], int outline, int sel, int act, int width, int height)
789 {
790         float dx, dy, patdx, patdy, searchdx, searchdy;
791         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
792         float col[3], scol[3], px[2], side;
793
794         if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
795                 return;
796
797         if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
798                 return;
799
800         track_colors(track, act, col, scol);
801
802         if (outline) {
803                 glLineWidth(3.0f);
804                 UI_ThemeColor(TH_MARKER_OUTLINE);
805         }
806
807         glPushMatrix();
808         glTranslatef(marker_pos[0], marker_pos[1], 0);
809
810         dx = 6.0f / width / sc->zoom;
811         dy = 6.0f / height / sc->zoom;
812
813         side = get_shortest_pattern_side(marker);
814         patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
815         patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;
816
817         searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
818         searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;
819
820         px[0] = 1.0f / sc->zoom / width / sc->scale;
821         px[1] = 1.0f / sc->zoom / height / sc->scale;
822
823         if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
824                 if (!outline) {
825                         if (track->search_flag & SELECT)
826                                 glColor3fv(scol);
827                         else
828                                 glColor3fv(col);
829                 }
830
831                 /* search offset square */
832                 draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);
833
834                 /* search re-sizing triangle */
835                 draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
836         }
837
838         if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
839                 int i;
840                 float pat_min[2], pat_max[2];
841 /*              float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
842                 float tilt_ctrl[2];
843
844                 if (!outline) {
845                         if (track->pat_flag & SELECT)
846                                 glColor3fv(scol);
847                         else
848                                 glColor3fv(col);
849                 }
850
851                 /* pattern's corners sliding squares */
852                 for (i = 0; i < 4; i++) {
853                         draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
854                                                  patdx / 1.5f, patdy / 1.5f, outline, px);
855                 }
856
857                 /* ** sliders to control overall pattern  ** */
858                 add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);
859
860                 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
861
862                 glEnable(GL_LINE_STIPPLE);
863                 glLineStipple(3, 0xaaaa);
864
865 #if 0
866                 /* TODO: disable for now, needs better approach visualizing this */
867
868                 glBegin(GL_LINE_LOOP);
869                 glVertex2f(pat_min[0] - dx, pat_min[1] - dy);
870                 glVertex2f(pat_max[0] + dx, pat_min[1] - dy);
871                 glVertex2f(pat_max[0] + dx, pat_max[1] + dy);
872                 glVertex2f(pat_min[0] - dx, pat_max[1] + dy);
873                 glEnd();
874
875                 /* marker's offset slider */
876                 draw_marker_slide_square(pat_min[0] - dx, pat_max[1] + dy, patdx, patdy, outline, px);
877
878                 /* pattern re-sizing triangle */
879                 draw_marker_slide_triangle(pat_max[0] + dx, pat_min[1] - dy, patdx, patdy, outline, px);
880 #endif
881
882                 glBegin(GL_LINES);
883                 glVertex2f(0.0f, 0.0f);
884                 glVertex2fv(tilt_ctrl);
885                 glEnd();
886
887                 glDisable(GL_LINE_STIPPLE);
888
889
890                 /* slider to control pattern tilt */
891                 draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
892         }
893
894         glPopMatrix();
895
896         if (outline)
897                 glLineWidth(1.0f);
898 }
899
900 static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
901                               const float marker_pos[2], int act, int width, int height, float zoomx, float zoomy)
902 {
903         char str[128] = {0}, state[64] = {0};
904         float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
905         uiStyle *style = U.uistyles.first;
906         int fontid = style->widget.uifont_id;
907
908         if (!TRACK_VIEW_SELECTED(sc, track))
909                 return;
910
911         BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
912         fontsize = BLF_height_max(fontid);
913
914         if (marker->flag & MARKER_DISABLED) {
915                 if (act)
916                         UI_ThemeColor(TH_ACT_MARKER);
917                 else
918                         UI_ThemeColorShade(TH_DIS_MARKER, 128);
919         }
920         else {
921                 if (act)
922                         UI_ThemeColor(TH_ACT_MARKER);
923                 else
924                         UI_ThemeColor(TH_SEL_MARKER);
925         }
926
927         if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
928             ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0))
929         {
930                 dx = marker->search_min[0];
931                 dy = marker->search_min[1];
932         }
933         else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
934                 float pat_min[2], pat_max[2];
935
936                 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
937                 dx = pat_min[0];
938                 dy = pat_min[1];
939         }
940
941         pos[0] = (marker_pos[0] + dx) * width;
942         pos[1] = (marker_pos[1] + dy) * height;
943         pos[2] = 0.0f;
944
945         mul_m4_v3(sc->stabmat, pos);
946
947         pos[0] = pos[0] * zoomx;
948         pos[1] = pos[1] * zoomy - fontsize;
949
950         if (marker->flag & MARKER_DISABLED)
951                 strcpy(state, "disabled");
952         else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
953                 strcpy(state, "estimated");
954         else if (marker->flag & MARKER_TRACKED)
955                 strcpy(state, "tracked");
956         else
957                 strcpy(state, "keyframed");
958
959         if (state[0])
960                 BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
961         else
962                 BLI_strncpy(str, track->name, sizeof(str));
963
964         BLF_position(fontid, pos[0], pos[1], 0.0f);
965         BLF_draw(fontid, str, sizeof(str));
966         pos[1] -= fontsize;
967
968         if (track->flag & TRACK_HAS_BUNDLE) {
969                 BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
970                 BLF_position(fontid, pos[0], pos[1], 0.0f);
971                 BLF_draw(fontid, str, sizeof(str));
972                 pos[1] -= fontsize;
973         }
974
975         if (track->flag & TRACK_LOCKED) {
976                 BLF_position(fontid, pos[0], pos[1], 0.0f);
977                 BLF_draw(fontid, "locked", 6);
978         }
979 }
980
981 static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
982 {
983         UI_GetThemeColor3fv(TH_MARKER, color);
984
985         if (is_active)
986                 UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
987         else
988                 UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
989 }
990
991 static void getArrowEndPoint(const int width, const int height, const float zoom,
992                              const float start_corner[2], const float end_corner[2],
993                              float end_point[2])
994 {
995         float direction[2];
996         float max_length;
997
998         sub_v2_v2v2(direction, end_corner, start_corner);
999
1000         direction[0] *= width;
1001         direction[1] *= height;
1002         max_length = normalize_v2(direction);
1003         mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
1004         direction[0] /= width;
1005         direction[1] /= height;
1006
1007         add_v2_v2v2(end_point, start_corner, direction);
1008 }
1009
1010 static void homogeneous_2d_to_gl_matrix(/*const*/ float matrix[3][3],
1011                                         float gl_matrix[4][4])
1012 {
1013         gl_matrix[0][0] = matrix[0][0];
1014         gl_matrix[0][1] = matrix[0][1];
1015         gl_matrix[0][2] = 0.0f;
1016         gl_matrix[0][3] = matrix[0][2];
1017
1018         gl_matrix[1][0] = matrix[1][0];
1019         gl_matrix[1][1] = matrix[1][1];
1020         gl_matrix[1][2] = 0.0f;
1021         gl_matrix[1][3] = matrix[1][2];
1022
1023         gl_matrix[2][0] = 0.0f;
1024         gl_matrix[2][1] = 0.0f;
1025         gl_matrix[2][2] = 1.0f;
1026         gl_matrix[2][3] = 0.0f;
1027
1028         gl_matrix[3][0] = matrix[2][0];
1029         gl_matrix[3][1] = matrix[2][1];
1030         gl_matrix[3][2] = 0.0f;
1031         gl_matrix[3][3] = matrix[2][2];
1032 }
1033
1034 static void draw_plane_marker_image(Scene *scene,
1035                                     MovieTrackingPlaneTrack *plane_track,
1036                                     MovieTrackingPlaneMarker *plane_marker)
1037 {
1038         Image *image = plane_track->image;
1039         ImBuf *ibuf;
1040         void *lock;
1041
1042         if (image == NULL) {
1043                 return;
1044         }
1045
1046         ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
1047
1048         if (ibuf) {
1049                 unsigned char *display_buffer;
1050                 void *cache_handle;
1051
1052                 if (image->flag & IMA_VIEW_AS_RENDER) {
1053                         display_buffer = IMB_display_buffer_acquire(ibuf,
1054                                                                     &scene->view_settings,
1055                                                                     &scene->display_settings,
1056                                                                     &cache_handle);
1057                 }
1058                 else {
1059                         display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
1060                                                                     &scene->display_settings,
1061                                                                     &cache_handle);
1062                 }
1063
1064                 if (display_buffer) {
1065                         GLuint texid, last_texid;
1066                         float frame_corners[4][2] = {{0.0f, 0.0f},
1067                                                      {1.0f, 0.0f},
1068                                                      {1.0f, 1.0f},
1069                                                      {0.0f, 1.0f}};
1070                         float perspective_matrix[3][3];
1071                         float gl_matrix[4][4];
1072                         bool transparent = false;
1073                         BKE_tracking_homography_between_two_quads(frame_corners,
1074                                                                   plane_marker->corners,
1075                                                                   perspective_matrix);
1076
1077                         homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
1078
1079                         if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
1080                                 transparent = true;
1081                                 glEnable(GL_BLEND);
1082                                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
1083                         }
1084
1085                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1086                         glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
1087
1088                         last_texid = glaGetOneInteger(GL_TEXTURE_2D);
1089                         glEnable(GL_TEXTURE_2D);
1090                         glGenTextures(1, (GLuint *)&texid);
1091
1092                         glBindTexture(GL_TEXTURE_2D, texid);
1093
1094                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1095                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1096
1097                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
1098                                      GL_UNSIGNED_BYTE, display_buffer);
1099
1100                         glPushMatrix();
1101                         glMultMatrixf(gl_matrix);
1102
1103                         glBegin(GL_QUADS);
1104                         glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
1105                         glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
1106                         glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
1107                         glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
1108                         glEnd();
1109
1110                         glPopMatrix();
1111
1112                         glBindTexture(GL_TEXTURE_2D, last_texid);
1113                         glDisable(GL_TEXTURE_2D);
1114
1115                         if (transparent) {
1116                                 glDisable(GL_BLEND);
1117                         }
1118                 }
1119
1120                 IMB_display_buffer_release(cache_handle);
1121         }
1122
1123         BKE_image_release_ibuf(image, ibuf, lock);
1124 }
1125
1126 static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1127                                  MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
1128                                  bool draw_outline, int width, int height)
1129 {
1130         bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
1131         bool is_selected_track = (plane_track->flag & SELECT) != 0;
1132         const bool has_image = plane_track->image != NULL &&
1133                                BKE_image_has_ibuf(plane_track->image, NULL);
1134         const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
1135         float px[2];
1136
1137         if (draw_outline) {
1138                 UI_ThemeColor(TH_MARKER_OUTLINE);
1139         }
1140         else {
1141                 float color[3], selected_color[3];
1142                 plane_track_colors(is_active_track, color, selected_color);
1143                 if (is_selected_track) {
1144                         glColor3fv(selected_color);
1145                 }
1146                 else {
1147                         glColor3fv(color);
1148                 }
1149         }
1150
1151         px[0] = 1.0f / width / sc->zoom;
1152         px[1] = 1.0f / height / sc->zoom;
1153
1154         /* Draw image */
1155         if (draw_outline == false) {
1156                 draw_plane_marker_image(scene, plane_track, plane_marker);
1157         }
1158
1159         if (draw_outline) {
1160                 if (!tiny) {
1161                         glLineWidth(3.0f);
1162                 }
1163         }
1164         else if (tiny) {
1165                 glLineStipple(3, 0xaaaa);
1166                 glEnable(GL_LINE_STIPPLE);
1167         }
1168
1169         if (draw_plane_quad) {
1170                 /* Draw rectangle itself. */
1171                 glBegin(GL_LINE_LOOP);
1172                 glVertex2fv(plane_marker->corners[0]);
1173                 glVertex2fv(plane_marker->corners[1]);
1174                 glVertex2fv(plane_marker->corners[2]);
1175                 glVertex2fv(plane_marker->corners[3]);
1176                 glEnd();
1177
1178                 /* Draw axis. */
1179                 if (!draw_outline) {
1180                         float end_point[2];
1181                         glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
1182
1183                         getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
1184                         glColor3f(1.0, 0.0, 0.0f);
1185                         glBegin(GL_LINES);
1186                         glVertex2fv(plane_marker->corners[0]);
1187                         glVertex2fv(end_point);
1188                         glEnd();
1189
1190                         getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
1191                         glColor3f(0.0, 1.0, 0.0f);
1192                         glBegin(GL_LINES);
1193                         glVertex2fv(plane_marker->corners[0]);
1194                         glVertex2fv(end_point);
1195                         glEnd();
1196
1197                         glPopAttrib();
1198                 }
1199         }
1200
1201         /* Draw sliders. */
1202         if (is_selected_track) {
1203                 int i;
1204                 for (i = 0; i < 4; i++) {
1205                         draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
1206                                                  3.0f * px[0], 3.0f * px[1], draw_outline, px);
1207                 }
1208         }
1209
1210         if (draw_outline) {
1211                 if (!tiny) {
1212                         glLineWidth(1.0f);
1213                 }
1214         }
1215         else if (tiny) {
1216                 glDisable(GL_LINE_STIPPLE);
1217         }
1218 }
1219
1220 static void draw_plane_marker_outline(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1221                                       MovieTrackingPlaneMarker *plane_marker, int width, int height)
1222 {
1223         draw_plane_marker_ex(sc, scene, plane_track, plane_marker, false, true, width, height);
1224 }
1225
1226 static void draw_plane_marker(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1227                               MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
1228                               int width, int height)
1229 {
1230         draw_plane_marker_ex(sc, scene, plane_track, plane_marker, is_active_track, false, width, height);
1231 }
1232
1233 static void draw_plane_track(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1234                              int framenr, bool is_active_track, int width, int height)
1235 {
1236         MovieTrackingPlaneMarker *plane_marker;
1237
1238         plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1239
1240         draw_plane_marker_outline(sc, scene, plane_track, plane_marker, width, height);
1241         draw_plane_marker(sc, scene, plane_track, plane_marker, is_active_track, width, height);
1242 }
1243
1244 /* Draw all kind of tracks. */
1245 static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
1246                                  int width, int height, float zoomx, float zoomy)
1247 {
1248         float x, y;
1249         MovieTracking *tracking = &clip->tracking;
1250         ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
1251         ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
1252         MovieTrackingTrack *track, *act_track;
1253         MovieTrackingPlaneTrack *plane_track, *active_plane_track;
1254         MovieTrackingMarker *marker;
1255         int framenr = ED_space_clip_get_clip_frame_number(sc);
1256         int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1257         float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];
1258
1259         /* ** find window pixel coordinates of origin ** */
1260
1261         /* UI_view2d_view_to_region_no_clip return integer values, this could
1262          * lead to 1px flickering when view is locked to selection during playbeck.
1263          * to avoid this flickering, calculate base point in the same way as it happens
1264          * in UI_view2d_view_to_region_no_clip, but do it in floats here */
1265
1266         UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
1267
1268         glPushMatrix();
1269         glTranslatef(x, y, 0);
1270
1271         glPushMatrix();
1272         glScalef(zoomx, zoomy, 0);
1273         glMultMatrixf(sc->stabmat);
1274         glScalef(width, height, 0);
1275
1276         act_track = BKE_tracking_track_get_active(tracking);
1277
1278         /* Draw plane tracks */
1279         active_plane_track = BKE_tracking_plane_track_get_active(tracking);
1280         for (plane_track = plane_tracks_base->first;
1281              plane_track;
1282              plane_track = plane_track->next)
1283         {
1284                 if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
1285                         draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
1286                 }
1287         }
1288
1289         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1290                 int count = 0;
1291
1292                 /* count */
1293                 track = tracksbase->first;
1294                 while (track) {
1295                         if ((track->flag & TRACK_HIDDEN) == 0) {
1296                                 marker = BKE_tracking_marker_get(track, framenr);
1297
1298                                 if (MARKER_VISIBLE(sc, track, marker))
1299                                         count++;
1300                         }
1301
1302                         track = track->next;
1303                 }
1304
1305                 /* undistort */
1306                 if (count) {
1307                         marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");
1308
1309                         track = tracksbase->first;
1310                         fp = marker_pos;
1311                         while (track) {
1312                                 if ((track->flag & TRACK_HIDDEN) == 0) {
1313                                         marker = BKE_tracking_marker_get(track, framenr);
1314
1315                                         if (MARKER_VISIBLE(sc, track, marker)) {
1316                                                 ED_clip_point_undistorted_pos(sc, marker->pos, fp);
1317
1318                                                 if (track == act_track)
1319                                                         active_pos = fp;
1320
1321                                                 fp += 2;
1322                                         }
1323                                 }
1324
1325                                 track = track->next;
1326                         }
1327                 }
1328         }
1329
1330         if (sc->flag & SC_SHOW_TRACK_PATH) {
1331                 track = tracksbase->first;
1332                 while (track) {
1333                         if ((track->flag & TRACK_HIDDEN) == 0)
1334                                 draw_track_path(sc, clip, track);
1335
1336                         track = track->next;
1337                 }
1338         }
1339
1340         /* markers outline and non-selected areas */
1341         track = tracksbase->first;
1342         fp = marker_pos;
1343         while (track) {
1344                 if ((track->flag & TRACK_HIDDEN) == 0) {
1345                         marker = BKE_tracking_marker_get(track, framenr);
1346
1347                         if (MARKER_VISIBLE(sc, track, marker)) {
1348                                 copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1349
1350                                 draw_marker_outline(sc, track, marker, cur_pos, width, height);
1351                                 draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
1352                                 draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
1353                                 draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);
1354
1355                                 if (fp)
1356                                         fp += 2;
1357                         }
1358                 }
1359
1360                 track = track->next;
1361         }
1362
1363         /* selected areas only, so selection wouldn't be overlapped by
1364          * non-selected areas */
1365         track = tracksbase->first;
1366         fp = marker_pos;
1367         while (track) {
1368                 if ((track->flag & TRACK_HIDDEN) == 0) {
1369                         int act = track == act_track;
1370                         marker = BKE_tracking_marker_get(track, framenr);
1371
1372                         if (MARKER_VISIBLE(sc, track, marker)) {
1373                                 if (!act) {
1374                                         copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1375
1376                                         draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
1377                                         draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
1378                                 }
1379
1380                                 if (fp)
1381                                         fp += 2;
1382                         }
1383                 }
1384
1385                 track = track->next;
1386         }
1387
1388         /* active marker would be displayed on top of everything else */
1389         if (act_track) {
1390                 if ((act_track->flag & TRACK_HIDDEN) == 0) {
1391                         marker = BKE_tracking_marker_get(act_track, framenr);
1392
1393                         if (MARKER_VISIBLE(sc, act_track, marker)) {
1394                                 copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
1395
1396                                 draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
1397                                 draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
1398                         }
1399                 }
1400         }
1401
1402         if (sc->flag & SC_SHOW_BUNDLES) {
1403                 MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
1404                 float pos[4], vec[4], mat[4][4], aspy;
1405
1406                 glEnable(GL_POINT_SMOOTH);
1407                 glPointSize(3.0f);
1408
1409                 aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1410                 BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);
1411
1412                 track = tracksbase->first;
1413                 while (track) {
1414                         if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
1415                                 marker = BKE_tracking_marker_get(track, framenr);
1416
1417                                 if (MARKER_VISIBLE(sc, track, marker)) {
1418                                         float npos[2];
1419                                         copy_v3_v3(vec, track->bundle_pos);
1420                                         vec[3] = 1;
1421
1422                                         mul_v4_m4v4(pos, mat, vec);
1423
1424                                         pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
1425                                         pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
1426
1427                                         BKE_tracking_distort_v2(tracking, pos, npos);
1428
1429                                         if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
1430                                                 vec[0] = (marker->pos[0] + track->offset[0]) * width;
1431                                                 vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;
1432
1433                                                 sub_v2_v2(vec, npos);
1434
1435                                                 if (len_squared_v2(vec) < (3.0f * 3.0f))
1436                                                         glColor3f(0.0f, 1.0f, 0.0f);
1437                                                 else
1438                                                         glColor3f(1.0f, 0.0f, 0.0f);
1439
1440                                                 glBegin(GL_POINTS);
1441                                                 if (undistort)
1442                                                         glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
1443                                                 else
1444                                                         glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
1445                                                 glEnd();
1446                                         }
1447                                 }
1448                         }
1449
1450                         track = track->next;
1451                 }
1452
1453                 glPointSize(1.0f);
1454                 glDisable(GL_POINT_SMOOTH);
1455         }
1456
1457         glPopMatrix();
1458
1459         if (sc->flag & SC_SHOW_NAMES) {
1460                 /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
1461                 track = tracksbase->first;
1462                 fp = marker_pos;
1463                 while (track) {
1464                         if ((track->flag & TRACK_HIDDEN) == 0) {
1465                                 marker = BKE_tracking_marker_get(track, framenr);
1466
1467                                 if (MARKER_VISIBLE(sc, track, marker)) {
1468                                         int act = track == act_track;
1469
1470                                         copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1471
1472                                         draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);
1473
1474                                         if (fp)
1475                                                 fp += 2;
1476                                 }
1477                         }
1478
1479                         track = track->next;
1480                 }
1481         }
1482
1483         glPopMatrix();
1484
1485         if (marker_pos)
1486                 MEM_freeN(marker_pos);
1487 }
1488
1489 static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
1490                             int width, int height, float zoomx, float zoomy)
1491 {
1492         float x, y;
1493         const int n = 10;
1494         int i, j, a;
1495         float pos[2], tpos[2], grid[11][11][2];
1496         MovieTracking *tracking = &clip->tracking;
1497         bGPdata *gpd = NULL;
1498         float aspy = 1.0f / tracking->camera.pixel_aspect;
1499         float dx = (float)width / n, dy = (float)height / n * aspy;
1500         float offsx = 0.0f, offsy = 0.0f;
1501
1502         if (!tracking->camera.focal)
1503                 return;
1504
1505         if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
1506                 return;
1507
1508         UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
1509
1510         glPushMatrix();
1511         glTranslatef(x, y, 0);
1512         glScalef(zoomx, zoomy, 0);
1513         glMultMatrixf(sc->stabmat);
1514         glScalef(width, height, 0);
1515
1516         /* grid */
1517         if (sc->flag & SC_SHOW_GRID) {
1518                 float val[4][2], idx[4][2];
1519                 float min[2], max[2];
1520
1521                 for (a = 0; a < 4; a++) {
1522                         if (a < 2)
1523                                 val[a][a % 2] = FLT_MAX;
1524                         else
1525                                 val[a][a % 2] = -FLT_MAX;
1526                 }
1527
1528                 zero_v2(pos);
1529                 for (i = 0; i <= n; i++) {
1530                         for (j = 0; j <= n; j++) {
1531                                 if (i == 0 || j == 0 || i == n || j == n) {
1532                                         BKE_tracking_distort_v2(tracking, pos, tpos);
1533
1534                                         for (a = 0; a < 4; a++) {
1535                                                 int ok;
1536
1537                                                 if (a < 2)
1538                                                         ok = tpos[a % 2] < val[a][a % 2];
1539                                                 else
1540                                                         ok = tpos[a % 2] > val[a][a % 2];
1541
1542                                                 if (ok) {
1543                                                         copy_v2_v2(val[a], tpos);
1544                                                         idx[a][0] = j;
1545                                                         idx[a][1] = i;
1546                                                 }
1547                                         }
1548                                 }
1549
1550                                 pos[0] += dx;
1551                         }
1552
1553                         pos[0] = 0.0f;
1554                         pos[1] += dy;
1555                 }
1556
1557                 INIT_MINMAX2(min, max);
1558
1559                 for (a = 0; a < 4; a++) {
1560                         pos[0] = idx[a][0] * dx;
1561                         pos[1] = idx[a][1] * dy;
1562
1563                         BKE_tracking_undistort_v2(tracking, pos, tpos);
1564
1565                         minmax_v2v2_v2(min, max, tpos);
1566                 }
1567
1568                 copy_v2_v2(pos, min);
1569                 dx = (max[0] - min[0]) / n;
1570                 dy = (max[1] - min[1]) / n;
1571
1572                 for (i = 0; i <= n; i++) {
1573                         for (j = 0; j <= n; j++) {
1574                                 BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
1575
1576                                 grid[i][j][0] /= width;
1577                                 grid[i][j][1] /= height * aspy;
1578
1579                                 pos[0] += dx;
1580                         }
1581
1582                         pos[0] = min[0];
1583                         pos[1] += dy;
1584                 }
1585
1586                 glColor3f(1.0f, 0.0f, 0.0f);
1587
1588                 for (i = 0; i <= n; i++) {
1589                         glBegin(GL_LINE_STRIP);
1590                         for (j = 0; j <= n; j++) {
1591                                 glVertex2fv(grid[i][j]);
1592                         }
1593                         glEnd();
1594                 }
1595
1596                 for (j = 0; j <= n; j++) {
1597                         glBegin(GL_LINE_STRIP);
1598                         for (i = 0; i <= n; i++) {
1599                                 glVertex2fv(grid[i][j]);
1600                         }
1601                         glEnd();
1602                 }
1603         }
1604
1605         if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
1606                 gpd = clip->gpd;
1607         }
1608
1609         if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
1610                 bGPDlayer *layer = gpd->layers.first;
1611
1612                 while (layer) {
1613                         bGPDframe *frame = layer->frames.first;
1614
1615                         if (layer->flag & GP_LAYER_HIDE) {
1616                                 layer = layer->next;
1617                                 continue;
1618                         }
1619
1620                         glColor4fv(layer->color);
1621                         glLineWidth(layer->thickness);
1622                         glPointSize((float)(layer->thickness + 2));
1623
1624                         while (frame) {
1625                                 bGPDstroke *stroke = frame->strokes.first;
1626
1627                                 while (stroke) {
1628                                         if (stroke->flag & GP_STROKE_2DSPACE) {
1629                                                 if (stroke->totpoints > 1) {
1630                                                         glBegin(GL_LINE_STRIP);
1631                                                         for (i = 0; i < stroke->totpoints - 1; i++) {
1632                                                                 float npos[2], dpos[2], len;
1633                                                                 int steps;
1634
1635                                                                 pos[0] = (stroke->points[i].x + offsx) * width;
1636                                                                 pos[1] = (stroke->points[i].y + offsy) * height * aspy;
1637
1638                                                                 npos[0] = (stroke->points[i + 1].x + offsx) * width;
1639                                                                 npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;
1640
1641                                                                 len = len_v2v2(pos, npos);
1642                                                                 steps = ceil(len / 5.0f);
1643
1644                                                                 /* we want to distort only long straight lines */
1645                                                                 if (stroke->totpoints == 2) {
1646                                                                         BKE_tracking_undistort_v2(tracking, pos, pos);
1647                                                                         BKE_tracking_undistort_v2(tracking, npos, npos);
1648                                                                 }
1649
1650                                                                 sub_v2_v2v2(dpos, npos, pos);
1651                                                                 mul_v2_fl(dpos, 1.0f / steps);
1652
1653                                                                 for (j = 0; j <= steps; j++) {
1654                                                                         BKE_tracking_distort_v2(tracking, pos, tpos);
1655                                                                         glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));
1656
1657                                                                         add_v2_v2(pos, dpos);
1658                                                                 }
1659                                                         }
1660                                                         glEnd();
1661                                                 }
1662                                                 else if (stroke->totpoints == 1) {
1663                                                         glBegin(GL_POINTS);
1664                                                         glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
1665                                                         glEnd();
1666                                                 }
1667                                         }
1668
1669                                         stroke = stroke->next;
1670                                 }
1671
1672                                 frame = frame->next;
1673                         }
1674
1675                         layer = layer->next;
1676                 }
1677
1678                 glLineWidth(1.0f);
1679                 glPointSize(1.0f);
1680         }
1681
1682         glPopMatrix();
1683 }
1684
1685 void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
1686 {
1687         MovieClip *clip = ED_space_clip_get_clip(sc);
1688         Scene *scene = CTX_data_scene(C);
1689         ImBuf *ibuf = NULL;
1690         int width, height;
1691         float zoomx, zoomy;
1692
1693         ED_space_clip_get_size(sc, &width, &height);
1694         ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
1695
1696         /* if no clip, nothing to do */
1697         if (!clip) {
1698                 ED_region_grid_draw(ar, zoomx, zoomy);
1699                 return;
1700         }
1701
1702         if (sc->flag & SC_SHOW_STABLE) {
1703                 float translation[2];
1704                 float aspect = clip->tracking.camera.pixel_aspect;
1705                 float smat[4][4], ismat[4][4];
1706
1707                 if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
1708                         ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc,
1709                                                                &sc->scale, &sc->angle);
1710                 }
1711
1712                 if (ibuf != NULL && width != ibuf->x)
1713                         mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
1714                 else
1715                         copy_v2_v2(translation, sc->loc);
1716
1717                 BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation,
1718                                                         sc->scale, sc->angle, sc->stabmat);
1719
1720                 unit_m4(smat);
1721                 smat[0][0] = 1.0f / width;
1722                 smat[1][1] = 1.0f / height;
1723                 invert_m4_m4(ismat, smat);
1724
1725                 mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
1726         }
1727         else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
1728                 ibuf = ED_space_clip_get_buffer(sc);
1729
1730                 zero_v2(sc->loc);
1731                 sc->scale = 1.0f;
1732                 unit_m4(sc->stabmat);
1733                 unit_m4(sc->unistabmat);
1734         }
1735
1736         if (ibuf) {
1737                 draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
1738                 IMB_freeImBuf(ibuf);
1739         }
1740         else if (sc->flag & SC_MUTE_FOOTAGE) {
1741                 draw_movieclip_muted(ar, width, height, zoomx, zoomy);
1742         }
1743         else {
1744                 ED_region_grid_draw(ar, zoomx, zoomy);
1745         }
1746
1747         if (width && height) {
1748                 draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
1749                 draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy);
1750                 draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
1751         }
1752 }
1753
1754 void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *ar)
1755 {
1756         Scene *scene = CTX_data_scene(C);
1757         MovieClip *clip = ED_space_clip_get_clip(sc);
1758         if (clip) {
1759                 draw_movieclip_cache(sc, ar, clip, scene);
1760                 draw_movieclip_notes(sc, ar);
1761         }
1762 }
1763
1764 /* draw grease pencil */
1765 void clip_draw_grease_pencil(bContext *C, int onlyv2d)
1766 {
1767         SpaceClip *sc = CTX_wm_space_clip(C);
1768         MovieClip *clip = ED_space_clip_get_clip(sc);
1769
1770         if (!clip)
1771                 return;
1772
1773         if (onlyv2d) {
1774                 bool is_track_source = sc->gpencil_src == SC_GPENCIL_SRC_TRACK;
1775                 /* if manual calibration is used then grease pencil data
1776                  * associated with the clip is already drawn in draw_distortion
1777                  */
1778                 if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
1779                         glPushMatrix();
1780                         glMultMatrixf(sc->unistabmat);
1781
1782                         if (is_track_source) {
1783                                 MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
1784
1785                                 if (track) {
1786                                         int framenr = ED_space_clip_get_clip_frame_number(sc);
1787                                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1788
1789                                         glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
1790                                 }
1791                         }
1792
1793                         ED_gpencil_draw_2dimage(C);
1794
1795                         glPopMatrix();
1796                 }
1797         }
1798         else {
1799                 ED_gpencil_draw_view2d(C, 0);
1800         }
1801 }