Internal refactoring of tracking module, should be no functional changes
[blender.git] / source / blender / editors / space_clip / clip_editor.c
index 099c3c7532c555f691b89552e27d2ceb91e54aa5..275cb782bbd321c2738c17928d6c4b507b809b65 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "BKE_main.h"
+#include "BKE_mask.h"
 #include "BKE_movieclip.h"
 #include "BKE_context.h"
 #include "BKE_tracking.h"
+
+#include "DNA_mask_types.h"
 #include "DNA_object_types.h"  /* SELECT */
 
 #include "BLI_utildefines.h"
@@ -60,6 +63,8 @@
 
 #include "clip_intern.h"       // own include
 
+/* ******** operactor poll functions ******** */
+
 int ED_space_clip_poll(bContext *C)
 {
        SpaceClip *sc = CTX_wm_space_clip(C);
@@ -70,6 +75,55 @@ int ED_space_clip_poll(bContext *C)
        return FALSE;
 }
 
+int ED_space_clip_view_clip_poll(bContext *C)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+
+       if (sc && sc->clip) {
+               return sc->view == SC_VIEW_CLIP;
+       }
+
+       return FALSE;
+}
+
+int ED_space_clip_tracking_poll(bContext *C)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+
+       if (sc && sc->clip)
+               return ED_space_clip_show_trackedit(sc);
+
+       return FALSE;
+}
+
+int ED_space_clip_maskedit_poll(bContext *C)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+
+       if (sc && sc->clip) {
+               return ED_space_clip_show_maskedit(sc);
+       }
+
+       return FALSE;
+}
+
+int ED_space_clip_maskedit_mask_poll(bContext *C)
+{
+       if (ED_space_clip_maskedit_poll(C)) {
+               MovieClip *clip = CTX_data_edit_movieclip(C);
+
+               if (clip) {
+                       SpaceClip *sc= CTX_wm_space_clip(C);
+
+                       return sc->mask != NULL;
+               }
+       }
+
+       return FALSE;
+}
+
+/* ******** editing functions ******** */
+
 void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip)
 {
        MovieClip *old_clip;
@@ -80,10 +134,10 @@ void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *c
        old_clip = sc->clip;
        sc->clip = clip;
 
-       if (sc->clip && sc->clip->id.us==0)
+       if (sc->clip && sc->clip->id.us == 0)
                sc->clip->id.us = 1;
 
-       if (screen) {
+       if (screen && sc->view == SC_VIEW_CLIP) {
                ScrArea *area;
                SpaceLink *sl;
 
@@ -92,7 +146,7 @@ void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *c
                                if (sl->spacetype == SPACE_CLIP) {
                                        SpaceClip *cur_sc = (SpaceClip *) sl;
 
-                                       if (cur_sc != sc) {
+                                       if (cur_sc != sc && cur_sc->view != SC_VIEW_CLIP) {
                                                if (cur_sc->clip == old_clip || cur_sc->clip == NULL) {
                                                        cur_sc->clip = clip;
                                                }
@@ -103,7 +157,7 @@ void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *c
        }
 
        if (C)
-               WM_event_add_notifier(C, NC_MOVIECLIP|NA_SELECTED, sc->clip);
+               WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip);
 }
 
 MovieClip *ED_space_clip(SpaceClip *sc)
@@ -111,6 +165,11 @@ MovieClip *ED_space_clip(SpaceClip *sc)
        return sc->clip;
 }
 
+Mask *ED_space_clip_mask(SpaceClip *sc)
+{
+       return sc->mask;
+}
+
 ImBuf *ED_space_clip_get_buffer(SpaceClip *sc)
 {
        if (sc->clip) {
@@ -155,14 +214,59 @@ void ED_space_clip_size(SpaceClip *sc, int *width, int *height)
        }
 }
 
+void ED_space_clip_mask_size(SpaceClip *sc, int *width, int *height)
+{
+       /* quite the same as ED_space_clip_size, but it also runs aspect correction on output resolution
+        * this is needed because mask should be rasterized with exactly the same resolution as
+        * currently displaying frame and it doesn't have access to aspect correction currently
+        * used for display. (sergey)
+        */
+
+       if (!sc->mask) {
+               *width = 0;
+               *height = 0;
+       } else {
+               float aspx, aspy;
+
+               ED_space_clip_size(sc, width, height);
+               ED_space_clip_aspect(sc, &aspx, &aspy);
+
+               *width *= aspx;
+               *height *= aspy;
+       }
+}
+
+void ED_space_clip_mask_aspect(SpaceClip *sc, float *aspx, float *aspy)
+{
+       int w, h;
+
+       ED_space_clip_aspect(sc, aspx, aspy);
+       ED_space_clip_size(sc, &w, &h);
+
+       /* now this is not accounted for! */
+#if 0
+       *aspx *= (float)w;
+       *aspy *= (float)h;
+#endif
+
+       if (*aspx < *aspy) {
+               *aspy= *aspy / *aspx;
+               *aspx= 1.0f;
+       }
+       else {
+               *aspx= *aspx / *aspy;
+               *aspy= 1.0f;
+       }
+}
+
 void ED_space_clip_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy)
 {
        int width, height;
 
        ED_space_clip_size(sc, &width, &height);
 
-       *zoomx = (float)(ar->winrct.xmax - ar->winrct.xmin + 1)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
-       *zoomy = (float)(ar->winrct.ymax - ar->winrct.ymin + 1)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
+       *zoomx = (float)(ar->winrct.xmax - ar->winrct.xmin + 1) / (float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin) * width);
+       *zoomy = (float)(ar->winrct.ymax - ar->winrct.ymin + 1) / (float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin) * height);
 }
 
 void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy)
