Camera tracking integration
[blender.git] / source / blender / editors / space_clip / clip_draw.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2011 Blender Foundation.
21  * All rights reserved.
22  *
23  *
24  * Contributor(s): Blender Foundation,
25  *                 Sergey Sharybin
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/editors/space_clip/clip_draw.c
31  *  \ingroup spclip
32  */
33
34 #include "DNA_movieclip_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_object_types.h"   /* SELECT */
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BKE_context.h"
41 #include "BKE_movieclip.h"
42 #include "BKE_tracking.h"
43
44 #include "IMB_imbuf_types.h"
45 #include "IMB_imbuf.h"
46
47 #include "BLI_utildefines.h"
48 #include "BLI_math.h"
49 #include "BLI_string.h"
50 #include "BLI_rect.h"
51
52 #include "ED_screen.h"
53 #include "ED_clip.h"
54
55 #include "BIF_gl.h"
56 #include "BIF_glutil.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "UI_resources.h"
62 #include "UI_view2d.h"
63
64 #include "RNA_access.h"
65
66 #include "BLF_api.h"
67
68 #include "clip_intern.h"        // own include
69
70 /*********************** main area drawing *************************/
71
72 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
73 {
74         float x;
75         int *points, totseg, sel_type, i, a;
76         float sfra= SFRA, efra= EFRA, framelen= ar->winx/(efra-sfra+1), fontsize, fontwidth;
77         void *sel;
78         uiStyle *style= U.uistyles.first;
79         int fontid= style->widget.uifont_id;
80         char str[32];
81
82         BKE_movieclip_last_selection(clip, &sel_type, &sel);
83
84         glEnable(GL_BLEND);
85
86         /* cache background */
87         glColor4ub(128, 128, 255, 64);
88         glRecti(0, 0, ar->winx, 8);
89
90         /* cached segments -- could be usefu lto debug caching strategies */
91         BKE_movieclip_get_cache_segments(clip, &totseg, &points);
92         if(totseg) {
93                 glColor4ub(128, 128, 255, 128);
94
95                 for(a= 0; a<totseg; a++) {
96                         float x1, x2;
97
98                         x1= (points[a*2]-sfra)/(efra-sfra+1)*ar->winx;
99                         x2= (points[a*2+1]-sfra+1)/(efra-sfra+1)*ar->winx;
100
101                         glRecti(x1, 0, x2, 8);
102                 }
103         }
104
105         /* track */
106         if(sel_type==MCLIP_SEL_TRACK) {
107                 MovieTrackingTrack *track= (MovieTrackingTrack *)sel;
108
109                 for(i= sfra, a= 0; i <= efra; i++) {
110                         int framenr;
111                         MovieTrackingMarker *marker;
112
113                         while(a<track->markersnr) {
114                                 if(track->markers[a].framenr>=i)
115                                         break;
116
117                                 if(a<track->markersnr-1 && track->markers[a+1].framenr>i)
118                                         break;
119
120                                 a++;
121                         }
122
123                         if(a<track->markersnr) marker= &track->markers[a];
124                         else marker= &track->markers[track->markersnr-1];
125
126                         if((marker->flag&MARKER_DISABLED)==0) {
127                                 framenr= marker->framenr;
128
129                                 if(framenr!=i) glColor4ub(128, 128, 0, 96);
130                                 else glColor4ub(255, 255, 0, 96);
131
132                                 glRecti((i-sfra)*framelen, 0, (i-sfra+1)*framelen, 4);
133                         }
134                 }
135         }
136
137         /* failed frames */
138         if(clip->tracking.reconstruction.flag&TRACKING_RECONSTRUCTED) {
139                 int n= clip->tracking.reconstruction.camnr;
140                 MovieReconstructedCamera *cameras= clip->tracking.reconstruction.cameras;
141
142                 glColor4ub(255, 0, 0, 96);
143
144                 for(i= sfra, a= 0; i <= efra; i++) {
145                         int ok= 0;
146
147                         while(a<n) {
148                                 if(cameras[a].framenr==i) {
149                                         ok= 1;
150                                         break;
151                                 }
152                                 else if(cameras[a].framenr>i) {
153                                         break;
154                                 }
155
156                                 a++;
157                         }
158
159                         if(!ok)
160                                 glRecti((i-sfra)*framelen, 0, (i-sfra+1)*framelen, 8);
161                 }
162         }
163
164         glDisable(GL_BLEND);
165
166         /* current frame */
167         x= (sc->user.framenr-sfra)/(efra-sfra+1)*ar->winx;
168
169         UI_ThemeColor(TH_CFRAME);
170         glRecti(x, 0, x+framelen, 8);
171
172         /* frame number */
173         BLF_size(fontid, 11.f, U.dpi);
174         BLI_snprintf(str, sizeof(str), "%d", sc->user.framenr);
175         fontsize= BLF_height(fontid, str);
176         fontwidth= BLF_width(fontid, str);
177
178         if(x+fontwidth+6.f<=ar->winx) {
179                 glRecti(x, 8.f, x+fontwidth+6.f, 12.f+fontsize);
180
181                 glColor3f(0.f, 0.f, 0.f);
182                 BLF_position(fontid, x+2.f, 10.f, 0.f);
183                 BLF_draw(fontid, str, strlen(str));
184         } else {
185                 glRecti(x+framelen, 8.f, x+framelen-fontwidth-6.f, 12.f+fontsize);
186
187                 glColor3f(0.f, 0.f, 0.f);
188                 BLF_position(fontid, x-2.f-fontwidth+framelen, 10.f, 0.f);
189                 BLF_draw(fontid, str, strlen(str));
190         }
191 }
192
193 static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy)
194 {
195         int x, y;
196
197         /* set zoom */
198         glPixelZoom(zoomx, zoomy);
199
200         /* find window pixel coordinates of origin */
201         UI_view2d_to_region_no_clip(&ar->v2d, 0.f, 0.f, &x, &y);
202
203         if(sc->flag&SC_MUTE_FOOTAGE) {
204                 glColor3f(0.0f, 0.0f, 0.0f);
205                 glRectf(x, y, x+ibuf->x*sc->zoom, y+ibuf->y*sc->zoom);
206         } else {
207                 if(ibuf->rect_float && !ibuf->rect) {
208                         IMB_rect_from_float(ibuf);
209                 }
210
211                 if(ibuf->rect) {
212                         MovieClip *clip= ED_space_clip(sc);
213
214                         glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
215
216                         /* draw boundary border for frame if stabilization is enabled */
217                         if(sc->flag&SC_SHOW_STABLE && clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
218                                 glColor3f(0.f, 0.f, 0.f);
219                                 glLineStipple(3, 0xaaaa);
220                                 glEnable(GL_LINE_STIPPLE);
221                                 glEnable(GL_COLOR_LOGIC_OP);
222                                 glLogicOp(GL_NOR);
223
224                                 glPushMatrix();
225                                 glTranslatef(x, y, 0);
226
227                                 glScalef(zoomx, zoomy, 0);
228                                 glMultMatrixf(sc->stabmat);
229
230                                 glBegin(GL_LINE_LOOP);
231                                         glVertex2f(0.f, 0.f);
232                                         glVertex2f(ibuf->x, 0.f);
233                                         glVertex2f(ibuf->x, ibuf->y);
234                                         glVertex2f(0.f, ibuf->y);
235                                 glEnd();
236
237                                 glPopMatrix();
238
239                                 glDisable(GL_COLOR_LOGIC_OP);
240                                 glDisable(GL_LINE_STIPPLE);
241                         }
242                 }
243         }
244
245         /* reset zoom */
246         glPixelZoom(1.f, 1.f);
247 }
248
249 static void draw_track_path(SpaceClip *sc, MovieClip *clip, MovieTrackingTrack *track)
250 {
251         int count= sc->path_length;
252         int i, a, b, sel_type, curindex= -1;
253         float path[102][2];
254         int tiny= sc->flag&SC_SHOW_TINY_MARKER, framenr;
255         MovieTrackingMarker *marker;
256         void *sel;
257
258         if(count==0)
259                 return;
260
261         BKE_movieclip_last_selection(clip, &sel_type, &sel);
262
263         marker= BKE_tracking_get_marker(track, sc->user.framenr);
264         if(marker->framenr!=sc->user.framenr || marker->flag&MARKER_DISABLED)
265                 return;
266
267         framenr= marker->framenr;
268
269         a= count;
270         i= framenr-1;
271         while(i>=framenr-count) {
272                 marker= BKE_tracking_get_marker(track, i);
273
274                 if(!marker || marker->flag&MARKER_DISABLED)
275                         break;
276
277                 if(marker->framenr==i) {
278                         add_v2_v2v2(path[--a], marker->pos, track->offset);
279
280                         if(marker->framenr==sc->user.framenr)
281                                 curindex= a;
282                 } else
283                         break;
284
285                 i--;
286         }
287
288         b= count;
289         i= framenr;
290         while(i<=framenr+count) {
291                 marker= BKE_tracking_get_marker(track, i);
292
293                 if(!marker || marker->flag&MARKER_DISABLED)
294                         break;
295
296                 if(marker->framenr==i) {
297                         if(marker->framenr==sc->user.framenr)
298                                 curindex= b;
299
300                         add_v2_v2v2(path[b++], marker->pos, track->offset);
301                 } else
302                         break;
303
304                 i++;
305         }
306
307         if(!tiny) {
308                 UI_ThemeColor(TH_MARKER_OUTLINE);
309
310                 if(TRACK_VIEW_SELECTED(sc, track)) {
311                         glPointSize(5.0f);
312                         glBegin(GL_POINTS);
313                                 for(i= a; i<b; i++) {
314                                         if(i!=curindex)
315                                                 glVertex2f(path[i][0], path[i][1]);
316                                 }
317                         glEnd();
318                 }
319
320                 glLineWidth(3.0f);
321                 glBegin(GL_LINE_STRIP);
322                         for(i= a; i<b; i++)
323                                 glVertex2f(path[i][0], path[i][1]);
324                 glEnd();
325                 glLineWidth(1.0f);
326         }
327
328         UI_ThemeColor(TH_PATH_BEFORE);
329
330         if(TRACK_VIEW_SELECTED(sc, track)) {
331                 glPointSize(3.0f);
332                 glBegin(GL_POINTS);
333                         for(i= a; i<b; i++) {
334                                 if(i==count+1)
335                                         UI_ThemeColor(TH_PATH_AFTER);
336
337                                 if(i!=curindex)
338                                         glVertex2f(path[i][0], path[i][1]);
339                         }
340                 glEnd();
341         }
342
343         UI_ThemeColor(TH_PATH_BEFORE);
344
345         glBegin(GL_LINE_STRIP);
346                 for(i= a; i<b; i++) {
347                         if(i==count+1)
348                                 UI_ThemeColor(TH_PATH_AFTER);
349
350                         glVertex2f(path[i][0], path[i][1]);
351                 }
352         glEnd();
353         glPointSize(1.0f);
354 }
355
356 static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, int width, int height)
357 {
358         int tiny= sc->flag&SC_SHOW_TINY_MARKER;
359         int show_pat= 0;
360         float px[2];
361
362         UI_ThemeColor(TH_MARKER_OUTLINE);
363
364         px[0]= 1.0f/width/sc->zoom;
365         px[1]= 1.0f/height/sc->zoom;
366
367         if((marker->flag&MARKER_DISABLED)==0) {
368                 float pos[2];
369                 rctf r;
370
371                 BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]);
372                 add_v2_v2v2(pos, marker->pos, track->offset);
373
374                 if(BLI_in_rctf(&r, pos[0]-marker->pos[0], pos[1]-marker->pos[1])) {
375                         if(tiny) glPointSize(3.0f);
376                         else glPointSize(4.0f);
377                         glBegin(GL_POINTS);
378                                 glVertex2f(pos[0], pos[1]);
379                         glEnd();
380                         glPointSize(1.0f);
381                 } else {
382                         if(!tiny) glLineWidth(3.0f);
383                         glBegin(GL_LINES);
384                                 glVertex2f(pos[0] + px[0]*2, pos[1]);
385                                 glVertex2f(pos[0] + px[0]*8, pos[1]);
386
387                                 glVertex2f(pos[0] - px[0]*2, pos[1]);
388                                 glVertex2f(pos[0] - px[0]*8, pos[1]);
389
390                                 glVertex2f(pos[0], pos[1] - px[1]*2);
391                                 glVertex2f(pos[0], pos[1] - px[1]*8);
392
393                                 glVertex2f(pos[0], pos[1] + px[1]*2);
394                                 glVertex2f(pos[0], pos[1] + px[1]*8);
395                         glEnd();
396                         if(!tiny) glLineWidth(1.0f);
397                 }
398         }
399
400         /* pattern and search outline */
401         glPushMatrix();
402         glTranslatef(marker->pos[0], marker->pos[1], 0);
403
404         if(!tiny) glLineWidth(3.0f);
405
406         show_pat= ((marker->flag&MARKER_DISABLED)==0 || (sc->flag&SC_SHOW_MARKER_SEARCH)==0);
407         if(sc->flag&SC_SHOW_MARKER_PATTERN && show_pat) {
408                 glBegin(GL_LINE_LOOP);
409                         glVertex2f(track->pat_min[0], track->pat_min[1]);
410                         glVertex2f(track->pat_max[0], track->pat_min[1]);
411                         glVertex2f(track->pat_max[0], track->pat_max[1]);
412                         glVertex2f(track->pat_min[0], track->pat_max[1]);
413                 glEnd();
414         }
415
416         if(sc->flag&SC_SHOW_MARKER_SEARCH) {
417                 glBegin(GL_LINE_LOOP);
418                         glVertex2f(track->search_min[0], track->search_min[1]);
419                         glVertex2f(track->search_max[0], track->search_min[1]);
420                         glVertex2f(track->search_max[0], track->search_max[1]);
421                         glVertex2f(track->search_min[0], track->search_max[1]);
422                 glEnd();
423         }
424         glPopMatrix();
425
426         if(!tiny) glLineWidth(1.0f);
427 }
428
429 static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
430 {
431         if(track->flag&TRACK_CUSTOMCOLOR) {
432                 if(act) UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
433                 else copy_v3_v3(scol, track->color);
434
435                 mul_v3_v3fl(col, track->color, 0.5f);
436         } else {
437                 UI_GetThemeColor3fv(TH_MARKER, col);
438
439                 if(act) UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
440                 else UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
441         }
442 }
443
444 static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, int width, int height, int act, int sel)
445 {
446         int tiny= sc->flag&SC_SHOW_TINY_MARKER;
447         int show_pat= 0;
448         float col[3], scol[3], px[2];
449
450         track_colors(track, act, col, scol);
451
452         px[0]= 1.0f/width/sc->zoom;
453         px[1]= 1.0f/height/sc->zoom;
454
455         /* marker position and offset position */
456         if((track->flag&SELECT)==sel && (marker->flag&MARKER_DISABLED)==0) {
457                 float pos[2];
458                 rctf r;
459
460                 if(track->flag&TRACK_LOCKED) {
461                         if(act) UI_ThemeColor(TH_ACT_MARKER);
462                         else if(track->flag&SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64);
463                         else UI_ThemeColor(TH_LOCK_MARKER);
464                 } else {
465                         if(track->flag&SELECT) glColor3fv(scol);
466                         else glColor3fv(col);
467                 }
468
469                 add_v2_v2v2(pos, marker->pos, track->offset);
470
471                 BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]);
472                 add_v2_v2v2(pos, marker->pos, track->offset);
473
474                 if(BLI_in_rctf(&r, pos[0]-marker->pos[0], pos[1]-marker->pos[1])) {
475                         if(!tiny) glPointSize(2.0f);
476                         glBegin(GL_POINTS);
477                                 glVertex2f(pos[0], pos[1]);
478                         glEnd();
479                         if(!tiny) glPointSize(1.0f);
480                 } else {
481                         glBegin(GL_LINES);
482                                 glVertex2f(pos[0] + px[0]*3, pos[1]);
483                                 glVertex2f(pos[0] + px[0]*7, pos[1]);
484
485                                 glVertex2f(pos[0] - px[0]*3, pos[1]);
486                                 glVertex2f(pos[0] - px[0]*7, pos[1]);
487
488                                 glVertex2f(pos[0], pos[1] - px[1]*3);
489                                 glVertex2f(pos[0], pos[1] - px[1]*7);
490
491                                 glVertex2f(pos[0], pos[1] + px[1]*3);
492                                 glVertex2f(pos[0], pos[1] + px[1]*7);
493                         glEnd();
494
495                         glColor3f(0.f, 0.f, 0.f);
496                         glLineStipple(3, 0xaaaa);
497                         glEnable(GL_LINE_STIPPLE);
498                         glEnable(GL_COLOR_LOGIC_OP);
499                         glLogicOp(GL_NOR);
500
501                         glBegin(GL_LINES);
502                                 glVertex2fv(pos);
503                                 glVertex2fv(marker->pos);
504                         glEnd();
505
506                         glDisable(GL_COLOR_LOGIC_OP);
507                         glDisable(GL_LINE_STIPPLE);
508                 }
509         }
510
511         /* pattern */
512         glPushMatrix();
513         glTranslatef(marker->pos[0], marker->pos[1], 0);
514
515         if(tiny) {
516                 glLineStipple(3, 0xaaaa);
517                 glEnable(GL_LINE_STIPPLE);
518         }
519
520         show_pat= ((marker->flag&MARKER_DISABLED)==0 || (sc->flag&SC_SHOW_MARKER_SEARCH)==0);
521         if((track->pat_flag&SELECT)==sel && show_pat) {
522                 if(track->flag&TRACK_LOCKED) {
523                         if(act) UI_ThemeColor(TH_ACT_MARKER);
524                         else if(track->pat_flag&SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64);
525                         else UI_ThemeColor(TH_LOCK_MARKER);
526                 }
527                 else if(marker->flag&MARKER_DISABLED) {
528                         if(act) UI_ThemeColor(TH_ACT_MARKER);
529                         else if(track->pat_flag&SELECT) UI_ThemeColorShade(TH_DIS_MARKER, 128);
530                         else UI_ThemeColor(TH_DIS_MARKER);
531                 } else {
532                         if(track->pat_flag&SELECT) glColor3fv(scol);
533                         else glColor3fv(col);
534                 }
535
536                 if(sc->flag&SC_SHOW_MARKER_PATTERN) {
537                         glBegin(GL_LINE_LOOP);
538                                 glVertex2f(track->pat_min[0], track->pat_min[1]);
539                                 glVertex2f(track->pat_max[0], track->pat_min[1]);
540                                 glVertex2f(track->pat_max[0], track->pat_max[1]);
541                                 glVertex2f(track->pat_min[0], track->pat_max[1]);
542                         glEnd();
543                 }
544         }
545
546         /* search */
547         if((track->search_flag&SELECT)==sel) {
548                 if(track->flag&TRACK_LOCKED) {
549                         if(act) UI_ThemeColor(TH_ACT_MARKER);
550                         else if(track->search_flag&SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64);
551                         else UI_ThemeColor(TH_LOCK_MARKER);
552                 }
553                 else if(marker->flag&MARKER_DISABLED) {
554                         if(act) UI_ThemeColor(TH_ACT_MARKER);
555                         else if(track->search_flag&SELECT) UI_ThemeColorShade(TH_DIS_MARKER, 128);
556                         else UI_ThemeColor(TH_DIS_MARKER);
557                 } else {
558                         if(track->search_flag&SELECT) glColor3fv(scol);
559                         else glColor3fv(col);
560                 }
561
562                 if(sc->flag&SC_SHOW_MARKER_SEARCH) {
563                         glBegin(GL_LINE_LOOP);
564                                 glVertex2f(track->search_min[0], track->search_min[1]);
565                                 glVertex2f(track->search_max[0], track->search_min[1]);
566                                 glVertex2f(track->search_max[0], track->search_max[1]);
567                                 glVertex2f(track->search_min[0], track->search_max[1]);
568                         glEnd();
569                 }
570         }
571
572         if(tiny)
573                 glDisable(GL_LINE_STIPPLE);
574
575         glPopMatrix();
576 }
577
578 static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, int outline, int sel, int act, int width, int height)
579 {
580         float x, y, dx, dy, patdx, patdy, searchdx, searchdy, tdx, tdy;
581         int tiny= sc->flag&SC_SHOW_TINY_MARKER;
582         float col[3], scol[3], px[2];
583
584         if((tiny && outline) || (marker->flag&MARKER_DISABLED))
585                 return;
586
587         if(!TRACK_VIEW_SELECTED(sc, track) || track->flag&TRACK_LOCKED)
588                 return;
589
590         track_colors(track, act, col, scol);
591
592         if(outline) {
593                 glLineWidth(3.0f);
594                 UI_ThemeColor(TH_MARKER_OUTLINE);
595         }
596
597         glPushMatrix();
598         glTranslatef(marker->pos[0], marker->pos[1], 0);
599
600         dx= 6.0f/width/sc->zoom;
601         dy= 6.0f/height/sc->zoom;
602
603         patdx= MIN2(dx*2.f/3.f, (track->pat_max[0]-track->pat_min[0])/6.f);
604         patdy= MIN2(dy*2.f/3.f, (track->pat_max[1]-track->pat_min[1])/6.f);
605
606         searchdx= MIN2(dx, (track->search_max[0]-track->search_min[0])/6.f);
607         searchdy= MIN2(dy, (track->search_max[1]-track->search_min[1])/6.f);
608
609         px[0]= 1.0f/sc->zoom/width/sc->scale;
610         px[1]= 1.0f/sc->zoom/height/sc->scale;
611
612         if((sc->flag&SC_SHOW_MARKER_SEARCH) && ((track->search_flag&SELECT)==sel || outline)) {
613                 if(!outline) {
614                         if(track->search_flag&SELECT) glColor3fv(scol);
615                         else glColor3fv(col);
616                 }
617
618                 /* search offset square */
619                 x= track->search_min[0];
620                 y= track->search_max[1];
621
622                 tdx= searchdx;
623                 tdy= searchdy;
624
625                 if(outline) {
626                         tdx+= px[0];
627                         tdy+= px[1];
628                 }
629
630                 glBegin(GL_QUADS);
631                         glVertex3f(x-tdx, y+tdy, 0);
632                         glVertex3f(x+tdx, y+tdy, 0);
633                         glVertex3f(x+tdx, y-tdy, 0);
634                         glVertex3f(x-tdx, y-tdy, 0);
635                 glEnd();
636
637                 /* search resizing triangle */
638                 x= track->search_max[0];
639                 y= track->search_min[1];
640
641                 tdx= searchdx*2.f;
642                 tdy= searchdy*2.f;
643
644                 if(outline) {
645                         tdx+= px[0];
646                         tdy+= px[1];
647                 }
648
649                 glBegin(GL_TRIANGLES);
650                         glVertex3f(x, y, 0);
651                         glVertex3f(x-tdx, y, 0);
652                         glVertex3f(x, y+tdy, 0);
653                 glEnd();
654         }
655
656         if((sc->flag&SC_SHOW_MARKER_PATTERN) && ((track->pat_flag&SELECT)==sel || outline)) {
657                 if(!outline) {
658                         if(track->pat_flag&SELECT) glColor3fv(scol);
659                         else glColor3fv(col);
660                 }
661
662                 /* pattern offset square */
663                 x= track->pat_min[0];
664                 y= track->pat_max[1];
665
666                 tdx= patdx;
667                 tdy= patdy;
668
669                 if(outline) {
670                         tdx+= px[0];
671                         tdy+= px[1];
672                 }
673
674                 glBegin(GL_QUADS);
675                         glVertex3f(x-tdx, y+tdy, 0);
676                         glVertex3f(x+tdx, y+tdy, 0);
677                         glVertex3f(x+tdx, y-tdy, 0);
678                         glVertex3f(x-tdx, y-tdy, 0);
679                 glEnd();
680
681                 /* pattern resizing triangle */
682                 x= track->pat_max[0];
683                 y= track->pat_min[1];
684
685                 tdx= patdx*2.f;
686                 tdy= patdy*2.f;
687
688                 if(outline) {
689                         tdx+= px[0];
690                         tdy+= px[1];
691                 }
692
693                 glBegin(GL_TRIANGLES);
694                         glVertex3f(x, y, 0);
695                         glVertex3f(x-tdx, y, 0);
696                         glVertex3f(x, y+tdy, 0);
697                 glEnd();
698         }
699
700         glPopMatrix();
701
702         if(outline)
703                 glLineWidth(1.0f);
704 }
705
706 static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, int act,
707                         int width, int height, float zoomx, float zoomy)
708 {
709         char str[128]= {0}, state[64]= {0};
710         float x, y, dx= 0.f, dy= 0.f, fontsize;
711         uiStyle *style= U.uistyles.first;
712         int fontid= style->widget.uifont_id;
713
714         if(!TRACK_VIEW_SELECTED(sc, track))
715                 return;
716
717         BLF_size(fontid, 11.f, U.dpi);
718         fontsize= BLF_height_max(fontid);
719
720         if(marker->flag&MARKER_DISABLED) {
721                 if(act) UI_ThemeColor(TH_ACT_MARKER);
722                 else UI_ThemeColorShade(TH_DIS_MARKER, 128);
723         } else {
724                 if(act) UI_ThemeColor(TH_ACT_MARKER);
725                 else UI_ThemeColor(TH_SEL_MARKER);
726         }
727
728         if(sc->flag&SC_SHOW_MARKER_SEARCH) {
729                 dx= track->search_min[0];
730                 dy= track->search_min[1];
731         } else if(sc->flag&SC_SHOW_MARKER_PATTERN) {
732                 dx= track->pat_min[0];
733                 dy= track->pat_min[1];
734         }
735
736         x= (marker->pos[0]+dx)*width*sc->scale*zoomx+sc->loc[0]*zoomx;
737         y= (marker->pos[1]+dy)*height*sc->scale*zoomy-fontsize+sc->loc[1]*zoomy;
738
739         if(marker->flag&MARKER_DISABLED) strcpy(state, "disabled");
740         else if(marker->framenr!=sc->user.framenr) strcpy(state, "estimated");
741         else if(marker->flag&MARKER_TRACKED) strcpy(state, "tracked");
742         else strcpy(state, "keyframed");
743
744         if(state[0])
745                 BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
746         else
747                 BLI_snprintf(str, sizeof(str), "%s", track->name);
748
749         BLF_position(fontid, x, y, 0.f);
750         BLF_draw(fontid, str, strlen(str));
751         y-= fontsize;
752
753         if(track->flag&TRACK_HAS_BUNDLE) {
754                 BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
755                 BLF_position(fontid, x, y, 0.f);
756                 BLF_draw(fontid, str, strlen(str));
757                 y-= fontsize;
758         }
759
760         if(track->flag&TRACK_LOCKED) {
761                 BLF_position(fontid, x, y, 0.f);
762                 BLF_draw(fontid, "locked", 6);
763         }
764 }
765
766 static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
767 {
768         /* express given coordinates as proportional values */
769         x= -v2d->cur.xmin / (v2d->cur.xmax-v2d->cur.xmin);
770         y= -v2d->cur.ymin / (v2d->cur.ymax-v2d->cur.ymin);
771
772         /* convert proportional distances to screen coordinates */
773         *regionx= v2d->mask.xmin + x*(v2d->mask.xmax-v2d->mask.xmin);
774         *regiony= v2d->mask.ymin + y*(v2d->mask.ymax-v2d->mask.ymin);
775 }
776
777 static void draw_distorion_grid(MovieTracking *tracking, int width, int height)
778 {
779         const int n= 9;
780         int x, y;
781         float pos[2], grid[10][10][2];
782         float dx= (float)width/n, dy= (float)height/n;
783
784         if(!tracking->camera.focal)
785                 return;
786
787         zero_v2(pos);
788
789         for(y= 0; y<=n; y++) {
790                 for(x= 0; x<=n; x++) {
791                         BKE_tracking_invert_intrinsics(tracking, pos, grid[y][x]);
792
793                         grid[y][x][0]/= width;
794                         grid[y][x][1]/= height;
795
796                         pos[0]+= dx;
797                 }
798
799                 pos[0]= 0.f;
800                 pos[1]+= dy;
801         }
802
803         glColor3f(1.f, 0.f, 0.f);
804
805         for(y= 0; y<=n; y++) {
806                 glBegin(GL_LINE_STRIP);
807                         for(x= 0; x<=n; x++) {
808                                 glVertex2fv(grid[y][x]);
809                         }
810                 glEnd();
811         }
812
813         for(x= 0; x<=n; x++) {
814                 glBegin(GL_LINE_STRIP);
815                         for(y= 0; y<=n; y++) {
816                                 glVertex2fv(grid[y][x]);
817                         }
818                 glEnd();
819         }
820 }
821
822 static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
823                         int width, int height, float zoomx, float zoomy)
824 {
825         float x, y;
826         MovieTracking* tracking= &clip->tracking;
827         MovieTrackingMarker *marker;
828         MovieTrackingTrack *track;
829         int sel_type, framenr= sc->user.framenr;
830         void *sel;
831
832         /* ** find window pixel coordinates of origin ** */
833
834         /* UI_view2d_to_region_no_clip return integer values, this could
835            lead to 1px flickering when view is locked to selection during playbeck.
836            to avoid this flickering, calclate base point in the same way as it happens
837            in UI_view2d_to_region_no_clip, but do it in floats here */
838
839         view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
840
841         glPushMatrix();
842         glTranslatef(x, y, 0);
843
844         glPushMatrix();
845         glScalef(zoomx, zoomy, 0);
846         glMultMatrixf(sc->stabmat);
847         glScalef(width, height, 0);
848
849         BKE_movieclip_last_selection(clip, &sel_type, &sel);
850
851         if(sc->flag&SC_SHOW_TRACK_PATH) {
852                 track= tracking->tracks.first;
853                 while(track) {
854                         if((track->flag&TRACK_HIDDEN)==0)
855                                 draw_track_path(sc, clip, track);
856
857                         track= track->next;
858                 }
859         }
860
861         /* markers outline and non-selected areas */
862         track= tracking->tracks.first;
863         while(track) {
864                 if((track->flag&TRACK_HIDDEN)==0) {
865                         marker= BKE_tracking_get_marker(track, framenr);
866
867                         if(MARKER_VISIBLE(sc, marker)) {
868                                 draw_marker_outline(sc, track, marker, width, height);
869                                 draw_marker_areas(sc, track, marker, width, height, 0, 0);
870                                 draw_marker_slide_zones(sc, track, marker, 1, 0, 0, width, height);
871                                 draw_marker_slide_zones(sc, track, marker, 0, 0, 0, width, height);
872                         }
873                 }
874
875                 track= track->next;
876         }
877
878         /* selected areas only, so selection wouldn't be overlapped by
879            non-selected areas */
880         track= tracking->tracks.first;
881         while(track) {
882                 if((track->flag&TRACK_HIDDEN)==0) {
883                         int act= sel_type==MCLIP_SEL_TRACK && sel==track;
884
885                         if(!act) {
886                                 marker= BKE_tracking_get_marker(track, framenr);
887
888                                 if(MARKER_VISIBLE(sc, marker)) {
889                                         draw_marker_areas(sc, track, marker, width, height, 0, 1);
890                                         draw_marker_slide_zones(sc, track, marker, 0, 1, 0, width, height);
891                                 }
892                         }
893                 }
894
895                 track= track->next;
896         }
897
898         /* active marker would be displayed on top of everything else */
899         if(sel_type==MCLIP_SEL_TRACK) {
900                 if((((MovieTrackingTrack *)sel)->flag&TRACK_HIDDEN)==0) {
901                         marker= BKE_tracking_get_marker(sel, framenr);
902
903                         if(MARKER_VISIBLE(sc, marker)) {
904                                 draw_marker_areas(sc, sel, marker, width, height, 1, 1);
905                                 draw_marker_slide_zones(sc, sel, marker, 0, 1, 1, width, height);
906                         }
907                 }
908         }
909
910         if(sc->flag&SC_SHOW_BUNDLES) {
911                 float pos[4], vec[4], mat[4][4], aspx, aspy;
912
913                 glEnable(GL_POINT_SMOOTH);
914                 glPointSize(3.0f);
915
916                 BKE_movieclip_aspect(clip, &aspx, &aspy);
917                 BKE_tracking_projection_matrix(tracking, framenr, width*aspx, height*aspy, mat);
918
919                 track= tracking->tracks.first;
920                 while(track) {
921                         if((track->flag&TRACK_HIDDEN)==0 && track->flag&TRACK_HAS_BUNDLE) {
922                                 marker= BKE_tracking_get_marker(track, framenr);
923
924                                 if(MARKER_VISIBLE(sc, marker)) {
925                                         copy_v4_v4(vec, track->bundle_pos);
926                                         vec[3]=1;
927
928                                         mul_v4_m4v4(pos, mat, vec);
929
930                                         pos[0]= (pos[0]/(pos[3]*2.0f)+0.5f)*width;
931                                         pos[1]= (pos[1]/(pos[3]*2.0f)+0.5f)*height;
932
933                                         BKE_tracking_apply_intrinsics(tracking, pos, pos);
934
935                                         vec[0]= (marker->pos[0]+track->offset[0])*width;
936                                         vec[1]= (marker->pos[1]+track->offset[1])*height;
937                                         sub_v2_v2(vec, pos);
938
939                                         if(len_v2(vec)<3) glColor3f(0.0f, 1.0f, 0.0f);
940                                         else glColor3f(1.0f, 0.0f, 0.0f);
941
942                                         glBegin(GL_POINTS);
943                                                 glVertex3f(pos[0]/width, pos[1]/height, 0);
944                                         glEnd();
945                                 }
946                         }
947
948                         track= track->next;
949                 }
950
951                 glPointSize(1.0f);
952                 glDisable(GL_POINT_SMOOTH);
953         }
954
955         if(sc->flag&SC_SHOW_GRID)
956                 draw_distorion_grid(tracking, width, height);
957
958         glPopMatrix();
959
960         if(sc->flag&SC_SHOW_NAMES) {
961                 /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
962                 track= tracking->tracks.first;
963                 while(track) {
964                         if((track->flag&TRACK_HIDDEN)==0) {
965                                 marker= BKE_tracking_get_marker(track, framenr);
966
967                                 if(MARKER_VISIBLE(sc, marker)) {
968                                         int act= sel_type==MCLIP_SEL_TRACK && sel==track;
969
970                                         draw_marker_texts(sc, track, marker, act, width, height, zoomx, zoomy);
971                                 }
972                         }
973
974                         track= track->next;
975                 }
976         }
977
978         glPopMatrix();
979 }
980
981 static void draw_tracking(SpaceClip *sc, ARegion *ar, MovieClip *clip,
982                         int width, int height, float zoomx, float zoomy)
983 {
984         draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy);
985 }
986
987 void draw_clip_main(SpaceClip *sc, ARegion *ar, Scene *scene)
988 {
989         MovieClip *clip= ED_space_clip(sc);
990         ImBuf *ibuf;
991         float zoomx, zoomy;
992
993         /* if no clip, nothing to do */
994         if(!clip)
995                 return;
996
997         ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
998
999         if(sc->flag&SC_SHOW_STABLE) {
1000                 ibuf= ED_space_clip_acquire_stable_buffer(sc, sc->loc, &sc->scale);
1001                 BKE_tracking_stabdata_to_mat4(sc->loc, sc->scale, sc->stabmat);
1002         } else {
1003                 ibuf= ED_space_clip_acquire_buffer(sc);
1004
1005                 zero_v2(sc->loc);
1006                 sc->scale= 1.f;
1007                 unit_m4(sc->stabmat);
1008         }
1009
1010         if(ibuf) {
1011                 draw_movieclip_buffer(sc, ar, ibuf, zoomx, zoomy);
1012                 IMB_freeImBuf(ibuf);
1013
1014                 draw_tracking(sc, ar, clip, ibuf->x, ibuf->y, zoomx, zoomy);
1015         }
1016
1017         draw_movieclip_cache(sc, ar, clip, scene);
1018 }