2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2011 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation,
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/space_clip/clip_draw.c
32 #include "DNA_gpencil_types.h"
33 #include "DNA_movieclip_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_object_types.h" /* SELECT */
36 #include "DNA_mask_types.h"
38 #include "MEM_guardedalloc.h"
40 #include "BKE_context.h"
41 #include "BKE_movieclip.h"
42 #include "BKE_tracking.h"
45 #include "IMB_colormanagement.h"
46 #include "IMB_imbuf_types.h"
47 #include "IMB_imbuf.h"
49 #include "BLI_utildefines.h"
51 #include "BLI_string.h"
53 #include "BLI_math_base.h"
55 #include "ED_screen.h"
57 #include "ED_gpencil.h"
60 #include "BIF_glutil.h"
65 #include "UI_interface.h"
66 #include "UI_resources.h"
67 #include "UI_view2d.h"
69 #include "RNA_access.h"
73 #include "clip_intern.h" // own include
75 /*********************** main area drawing *************************/
77 void clip_draw_curfra_label(SpaceClip *sc, float x, float y)
79 uiStyle *style = UI_GetStyle();
80 int fontid = style->widget.uifont_id;
82 float font_dims[2] = {0.0f, 0.0f};
85 BLF_size(fontid, 11.0f, U.dpi);
86 BLI_snprintf(numstr, sizeof(numstr), "%d", sc->user.framenr);
88 BLF_width_and_height(fontid, numstr, &font_dims[0], &font_dims[1]);
90 glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
92 UI_ThemeColor(TH_TEXT);
93 BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
94 BLF_draw(fontid, numstr, sizeof(numstr));
97 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
100 int *points, totseg, i, a;
101 float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
102 MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
103 MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(&clip->tracking);
107 /* cache background */
108 glColor4ub(128, 128, 255, 64);
109 glRecti(0, 0, ar->winx, 8);
111 /* cached segments -- could be usefu lto debug caching strategies */
112 BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
114 glColor4ub(128, 128, 255, 128);
116 for (a = 0; a < totseg; a++) {
119 x1 = (points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
120 x2 = (points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
122 glRecti(x1, 0, x2, 8);
128 MovieTrackingTrack *track = act_track;
130 for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
132 MovieTrackingMarker *marker;
134 while (a < track->markersnr) {
135 if (track->markers[a].framenr >= i)
138 if (a < track->markersnr - 1 && track->markers[a + 1].framenr > i)
144 if (a < track->markersnr)
145 marker = &track->markers[a];
147 marker = &track->markers[track->markersnr - 1];
149 if ((marker->flag & MARKER_DISABLED) == 0) {
150 framenr = marker->framenr;
153 glColor4ub(128, 128, 0, 96);
154 else if ((marker->flag & MARKER_TRACKED) == 0)
155 glColor4ub(255, 255, 0, 196);
157 glColor4ub(255, 255, 0, 96);
159 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4);
165 if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
166 int n = reconstruction->camnr;
167 MovieReconstructedCamera *cameras = reconstruction->cameras;
169 glColor4ub(255, 0, 0, 96);
171 for (i = sfra, a = 0; i <= efra; i++) {
175 if (cameras[a].framenr == i) {
179 else if (cameras[a].framenr > i) {
187 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8);
194 x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
196 UI_ThemeColor(TH_CFRAME);
197 glRecti(x, 0, x + framelen, 8);
199 clip_draw_curfra_label(sc, x, 8.0f);
201 /* movie clip animation */
202 if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask) {
203 MaskLayer *masklay = BKE_mask_layer_active(sc->mask);
205 MaskLayerShape *masklay_shape;
207 glColor4ub(255, 175, 0, 255);
210 for (masklay_shape = masklay->splines_shapes.first;
212 masklay_shape = masklay_shape->next)
214 i = masklay_shape->frame;
216 /* glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 4); */
218 /* use a line so we always see the keyframes */
219 glVertex2i((i - sfra) * framelen, 0);
220 glVertex2i((i - sfra) * framelen, (i == CFRA) ? 22 : 10);
228 static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
230 MovieClip *clip = ED_space_clip_get_clip(sc);
231 MovieTracking *tracking = &clip->tracking;
235 if (tracking->stats) {
236 BLI_strncpy(str, tracking->stats->message, sizeof(str));
240 if (sc->flag & SC_LOCK_SELECTION)
241 strcpy(str, "Locked");
245 ED_region_info_draw(ar, str, block, 0.6f);
248 static void verify_buffer_float(ImBuf *ibuf)
250 if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) {
251 IMB_rect_from_float(ibuf);
255 static void draw_movieclip_buffer(wmWindow *win, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
256 int width, int height, float zoomx, float zoomy)
259 MovieClip *clip = ED_space_clip_get_clip(sc);
261 /* find window pixel coordinates of origin */
262 UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
264 if (sc->flag & SC_MUTE_FOOTAGE) {
265 glColor3f(0.0f, 0.0f, 0.0f);
266 glRectf(x, y, x + zoomx * width, y + zoomy * height);
269 const ColorManagedViewSettings *view_settings;
270 unsigned char *display_buffer;
273 verify_buffer_float(ibuf);
275 view_settings = IMB_view_settings_get_effective(win, &sc->view_settings);
276 display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, win->display_device, &cache_handle);
278 if (display_buffer) {
279 int need_fallback = 1;
281 if (ED_space_clip_texture_buffer_supported(sc)) {
282 if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) {
284 glTranslatef(x, y, 0.0f);
285 glScalef(zoomx, zoomy, 1.0f);
288 glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
289 glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f);
290 glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height);
291 glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height);
296 ED_space_clip_unload_movieclip_buffer(sc);
302 /* if texture buffers aren't efficiently supported or texture is too large to
303 * be binder fallback to simple draw pixels solution */
306 glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
308 glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
311 glPixelZoom(1.0f, 1.0f);
315 IMB_display_buffer_release(cache_handle);
318 /* draw boundary border for frame if stabilization is enabled */
319 if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
320 glColor3f(0.0f, 0.0f, 0.0f);
321 glLineStipple(3, 0xaaaa);
322 glEnable(GL_LINE_STIPPLE);
323 glEnable(GL_COLOR_LOGIC_OP);
327 glTranslatef(x, y, 0.0f);
329 glScalef(zoomx, zoomy, 1.0f);
330 glMultMatrixf(sc->stabmat);
332 glBegin(GL_LINE_LOOP);
333 glVertex2f(0.0f, 0.0f);
334 glVertex2f(width, 0.0f);
335 glVertex2f(width, height);
336 glVertex2f(0.0f, height);
341 glDisable(GL_COLOR_LOGIC_OP);
342 glDisable(GL_LINE_STIPPLE);
346 static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
348 int count = sc->path_length;
349 int i, a, b, curindex = -1;
351 int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
352 MovieTrackingMarker *marker;
357 start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);
359 marker = BKE_tracking_marker_get(track, framenr);
360 if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
365 while (i >= framenr - count) {
366 marker = BKE_tracking_marker_get(track, i);
368 if (!marker || marker->flag & MARKER_DISABLED)
371 if (marker->framenr == i) {
372 add_v2_v2v2(path[--a], marker->pos, track->offset);
373 ED_clip_point_undistorted_pos(sc, path[a], path[a]);
375 if (marker->framenr == start_frame)
387 while (i <= framenr + count) {
388 marker = BKE_tracking_marker_get(track, i);
390 if (!marker || marker->flag & MARKER_DISABLED)
393 if (marker->framenr == i) {
394 if (marker->framenr == start_frame)
397 add_v2_v2v2(path[b++], marker->pos, track->offset);
398 ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
407 UI_ThemeColor(TH_MARKER_OUTLINE);
409 if (TRACK_VIEW_SELECTED(sc, track)) {
412 for (i = a; i < b; i++) {
414 glVertex2f(path[i][0], path[i][1]);
420 glBegin(GL_LINE_STRIP);
421 for (i = a; i < b; i++)
422 glVertex2f(path[i][0], path[i][1]);
427 UI_ThemeColor(TH_PATH_BEFORE);
429 if (TRACK_VIEW_SELECTED(sc, track)) {
432 for (i = a; i < b; i++) {
434 UI_ThemeColor(TH_PATH_AFTER);
437 glVertex2f(path[i][0], path[i][1]);
442 UI_ThemeColor(TH_PATH_BEFORE);
444 glBegin(GL_LINE_STRIP);
445 for (i = a; i < b; i++) {
447 UI_ThemeColor(TH_PATH_AFTER);
449 glVertex2f(path[i][0], path[i][1]);
455 static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
456 float marker_pos[2], int width, int height)
458 int tiny = sc->flag & SC_SHOW_TINY_MARKER;
459 int show_search = FALSE;
462 UI_ThemeColor(TH_MARKER_OUTLINE);
464 px[0] = 1.0f / width / sc->zoom;
465 px[1] = 1.0f / height / sc->zoom;
467 if ((marker->flag & MARKER_DISABLED) == 0) {
471 add_v2_v2v2(pos, marker->pos, track->offset);
473 ED_clip_point_undistorted_pos(sc, pos, pos);
475 sub_v2_v2v2(p, pos, marker_pos);
477 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
478 marker->pattern_corners[2], marker->pattern_corners[3]))
480 if (tiny) glPointSize(3.0f);
481 else glPointSize(4.0f);
483 glVertex2f(pos[0], pos[1]);
488 if (!tiny) glLineWidth(3.0f);
490 glVertex2f(pos[0] + px[0] * 2, pos[1]);
491 glVertex2f(pos[0] + px[0] * 8, pos[1]);
493 glVertex2f(pos[0] - px[0] * 2, pos[1]);
494 glVertex2f(pos[0] - px[0] * 8, pos[1]);
496 glVertex2f(pos[0], pos[1] - px[1] * 2);
497 glVertex2f(pos[0], pos[1] - px[1] * 8);
499 glVertex2f(pos[0], pos[1] + px[1] * 2);
500 glVertex2f(pos[0], pos[1] + px[1] * 8);
502 if (!tiny) glLineWidth(1.0f);
506 /* pattern and search outline */
508 glTranslatef(marker_pos[0], marker_pos[1], 0);
513 if (sc->flag & SC_SHOW_MARKER_PATTERN) {
514 glBegin(GL_LINE_LOOP);
515 glVertex2fv(marker->pattern_corners[0]);
516 glVertex2fv(marker->pattern_corners[1]);
517 glVertex2fv(marker->pattern_corners[2]);
518 glVertex2fv(marker->pattern_corners[3]);
522 show_search = TRACK_VIEW_SELECTED(sc, track) &&
523 ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
524 if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
525 glBegin(GL_LINE_LOOP);
526 glVertex2f(marker->search_min[0], marker->search_min[1]);
527 glVertex2f(marker->search_max[0], marker->search_min[1]);
528 glVertex2f(marker->search_max[0], marker->search_max[1]);
529 glVertex2f(marker->search_min[0], marker->search_max[1]);
538 static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
540 if (track->flag & TRACK_CUSTOMCOLOR) {
542 UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
544 copy_v3_v3(scol, track->color);
546 mul_v3_v3fl(col, track->color, 0.5f);
549 UI_GetThemeColor3fv(TH_MARKER, col);
552 UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
554 UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
558 static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
559 float marker_pos[2], int width, int height, int act, int sel)
561 int tiny = sc->flag & SC_SHOW_TINY_MARKER;
563 float col[3], scol[3], px[2];
565 track_colors(track, act, col, scol);
567 px[0] = 1.0f / width / sc->zoom;
568 px[1] = 1.0f / height / sc->zoom;
570 /* marker position and offset position */
571 if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
574 if (track->flag & TRACK_LOCKED) {
576 UI_ThemeColor(TH_ACT_MARKER);
577 else if (track->flag & SELECT)
578 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
580 UI_ThemeColor(TH_LOCK_MARKER);
583 if (track->flag & SELECT)
589 add_v2_v2v2(pos, marker->pos, track->offset);
590 ED_clip_point_undistorted_pos(sc, pos, pos);
592 sub_v2_v2v2(p, pos, marker_pos);
594 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
595 marker->pattern_corners[2], marker->pattern_corners[3]))
601 glVertex2f(pos[0], pos[1]);
609 glVertex2f(pos[0] + px[0] * 3, pos[1]);
610 glVertex2f(pos[0] + px[0] * 7, pos[1]);
612 glVertex2f(pos[0] - px[0] * 3, pos[1]);
613 glVertex2f(pos[0] - px[0] * 7, pos[1]);
615 glVertex2f(pos[0], pos[1] - px[1] * 3);
616 glVertex2f(pos[0], pos[1] - px[1] * 7);
618 glVertex2f(pos[0], pos[1] + px[1] * 3);
619 glVertex2f(pos[0], pos[1] + px[1] * 7);
622 glColor3f(0.0f, 0.0f, 0.0f);
623 glLineStipple(3, 0xaaaa);
624 glEnable(GL_LINE_STIPPLE);
625 glEnable(GL_COLOR_LOGIC_OP);
630 glVertex2fv(marker_pos);
633 glDisable(GL_COLOR_LOGIC_OP);
634 glDisable(GL_LINE_STIPPLE);
640 glTranslatef(marker_pos[0], marker_pos[1], 0);
643 glLineStipple(3, 0xaaaa);
644 glEnable(GL_LINE_STIPPLE);
647 if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
648 if (track->flag & TRACK_LOCKED) {
650 UI_ThemeColor(TH_ACT_MARKER);
651 else if (track->pat_flag & SELECT)
652 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
653 else UI_ThemeColor(TH_LOCK_MARKER);
655 else if (marker->flag & MARKER_DISABLED) {
657 UI_ThemeColor(TH_ACT_MARKER);
658 else if (track->pat_flag & SELECT)
659 UI_ThemeColorShade(TH_DIS_MARKER, 128);
660 else UI_ThemeColor(TH_DIS_MARKER);
663 if (track->pat_flag & SELECT)
665 else glColor3fv(col);
668 glBegin(GL_LINE_LOOP);
669 glVertex2fv(marker->pattern_corners[0]);
670 glVertex2fv(marker->pattern_corners[1]);
671 glVertex2fv(marker->pattern_corners[2]);
672 glVertex2fv(marker->pattern_corners[3]);
677 show_search = TRACK_VIEW_SELECTED(sc, track) &&
678 ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
679 if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
680 if (track->flag & TRACK_LOCKED) {
682 UI_ThemeColor(TH_ACT_MARKER);
683 else if (track->search_flag & SELECT)
684 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
685 else UI_ThemeColor(TH_LOCK_MARKER);
687 else if (marker->flag & MARKER_DISABLED) {
689 UI_ThemeColor(TH_ACT_MARKER);
690 else if (track->search_flag & SELECT)
691 UI_ThemeColorShade(TH_DIS_MARKER, 128);
692 else UI_ThemeColor(TH_DIS_MARKER);
695 if (track->search_flag & SELECT)
701 glBegin(GL_LINE_LOOP);
702 glVertex2f(marker->search_min[0], marker->search_min[1]);
703 glVertex2f(marker->search_max[0], marker->search_min[1]);
704 glVertex2f(marker->search_max[0], marker->search_max[1]);
705 glVertex2f(marker->search_min[0], marker->search_max[1]);
710 glDisable(GL_LINE_STIPPLE);
715 static float get_shortest_pattern_side(MovieTrackingMarker *marker)
720 for (i = 0; i < 4; i++) {
725 cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
727 len = MIN2(cur_len, len);
733 static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
746 glVertex3f(x - tdx, y + tdy, 0.0f);
747 glVertex3f(x + tdx, y + tdy, 0.0f);
748 glVertex3f(x + tdx, y - tdy, 0.0f);
749 glVertex3f(x - tdx, y - tdy, 0.0f);
753 static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
765 glBegin(GL_TRIANGLES);
766 glVertex3f(x, y, 0.0f);
767 glVertex3f(x - tdx, y, 0.0f);
768 glVertex3f(x, y + tdy, 0.0f);
772 static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
773 float marker_pos[2], int outline, int sel, int act, int width, int height)
775 float dx, dy, patdx, patdy, searchdx, searchdy;
776 int tiny = sc->flag & SC_SHOW_TINY_MARKER;
777 float col[3], scol[3], px[2], side;
779 if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
782 if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
785 track_colors(track, act, col, scol);
789 UI_ThemeColor(TH_MARKER_OUTLINE);
793 glTranslatef(marker_pos[0], marker_pos[1], 0);
795 dx = 6.0f / width / sc->zoom;
796 dy = 6.0f / height / sc->zoom;
798 side = get_shortest_pattern_side(marker);
799 patdx = MIN2(dx * 2.0f / 3.0f, side / 6.0f);
800 patdy = MIN2(dy * 2.0f / 3.0f, side * width / height / 6.0f);
802 searchdx = MIN2(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f);
803 searchdy = MIN2(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f);
805 px[0] = 1.0f / sc->zoom / width / sc->scale;
806 px[1] = 1.0f / sc->zoom / height / sc->scale;
808 if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
810 if (track->search_flag & SELECT)
816 /* search offset square */
817 draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);
819 /* search re-sizing triangle */
820 draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
823 if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
825 float pat_min[2], pat_max[2];
826 /* float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
830 if (track->pat_flag & SELECT)
836 /* pattern's corners sliding squares */
837 for (i = 0; i < 4; i++) {
838 draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
839 patdx / 1.5f, patdy / 1.5f, outline, px);
842 /* ** sliders to control overall pattern ** */
843 add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);
845 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
847 glEnable(GL_LINE_STIPPLE);
848 glLineStipple(3, 0xaaaa);
851 /* TODO: disable for now, needs better approach visualizing this */
853 glBegin(GL_LINE_LOOP);
854 glVertex2f(pat_min[0] - dx, pat_min[1] - dy);
855 glVertex2f(pat_max[0] + dx, pat_min[1] - dy);
856 glVertex2f(pat_max[0] + dx, pat_max[1] + dy);
857 glVertex2f(pat_min[0] - dx, pat_max[1] + dy);
860 /* marker's offset slider */
861 draw_marker_slide_square(pat_min[0] - dx, pat_max[1] + dy, patdx, patdy, outline, px);
863 /* pattern re-sizing triangle */
864 draw_marker_slide_triangle(pat_max[0] + dx, pat_min[1] - dy, patdx, patdy, outline, px);
868 glVertex2f(0.0f, 0.0f);
869 glVertex2fv(tilt_ctrl);
872 glDisable(GL_LINE_STIPPLE);
875 /* slider to control pattern tilt */
876 draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
885 static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
886 float marker_pos[2], int act, int width, int height, float zoomx, float zoomy)
888 char str[128] = {0}, state[64] = {0};
889 float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
890 uiStyle *style = U.uistyles.first;
891 int fontid = style->widget.uifont_id;
893 if (!TRACK_VIEW_SELECTED(sc, track))
896 BLF_size(fontid, 11.0f, U.dpi);
897 fontsize = BLF_height_max(fontid);
899 if (marker->flag & MARKER_DISABLED) {
901 UI_ThemeColor(TH_ACT_MARKER);
903 UI_ThemeColorShade(TH_DIS_MARKER, 128);
907 UI_ThemeColor(TH_ACT_MARKER);
909 UI_ThemeColor(TH_SEL_MARKER);
912 if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
913 ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0))
915 dx = marker->search_min[0];
916 dy = marker->search_min[1];
918 else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
919 float pat_min[2], pat_max[2];
921 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
926 pos[0] = (marker_pos[0] + dx) * width;
927 pos[1] = (marker_pos[1] + dy) * height;
930 mul_m4_v3(sc->stabmat, pos);
932 pos[0] = pos[0] * zoomx;
933 pos[1] = pos[1] * zoomy - fontsize;
935 if (marker->flag & MARKER_DISABLED)
936 strcpy(state, "disabled");
937 else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
938 strcpy(state, "estimated");
939 else if (marker->flag & MARKER_TRACKED)
940 strcpy(state, "tracked");
942 strcpy(state, "keyframed");
945 BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
947 BLI_snprintf(str, sizeof(str), "%s", track->name);
949 BLF_position(fontid, pos[0], pos[1], 0.0f);
950 BLF_draw(fontid, str, sizeof(str));
953 if (track->flag & TRACK_HAS_BUNDLE) {
954 BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
955 BLF_position(fontid, pos[0], pos[1], 0.0f);
956 BLF_draw(fontid, str, sizeof(str));
960 if (track->flag & TRACK_LOCKED) {
961 BLF_position(fontid, pos[0], pos[1], 0.0f);
962 BLF_draw(fontid, "locked", 6);
966 static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
968 /* express given coordinates as proportional values */
969 x = -v2d->cur.xmin / (v2d->cur.xmax - v2d->cur.xmin);
970 y = -v2d->cur.ymin / (v2d->cur.ymax - v2d->cur.ymin);
972 /* convert proportional distances to screen coordinates */
973 *regionx = v2d->mask.xmin + x * (v2d->mask.xmax - v2d->mask.xmin);
974 *regiony = v2d->mask.ymin + y * (v2d->mask.ymax - v2d->mask.ymin);
977 static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
978 int width, int height, float zoomx, float zoomy)
981 MovieTracking *tracking = &clip->tracking;
982 ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
983 MovieTrackingTrack *track, *act_track;
984 MovieTrackingMarker *marker;
985 int framenr = ED_space_clip_get_clip_frame_number(sc);
986 int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
987 float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];
989 /* ** find window pixel coordinates of origin ** */
991 /* UI_view2d_to_region_no_clip return integer values, this could
992 * lead to 1px flickering when view is locked to selection during playbeck.
993 * to avoid this flickering, calculate base point in the same way as it happens
994 * in UI_view2d_to_region_no_clip, but do it in floats here */
996 view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
999 glTranslatef(x, y, 0);
1002 glScalef(zoomx, zoomy, 0);
1003 glMultMatrixf(sc->stabmat);
1004 glScalef(width, height, 0);
1006 act_track = BKE_tracking_track_get_active(tracking);
1008 if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1012 track = tracksbase->first;
1014 if ((track->flag & TRACK_HIDDEN) == 0) {
1015 marker = BKE_tracking_marker_get(track, framenr);
1017 if (MARKER_VISIBLE(sc, track, marker))
1021 track = track->next;
1026 marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");
1028 track = tracksbase->first;
1031 if ((track->flag & TRACK_HIDDEN) == 0) {
1032 marker = BKE_tracking_marker_get(track, framenr);
1034 if (MARKER_VISIBLE(sc, track, marker)) {
1035 ED_clip_point_undistorted_pos(sc, marker->pos, fp);
1037 if (track == act_track)
1044 track = track->next;
1049 if (sc->flag & SC_SHOW_TRACK_PATH) {
1050 track = tracksbase->first;
1052 if ((track->flag & TRACK_HIDDEN) == 0)
1053 draw_track_path(sc, clip, track);
1055 track = track->next;
1059 /* markers outline and non-selected areas */
1060 track = tracksbase->first;
1063 if ((track->flag & TRACK_HIDDEN) == 0) {
1064 marker = BKE_tracking_marker_get(track, framenr);
1066 if (MARKER_VISIBLE(sc, track, marker)) {
1067 copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1069 draw_marker_outline(sc, track, marker, cur_pos, width, height);
1070 draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
1071 draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
1072 draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);
1079 track = track->next;
1082 /* selected areas only, so selection wouldn't be overlapped by
1083 * non-selected areas */
1084 track = tracksbase->first;
1087 if ((track->flag & TRACK_HIDDEN) == 0) {
1088 int act = track == act_track;
1089 marker = BKE_tracking_marker_get(track, framenr);
1091 if (MARKER_VISIBLE(sc, track, marker)) {
1093 copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1095 draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
1096 draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
1104 track = track->next;
1107 /* active marker would be displayed on top of everything else */
1109 if ((act_track->flag & TRACK_HIDDEN) == 0) {
1110 marker = BKE_tracking_marker_get(act_track, framenr);
1112 if (MARKER_VISIBLE(sc, act_track, marker)) {
1113 copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
1115 draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
1116 draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
1121 if (sc->flag & SC_SHOW_BUNDLES) {
1122 MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
1123 float pos[4], vec[4], mat[4][4], aspy;
1125 glEnable(GL_POINT_SMOOTH);
1128 aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1129 BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);
1131 track = tracksbase->first;
1133 if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
1134 marker = BKE_tracking_marker_get(track, framenr);
1136 if (MARKER_VISIBLE(sc, track, marker)) {
1138 copy_v4_v4(vec, track->bundle_pos);
1141 mul_v4_m4v4(pos, mat, vec);
1143 pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
1144 pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
1146 BKE_tracking_distort_v2(tracking, pos, npos);
1148 if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
1149 vec[0] = (marker->pos[0] + track->offset[0]) * width;
1150 vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;
1152 sub_v2_v2(vec, npos);
1154 if (len_v2(vec) < 3.0f)
1155 glColor3f(0.0f, 1.0f, 0.0f);
1157 glColor3f(1.0f, 0.0f, 0.0f);
1161 glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
1163 glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
1169 track = track->next;
1173 glDisable(GL_POINT_SMOOTH);
1178 if (sc->flag & SC_SHOW_NAMES) {
1179 /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
1180 track = tracksbase->first;
1183 if ((track->flag & TRACK_HIDDEN) == 0) {
1184 marker = BKE_tracking_marker_get(track, framenr);
1186 if (MARKER_VISIBLE(sc, track, marker)) {
1187 int act = track == act_track;
1189 copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1191 draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);
1198 track = track->next;
1205 MEM_freeN(marker_pos);
1208 static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
1209 int width, int height, float zoomx, float zoomy)
1214 float pos[2], tpos[2], grid[11][11][2];
1215 MovieTracking *tracking = &clip->tracking;
1216 bGPdata *gpd = NULL;
1217 float aspy = 1.0f / tracking->camera.pixel_aspect;
1218 float dx = (float)width / n, dy = (float)height / n * aspy;
1219 float offsx = 0.0f, offsy = 0.0f;
1221 if (sc->mode != SC_MODE_DISTORTION)
1224 if (!tracking->camera.focal)
1227 if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
1230 view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
1233 glTranslatef(x, y, 0);
1234 glScalef(zoomx, zoomy, 0);
1235 glMultMatrixf(sc->stabmat);
1236 glScalef(width, height, 0);
1239 if (sc->flag & SC_SHOW_GRID) {
1240 float val[4][2], idx[4][2];
1241 float min[2], max[2];
1243 for (a = 0; a < 4; a++) {
1245 val[a][a % 2] = FLT_MAX;
1247 val[a][a % 2] = -FLT_MAX;
1251 for (i = 0; i <= n; i++) {
1252 for (j = 0; j <= n; j++) {
1253 if (i == 0 || j == 0 || i == n || j == n) {
1254 BKE_tracking_distort_v2(tracking, pos, tpos);
1256 for (a = 0; a < 4; a++) {
1260 ok = tpos[a % 2] < val[a][a % 2];
1262 ok = tpos[a % 2] > val[a][a % 2];
1265 copy_v2_v2(val[a], tpos);
1279 INIT_MINMAX2(min, max);
1281 for (a = 0; a < 4; a++) {
1282 pos[0] = idx[a][0] * dx;
1283 pos[1] = idx[a][1] * dy;
1285 BKE_tracking_undistort_v2(tracking, pos, tpos);
1287 DO_MINMAX2(tpos, min, max);
1290 copy_v2_v2(pos, min);
1291 dx = (max[0] - min[0]) / n;
1292 dy = (max[1] - min[1]) / n;
1294 for (i = 0; i <= n; i++) {
1295 for (j = 0; j <= n; j++) {
1296 BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
1298 grid[i][j][0] /= width;
1299 grid[i][j][1] /= height * aspy;
1308 glColor3f(1.0f, 0.0f, 0.0f);
1310 for (i = 0; i <= n; i++) {
1311 glBegin(GL_LINE_STRIP);
1312 for (j = 0; j <= n; j++) {
1313 glVertex2fv(grid[i][j]);
1318 for (j = 0; j <= n; j++) {
1319 glBegin(GL_LINE_STRIP);
1320 for (i = 0; i <= n; i++) {
1321 glVertex2fv(grid[i][j]);
1327 if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
1328 MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
1331 int framenr = ED_space_clip_get_clip_frame_number(sc);
1332 MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
1334 offsx = marker->pos[0];
1335 offsy = marker->pos[1];
1345 if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
1346 bGPDlayer *layer = gpd->layers.first;
1349 bGPDframe *frame = layer->frames.first;
1351 if (layer->flag & GP_LAYER_HIDE) {
1352 layer = layer->next;
1356 glColor4fv(layer->color);
1357 glLineWidth(layer->thickness);
1358 glPointSize((float)(layer->thickness + 2));
1361 bGPDstroke *stroke = frame->strokes.first;
1364 if (stroke->flag & GP_STROKE_2DSPACE) {
1365 if (stroke->totpoints > 1) {
1366 glBegin(GL_LINE_STRIP);
1367 for (i = 0; i < stroke->totpoints - 1; i++) {
1368 float npos[2], dpos[2], len;
1371 pos[0] = (stroke->points[i].x + offsx) * width;
1372 pos[1] = (stroke->points[i].y + offsy) * height * aspy;
1374 npos[0] = (stroke->points[i + 1].x + offsx) * width;
1375 npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;
1377 len = len_v2v2(pos, npos);
1378 steps = ceil(len / 5.0f);
1380 /* we want to distort only long straight lines */
1381 if (stroke->totpoints == 2) {
1382 BKE_tracking_undistort_v2(tracking, pos, pos);
1383 BKE_tracking_undistort_v2(tracking, npos, npos);
1386 sub_v2_v2v2(dpos, npos, pos);
1387 mul_v2_fl(dpos, 1.0f / steps);
1389 for (j = 0; j <= steps; j++) {
1390 BKE_tracking_distort_v2(tracking, pos, tpos);
1391 glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));
1393 add_v2_v2(pos, dpos);
1398 else if (stroke->totpoints == 1) {
1400 glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
1405 stroke = stroke->next;
1408 frame = frame->next;
1411 layer = layer->next;
1421 void clip_draw_main(const bContext *C, ARegion *ar)
1423 wmWindow *win = CTX_wm_window(C);
1424 SpaceClip *sc = CTX_wm_space_clip(C);
1425 MovieClip *clip = ED_space_clip_get_clip(sc);
1426 Scene *scene = CTX_data_scene(C);
1431 ED_space_clip_get_size(C, &width, &height);
1432 ED_space_clip_get_zoom(C, &zoomx, &zoomy);
1434 /* if no clip, nothing to do */
1436 ED_region_grid_draw(ar, zoomx, zoomy);
1440 if (sc->flag & SC_SHOW_STABLE) {
1441 float smat[4][4], ismat[4][4];
1443 ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle);
1447 float aspect = clip->tracking.camera.pixel_aspect;
1449 if (width != ibuf->x)
1450 mul_v2_v2fl(loc, sc->loc, (float)width / ibuf->x);
1452 copy_v2_v2(loc, sc->loc);
1454 BKE_tracking_stabilization_data_to_mat4(width, height, aspect, loc, sc->scale, sc->angle, sc->stabmat);
1457 smat[0][0] = 1.0f / width;
1458 smat[1][1] = 1.0f / height;
1459 invert_m4_m4(ismat, smat);
1461 mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL);
1465 ibuf = ED_space_clip_get_buffer(sc);
1469 unit_m4(sc->stabmat);
1470 unit_m4(sc->unistabmat);
1474 draw_movieclip_buffer(win, sc, ar, ibuf, width, height, zoomx, zoomy);
1475 IMB_freeImBuf(ibuf);
1478 ED_region_grid_draw(ar, zoomx, zoomy);
1481 if (width && height) {
1482 draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy);
1483 draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
1486 draw_movieclip_cache(sc, ar, clip, scene);
1487 draw_movieclip_notes(sc, ar);
1490 /* draw grease pencil */
1491 void clip_draw_grease_pencil(bContext *C, int onlyv2d)
1493 SpaceClip *sc = CTX_wm_space_clip(C);
1494 MovieClip *clip = ED_space_clip_get_clip(sc);
1500 /* if manual calibration is used then grease pencil data is already
1501 * drawed in draw_distortion */
1502 if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) {
1504 glMultMatrixf(sc->unistabmat);
1506 if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
1507 MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
1510 int framenr = ED_space_clip_get_clip_frame_number(sc);
1511 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1513 glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
1517 draw_gpencil_2dimage(C);
1523 draw_gpencil_view2d(C, 0);