@@ -175,6 +279,33 @@ void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy)
                *aspx = *aspy = 1.0f;
 }
 
+void ED_space_clip_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy)
+{
+       int w, h;
+
+       /* most of tools does not require aspect to be returned with dimensions correction
+        * due to they're invariant to this stuff, but some transformation tools like rotation
+        * should be aware of aspect correction caused by different resolution in different
+        * directions.
+        * mainly this is sued for transformation stuff
+        */
+
+       ED_space_clip_aspect(sc, aspx, aspy);
+       ED_space_clip_size(sc, &w, &h);
+
+       *aspx *= (float)w;
+       *aspy *= (float)h;
+
+       if (*aspx < *aspy) {
+               *aspy= *aspy / *aspx;
+               *aspx= 1.0f;
+       }
+       else {
+               *aspx= *aspx / *aspy;
+               *aspy= 1.0f;
+       }
+}
+
 void ED_clip_update_frame(const Main *mainp, int cfra)
 {
        wmWindowManager *wm;
@@ -198,12 +329,20 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
        }
 }
 
+/* return current frame number in clip space */
+int ED_space_clip_clip_framenr(SpaceClip *sc)
+{
+       MovieClip *clip = ED_space_clip(sc);
+
+       return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
+}
+
 static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
 {
        MovieClip *clip = ED_space_clip(sc);
        MovieTrackingTrack *track;
        int width, height, ok = FALSE;
-       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
+       ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
 
        INIT_MINMAX2(min, max);
 
@@ -212,7 +351,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
        track = tracksbase->first;
        while (track) {
                if (TRACK_VIEW_SELECTED(sc, track)) {
-                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
+                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, sc->user.framenr);
 
                        if (marker) {
                                float pos[3];
@@ -258,7 +397,8 @@ int ED_clip_view_selection(SpaceClip *sc, ARegion *ar, int fit)
                return FALSE;
 
        /* center view */
-       clip_view_center_to_point(sc, (max[0]+min[0])/(2*frame_width), (max[1]+min[1])/(2*frame_height));
+       clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width),
+                                 (max[1] + min[1]) / (2 * frame_height));
 
        w = max[0] - min[0];
        h = max[1] - min[1];
@@ -278,16 +418,16 @@ int ED_clip_view_selection(SpaceClip *sc, ARegion *ar, int fit)
 
                newzoom = 1.0f / power_of_2(1.0f / MIN2(zoomx, zoomy));
 
-               if (fit || sc->zoom>newzoom)
+               if (fit || sc->zoom > newzoom)
                        sc->zoom = newzoom;
        }
 
        return TRUE;
 }
 
-void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2])
+void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2])
 {
-       copy_v2_v2(nco, co);
+       copy_v2_v2(r_co, co);
 
        if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
                MovieClip *clip = ED_space_clip(sc);
@@ -296,13 +436,13 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, float co[2], float nco[2])
 
                ED_space_clip_size(sc, &width, &height);
 
-               nco[0] *= width;
-               nco[1] *= height * aspy;
+               r_co[0] *= width;
+               r_co[1] *= height * aspy;
 
-               BKE_tracking_invert_intrinsics(&clip->tracking, nco, nco);
+               BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co);
 
-               nco[0] /= width;
-               nco[1] /= height * aspy;
+               r_co[0] /= width;
+               r_co[1] /= height * aspy;
        }
 }
 
@@ -311,7 +451,7 @@ void ED_clip_point_stable_pos(bContext *C, float x, float y, float *xr, float *y
        ARegion *ar = CTX_wm_region(C);
        SpaceClip *sc = CTX_wm_space_clip(C);
        int sx, sy, width, height;
-       float zoomx, zoomy, pos[3] = {0.0f, 0.0f, 0.0f}, imat[4][4];
+       float zoomx, zoomy, pos[3], imat[4][4];
 
        ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
        ED_space_clip_size(sc, &width, &height);
@@ -320,6 +460,7 @@ void ED_clip_point_stable_pos(bContext *C, float x, float y, float *xr, float *y
 
        pos[0] = (x - sx) / zoomx;
        pos[1] = (y - sy) / zoomy;
+       pos[2] = 0.0f;
 
        invert_m4_m4(imat, sc->stabmat);
        mul_v3_m4v3(pos, imat, pos);
@@ -333,13 +474,38 @@ void ED_clip_point_stable_pos(bContext *C, float x, float y, float *xr, float *y
                float aspy = 1.0f / tracking->camera.pixel_aspect;
                float tmp[2] = {*xr * width, *yr * height * aspy};
 
-               BKE_tracking_apply_intrinsics(tracking, tmp, tmp);
+               BKE_tracking_distort_v2(tracking, tmp, tmp);
 
                *xr = tmp[0] / width;
                *yr = tmp[1] / (height * aspy);
        }
 }
 
+/**
+ * \brief the reverse of ED_clip_point_stable_pos(), gets the marker region coords.
+ * better name here? view_to_track / track_to_view or so?
+ */
+void ED_clip_point_stable_pos__reverse(SpaceClip *sc, ARegion *ar, const float co[2], float r_co[2])
+{
+       float zoomx, zoomy;
+       float pos[3];
+       int width, height;
+       int sx, sy;
+
+       UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+       ED_space_clip_size(sc, &width, &height);
+       ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
+
+       ED_clip_point_undistorted_pos(sc, co, pos);
+       pos[2] = 0.0f;
+
+       /* untested */
+       mul_v3_m4v3(pos, sc->stabmat, pos);
+
+       r_co[0] = (pos[0] * width  * zoomx) + (float)sx;
+       r_co[1] = (pos[1] * height * zoomy) + (float)sy;
+}
+
 void ED_clip_mouse_pos(bContext *C, wmEvent *event, float co[2])
 {
        ED_clip_point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]);
@@ -355,7 +521,10 @@ typedef struct SpaceClipDrawContext {
        struct ImBuf *texture_ibuf;     /* image buffer for which texture was created */
        int image_width, image_height;  /* image width and height for which texture was created */
        unsigned last_texture;          /* ID of previously used texture, so it'll be restored after clip drawing */
-       int framenr;
+
+       /* fields to check if cache is still valid */
+       int framenr, start_frame, frame_offset;
+       short render_size, render_flag;
 } SpaceClipDrawContext;
 
 int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
@@ -369,7 +538,12 @@ int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
 
        if (!context->support_checked) {
                context->support_checked = TRUE;
-               context->buffers_supported = GPU_non_power_of_two_support();
+               if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+                       context->buffers_supported = FALSE;
+               }
+               else {
+                       context->buffers_supported = GPU_non_power_of_two_support();
+               }
        }
 
        return context->buffers_supported;
@@ -388,19 +562,18 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
         * so not changed image buffer pointer means unchanged image content */
        need_rebind |= context->texture_ibuf != ibuf;
        need_rebind |= context->framenr != sc->user.framenr;
+       need_rebind |= context->render_size != sc->user.render_size;
+       need_rebind |= context->render_flag != sc->user.render_flag;
+       need_rebind |= context->start_frame != clip->start_frame;
+       need_rebind |= context->frame_offset != clip->frame_offset;
 
        if (need_rebind) {
                int width = ibuf->x, height = ibuf->y;
-               float *frect = NULL, *fscalerect = NULL;
-               unsigned int *rect = NULL, *scalerect = NULL;
                int need_recreate = 0;
 
                if (width > GL_MAX_TEXTURE_SIZE || height > GL_MAX_TEXTURE_SIZE)
                        return 0;
 
-               rect = ibuf->rect;
-               frect = ibuf->rect_float;
-
                /* if image resolution changed (e.g. switched to proxy display) texture need to be recreated */
                need_recreate = context->image_width != ibuf->x || context->image_height != ibuf->y;
 
@@ -409,35 +582,6 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
                        context->texture_allocated = 0;
                }
 
-#if 0
-               /* disabled for now because current tracking users have got NPOT textures
-                * working smoothly on their computers and forcing re-scaling during playback
-                * slows down playback a lot */
-
-               /* if videocard doesn't support NPOT textures, need to do rescaling */
-               if (!GPU_non_power_of_two_support()) {
-                       if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) {
-                               width = power_of_2_max_i(width);
-                               height = power_of_2_max_i(height);
-
-                               if (ibuf->x != width || ibuf->y != height) {
-                                       if (frect) {
-                                               fscalerect= MEM_mallocN(width*width*sizeof(*fscalerect)*4, "fscalerect");
-                                               gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float, width, height, GL_FLOAT, fscalerect);
-
-                                               frect = fscalerect;
-                                       }
-                                       else {
-                                               scalerect= MEM_mallocN(width*height*sizeof(*scalerect), "scalerect");
-                                               gluScaleImage(GL_RGBA, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect, width, height, GL_UNSIGNED_BYTE, scalerect);
-
-                                               rect = scalerect;
-                                       }
-                               }
-                       }
-               }
-#endif
-
                if (need_recreate || !context->texture_allocated) {
                        /* texture doesn't exist yet or need to be re-allocated because of changed dimensions */
                        int filter = GL_LINEAR;
@@ -462,10 +606,13 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
                        glBindTexture(GL_TEXTURE_2D, context->texture);
                }
 
-               if (frect)
-                       glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA16,  width, height, 0, GL_RGBA, GL_FLOAT, frect);
-               else
-                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               if (ibuf->rect_float) {
+                       if (ibuf->rect == NULL)
+                               IMB_rect_from_float(ibuf);
+               }
+
+               if (ibuf->rect)
+                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
 
                /* store settings */
                context->texture_allocated = 1;
@@ -473,11 +620,10 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
                context->image_width = ibuf->x;
                context->image_height = ibuf->y;
                context->framenr = sc->user.framenr;
-
-               if (fscalerect)
-                       MEM_freeN(fscalerect);
-               if (scalerect)
-                       MEM_freeN(scalerect);
+               context->render_size = sc->user.render_size;
+               context->render_flag = sc->user.render_flag;
+               context->start_frame = clip->start_frame;
+               context->frame_offset = clip->frame_offset;
        }
        else {
                /* displaying exactly the same image which was loaded t oa texture,
@@ -487,7 +633,7 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
 
        glEnable(GL_TEXTURE_2D);
 
-       return 1;
+       return TRUE;
 }
 
 void ED_space_clip_unload_movieclip_buffer(SpaceClip *sc)
@@ -508,3 +654,36 @@ void ED_space_clip_free_texture_buffer(SpaceClip *sc)
                MEM_freeN(context);
        }
 }
+
+/* ******** masking editing related functions ******** */
+
+int ED_space_clip_show_trackedit(SpaceClip *sc)
+{
+       if (sc) {
+               return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION);
+       }
+
+       return FALSE;
+}
+
+int ED_space_clip_show_maskedit(SpaceClip *sc)
+{
+       if (sc) {
+               return sc->mode == SC_MODE_MASKEDIT;
+       }
+
+       return FALSE;
+}
+
+void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
+{
+       sc->mask = mask;
+
+       if (sc->mask && sc->mask->id.us==0) {
+               sc->clip->id.us = 1;
+       }
+
+       if (C) {
+               WM_event_add_notifier(C, NC_MASK|NA_SELECTED, mask);
+       }
+}