Merging r47624 through r47661 from trunk into soc-2011-tomato
[blender.git] / source / blender / editors / space_clip / tracking_ops.c
index 56f50d41a128e6cb018c435a1ccfdef7d0085982..f6e9622f0a53b071d18925ed7c5407f0f474b761 100644 (file)
@@ -42,6 +42,7 @@
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_rect.h"
+#include "BLI_lasso.h"
 #include "BLI_blenlib.h"
 
 #include "BKE_main.h"
@@ -78,6 +79,8 @@
 
 #include "clip_intern.h"       // own include
 
+static float dist_to_crns(float co[2], float pos[2], float crns[4][2]);
+
 /********************** add marker operator *********************/
 
 static void add_marker(SpaceClip *sc, float x, float y)
@@ -87,10 +90,11 @@ static void add_marker(SpaceClip *sc, float x, float y)
        ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
        int width, height;
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        ED_space_clip_size(sc, &width, &height);
 
-       track = BKE_tracking_add_track(tracking, tracksbase, x, y, sc->user.framenr, width, height);
+       track = BKE_tracking_add_track(tracking, tracksbase, x, y, framenr, width, height);
 
        BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, 0);
 
@@ -105,6 +109,7 @@ static int add_marker_exec(bContext *C, wmOperator *op)
        int width, height;
 
        ED_space_clip_size(sc, &width, &height);
+
        if (!width || !height)
                return OPERATOR_CANCELLED;
 
@@ -116,7 +121,7 @@ static int add_marker_exec(bContext *C, wmOperator *op)
        sc->xlockof = 0;
        sc->ylockof = 0;
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -142,10 +147,10 @@ void CLIP_OT_add_marker(wmOperatorType *ot)
        /* api callbacks */
        ot->invoke = add_marker_invoke;
        ot->exec = add_marker_exec;
-       ot->poll = ED_space_clip_tracking_size_poll;
+       ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX,
@@ -190,7 +195,7 @@ void CLIP_OT_delete_track(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** delete marker operator *********************/
@@ -201,7 +206,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
        MovieClip *clip = ED_space_clip(sc);
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track = tracksbase->first, *next;
-       int framenr = sc->user.framenr;
+       int framenr = ED_space_clip_clip_framenr(sc);
        int has_selection = 0;
 
        while (track) {
@@ -211,7 +216,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
                        MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr);
 
                        if (marker) {
-                               has_selection |= track->markersnr>1;
+                               has_selection |= track->markersnr > 1;
 
                                clip_delete_marker(C, clip, tracksbase, track, marker);
                        }
@@ -241,7 +246,7 @@ void CLIP_OT_delete_marker(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** slide marker operator *********************/
@@ -257,19 +262,21 @@ typedef struct {
 
        int mval[2];
        int width, height;
-       float *min, *max, *pos, *offset;
-       float smin[2], smax[2], spos[2], soff[2];
+       float *min, *max, *pos, *offset, (*corners)[2];
+       float smin[2], smax[2], spos[2], soff[2], scorners[4][2];
        float (*smarkers)[2];
 
-       int lock, accurate;
+       int lock, accurate, scale;
 } SlideMarkerData;
 
 static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track,
-                       MovieTrackingMarker *marker, wmEvent *event, int area, int action, int width, int height)
+                                                 MovieTrackingMarker *marker, wmEvent *event,
+                                                                                                int area, int corner, int action, int width, int height)
 {
        SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data");
+       int framenr = ED_space_clip_clip_framenr(sc);
 
-       marker = BKE_tracking_ensure_marker(track, sc->user.framenr);
+       marker = BKE_tracking_ensure_marker(track, framenr);
 
        data->area = area;
        data->action = action;
@@ -284,10 +291,9 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra
        }
        else if (area == TRACK_AREA_PAT) {
                if (action == SLIDE_ACTION_SIZE) {
-                       data->min = track->pat_min;
-                       data->max = track->pat_max;
+                       data->corners = marker->pattern_corners;
                }
-               else {
+               else if (action == SLIDE_ACTION_OFFSET) {
                        int a;
 
                        data->pos = marker->pos;
@@ -299,15 +305,28 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra
                        for (a = 0; a < track->markersnr; a++)
                                copy_v2_v2(data->smarkers[a], track->markers[a].pos);
                }
+               else if (action == SLIDE_ACTION_POS) {
+                       data->corners = marker->pattern_corners;
+                       data->pos = marker->pattern_corners[corner];
+
+                       copy_v2_v2(data->spos, data->pos);
+               }
        }
        else if (area == TRACK_AREA_SEARCH) {
-               data->min = track->search_min;
-               data->max = track->search_max;
+               data->min = marker->search_min;
+               data->max = marker->search_max;
        }
 
-       if (area == TRACK_AREA_SEARCH || (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET)) {
-               copy_v2_v2(data->smin, data->min);
-               copy_v2_v2(data->smax, data->max);
+       if ((area == TRACK_AREA_SEARCH) ||
+               (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET))
+       {
+               if (data->corners) {
+                       memcpy(data->scorners, data->corners, sizeof(data->scorners));
+               }
+               else {
+                       copy_v2_v2(data->smin, data->min);
+                       copy_v2_v2(data->smax, data->max);
+               }
        }
 
        data->mval[0] = event->mval[0];
@@ -322,9 +341,7 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra
        return data;
 }
 
-/* corner = 0: right-bottom corner,
- * corner = 1: left-top corner */
-static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
+static int mouse_on_corner(SpaceClip *sc, MovieTrackingMarker *marker,
                            int area, float co[2], int corner, int width, int height)
 {
        int inside = 0;
@@ -333,12 +350,11 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
        float crn[2], dx, dy, tdx, tdy;
 
        if (area == TRACK_AREA_SEARCH) {
-               copy_v2_v2(min, track->search_min);
-               copy_v2_v2(max, track->search_max);
+               copy_v2_v2(min, marker->search_min);
+               copy_v2_v2(max, marker->search_max);
        }
        else {
-               copy_v2_v2(min, track->pat_min);
-               copy_v2_v2(max, track->pat_max);
+               BKE_tracking_marker_pattern_minmax(marker, min, max);
        }
 
        dx = size / width / sc->zoom;
@@ -357,8 +373,8 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
                inside = co[0] >= crn[0] - dx && co[0] <= crn[0] + tdx && co[1] >= crn[1] - tdy && co[1] <= crn[1] + dy;
        }
        else {
-               crn[0] = marker->pos[0]+min[0];
-               crn[1] = marker->pos[1]+max[1];
+               crn[0] = marker->pos[0] + min[0];
+               crn[1] = marker->pos[1] + max[1];
 
                inside = co[0] >= crn[0] - dx && co[0] <= crn[0] + dx && co[1] >= crn[1] - dy && co[1] <= crn[1] + dy;
        }
@@ -366,22 +382,95 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
        return inside;
 }
 
+static int get_mouse_pattern_corner(SpaceClip *sc, MovieTrackingMarker *marker, float co[2], int width, int height)
+{
+       int i, next;
+       float len = FLT_MAX, dx, dy;
+
+       for (i = 0; i < 4; i++) {
+               float cur_len;
+
+               next = (i + 1) % 4;
+
+               cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
+
+               len = MIN2(cur_len, len);
+       }
+
+       dx = 6.0f / width / sc->zoom;
+       dy = 6.0f / height / sc->zoom;
+
+       dx = MIN2(dx * 2.0f / 3.0f, len / 6.0f);
+       dy = MIN2(dy * 2.0f / 3.0f, len * width / height / 6.0f);
+
+       for (i = 0; i < 4; i++) {
+               float crn[2];
+               int inside;
+
+               add_v2_v2v2(crn, marker->pattern_corners[i], marker->pos);
+
+               inside = IN_RANGE_INCL(co[0], crn[0] - dx, crn[0] + dx) &&
+                        IN_RANGE_INCL(co[1], crn[1] - dy, crn[1] + dy);
+
+               if (inside)
+                       return i;
+       }
+
+       return -1;
+}
+
 static int mouse_on_offset(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
-                       float co[2], int width, int height)
+                           float co[2], int width, int height)
 {
        float pos[2], dx, dy;
+       float pat_min[2], pat_max[2];
+
+       BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
 
        add_v2_v2v2(pos, marker->pos, track->offset);
 
        dx = 12.0f / width / sc->zoom;
-       dy = 12.0f / height /sc->zoom;
+       dy = 12.0f / height / sc->zoom;
 
-       dx = MIN2(dx, (track->pat_max[0] - track->pat_min[0]) / 2.0f);
-       dy = MIN2(dy, (track->pat_max[1] - track->pat_min[1]) / 2.0f);
+       dx = MIN2(dx, (pat_max[0] - pat_min[0]) / 2.0f);
+       dy = MIN2(dy, (pat_max[1] - pat_min[1]) / 2.0f);
 
        return co[0] >= pos[0] - dx && co[0] <= pos[0] + dx && co[1] >= pos[1] - dy && co[1] <= pos[1] + dy;
 }
 
+static int slide_check_corners(float (*corners)[2])
+{
+       int i, next, prev;
+       float cross = 0.0f;
+       float p[2] = {0.0f, 0.0f};
+
+       if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3]))
+               return FALSE;
+
+       for (i = 0; i < 4; i++) {
+               float v1[2], v2[2], cur_cross;
+
+               next = (i + 1) % 4;
+               prev = (4 + i - 1) % 4;
+
+               sub_v2_v2v2(v1, corners[i], corners[prev]);
+               sub_v2_v2v2(v2, corners[next], corners[i]);
+
+               cur_cross = cross_v2v2(v1, v2);
+
+               if (fabsf(cur_cross) > FLT_EPSILON) {
+                       if (cross == 0.0f) {
+                               cross = cur_cross;
+                       }
+                       else if (cross * cur_cross < 0.0f) {
+                               return FALSE;
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
 static void hide_cursor(bContext *C)
 {
        wmWindow *win = CTX_wm_window(C);
@@ -405,6 +494,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
        float co[2];
        void *customdata = NULL;
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        ED_space_clip_size(sc, &width, &height);
 
@@ -416,26 +506,48 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
        track = tracksbase->first;
        while (track) {
                if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
-                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
+                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
 
                        if ((marker->flag & MARKER_DISABLED) == 0) {
-                               if (!customdata)
+                               if (!customdata) {
                                        if (mouse_on_offset(sc, track, marker, co, width, height))
-                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, SLIDE_ACTION_POS, width, height);
+                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, 0,
+                                                                                     SLIDE_ACTION_POS, width, height);
+                               }
 
                                if (sc->flag & SC_SHOW_MARKER_SEARCH) {
-                                       if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 1, width, height))
-                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, SLIDE_ACTION_OFFSET, width, height);
-                                       else if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 0, width, height))
-                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, SLIDE_ACTION_SIZE, width, height);
+                                       if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, width, height)) {
+                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0,
+                                                                                     SLIDE_ACTION_OFFSET, width, height);
+                                       }
+                                       else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, width, height)) {
+                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0,
+                                                                                     SLIDE_ACTION_SIZE, width, height);
+                                       }
                                }
 
                                if (!customdata && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
-                                       if (mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 1,  width, height))
-                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, SLIDE_ACTION_OFFSET, width, height);
-
-                                       if (!customdata && mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 0, width, height))
-                                               customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, SLIDE_ACTION_SIZE, width, height);
+                                       /* XXX: need to be real check if affine tracking is enabled, but for now not
+                                        *      sure how to do this, so assume affine tracker is always enabled */
+                                       if (TRUE) {
+                                               int corner = get_mouse_pattern_corner(sc, marker, co, width, height);
+
+                                               if (corner != -1) {
+                                                       customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, corner,
+                                                                                             SLIDE_ACTION_POS, width, height);
+                                               }
+                                       }
+                                       else {
+                                               if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1,  width, height)) {
+                                                       customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0,
+                                                                                             SLIDE_ACTION_OFFSET, width, height);
+                                               }
+
+                                               if (!customdata && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, width, height)) {
+                                                       customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0,
+                                                                                             SLIDE_ACTION_SIZE, width, height);
+                                               }
+                                       }
                                }
 
                                if (customdata)
@@ -465,7 +577,7 @@ static int slide_marker_invoke(bContext *C, wmOperator *op, wmEvent *event)
                hide_cursor(C);
                WM_event_add_modal_handler(C, op);
 
-               WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
                return OPERATOR_RUNNING_MODAL;
        }
@@ -483,14 +595,21 @@ static void cancel_mouse_slide(SlideMarkerData *data)
                        copy_v2_v2(data->pos, data->spos);
        }
        else {
-               if (data->action == SLIDE_ACTION_SIZE) {
-                       copy_v2_v2(data->min, data->smin);
-                       copy_v2_v2(data->max, data->smax);
+               if ((data->action == SLIDE_ACTION_SIZE) ||
+                   (data->action == SLIDE_ACTION_POS && data->area == TRACK_AREA_PAT))
+               {
+                       if (data->corners) {
+                               memcpy(data->corners, data->scorners, sizeof(data->scorners));
+                       }
+                       else {
+                               copy_v2_v2(data->min, data->smin);
+                               copy_v2_v2(data->max, data->smax);
+                       }
                }
                else {
                        int a;
 
-                       for (a = 0; a<data->track->markersnr; a++)
+                       for (a = 0; a < data->track->markersnr; a++)
                                copy_v2_v2(data->track->markers[a].pos, data->smarkers[a]);
 
                        copy_v2_v2(data->offset, data->soff);
@@ -521,14 +640,18 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event)
                                if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY))
                                        data->lock = event->val == KM_RELEASE;
 
+                       if (data->action == SLIDE_ACTION_POS)
+                               if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY))
+                                       data->scale = event->val == KM_PRESS;
+
                        if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
                                data->accurate = event->val == KM_PRESS;
 
                        /* no break! update area size */
 
                case MOUSEMOVE:
-                       mdelta[0] = event->mval[0]-data->mval[0];
-                       mdelta[1] = event->mval[1]-data->mval[1];
+                       mdelta[0] = event->mval[0] - data->mval[0];
+                       mdelta[1] = event->mval[1] - data->mval[1];
 
                        dx = mdelta[0] / data->width / sc->zoom;
 
@@ -550,27 +673,40 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event)
                                else {
                                        data->pos[0] = data->spos[0] + dx;
                                        data->pos[1] = data->spos[1] + dy;
-
-                                       data->marker->flag &= ~MARKER_TRACKED;
                                }
 
-                               WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+                               WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
                                DAG_id_tag_update(&sc->clip->id, 0);
                        }
                        else {
                                if (data->action == SLIDE_ACTION_SIZE) {
-                                       data->min[0] = data->smin[0] - dx;
-                                       data->max[0] = data->smax[0] + dx;
+                                       if (data->corners) {
+                                               data->corners[0][0] = data->scorners[0][0] - dx;
+                                               data->corners[0][1] = data->scorners[0][1] + dy;
+
+                                               data->corners[1][0] = data->scorners[1][0] + dx;
+                                               data->corners[1][1] = data->scorners[1][1] + dy;
+
+                                               data->corners[2][0] = data->scorners[2][0] + dx;
+                                               data->corners[2][1] = data->scorners[2][1] - dy;
+
+                                               data->corners[3][0] = data->scorners[3][0] - dx;
+                                               data->corners[3][1] = data->scorners[3][1] - dy;
+                                       }
+                                       else {
+                                               data->min[0] = data->smin[0] - dx;
+                                               data->max[0] = data->smax[0] + dx;
 
-                                       data->min[1] = data->smin[1] + dy;
-                                       data->max[1] = data->smax[1] - dy;
+                                               data->min[1] = data->smin[1] + dy;
+                                               data->max[1] = data->smax[1] - dy;
+                                       }
 
                                        if (data->area == TRACK_AREA_SEARCH)
-                                               BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_DIM);
+                                               BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_DIM);
                                        else
-                                               BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM);
+                                               BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM);
                                }
-                               else {
+                               else if (data->action == SLIDE_ACTION_OFFSET) {
                                        float d[2] = {dx, dy};
 
                                        if (data->area == TRACK_AREA_SEARCH) {
@@ -580,18 +716,51 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event)
                                        else {
                                                int a;
 
-                                               for (a = 0; a<data->track->markersnr; a++)
+                                               for (a = 0; a < data->track->markersnr; a++)
                                                        add_v2_v2v2(data->track->markers[a].pos, data->smarkers[a], d);
 
                                                sub_v2_v2v2(data->offset, data->soff, d);
                                        }
 
                                        if (data->area == TRACK_AREA_SEARCH)
-                                               BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_POS);
+                                               BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_POS);
+                               }
+                               else if (data->action == SLIDE_ACTION_POS) {
+                                       if (data->scale) {
+                                               float scale = 1.0f + 10.0f * (dx - dy);
+
+                                               if (scale > 0.0f) {
+                                                       int a;
+
+                                                       for (a = 0; a < 4; a++) {
+                                                               mul_v2_v2fl(data->corners[a], data->scorners[a], scale);
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               float spos[2];
+
+                                               copy_v2_v2(spos, data->pos);
+
+                                               /* corners might've been scaled before, restore their original position */
+                                               memcpy(data->corners, data->scorners, sizeof(data->scorners));
+
+                                               data->pos[0] = data->spos[0] + dx;
+                                               data->pos[1] = data->spos[1] + dy;
+
+                                               if (!slide_check_corners(data->corners)) {
+                                                       copy_v2_v2(data->pos, spos);
+                                               }
+                                       }
+
+                                       /* currently only patterns are allowed to have such combination of event and data */
+                                       BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM);
                                }
                        }
 
-                       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, NULL);
+                       data->marker->flag &= ~MARKER_TRACKED;
+
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
 
                        break;
 
@@ -613,7 +782,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event)
 
                        show_cursor(C);
 
-                       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, NULL);
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
 
                        return OPERATOR_CANCELLED;
        }
@@ -629,12 +798,12 @@ void CLIP_OT_slide_marker(wmOperatorType *ot)
        ot->idname = "CLIP_OT_slide_marker";
 
        /* api callbacks */
-       ot->poll = ED_space_clip_tracking_size_poll;
+       ot->poll = ED_space_clip_tracking_poll;
        ot->invoke = slide_marker_invoke;
        ot->modal = slide_marker_modal;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_GRAB_POINTER|OPTYPE_BLOCKING;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
 
        /* properties */
        RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -657,43 +826,57 @@ static int mouse_on_side(float co[2], float x1, float y1, float x2, float y2, fl
 
 static int mouse_on_rect(float co[2], float pos[2], float min[2], float max[2], float epsx, float epsy)
 {
-       return mouse_on_side(co, pos[0]+min[0], pos[1]+min[1], pos[0]+max[0], pos[1]+min[1], epsx, epsy) ||
-              mouse_on_side(co, pos[0]+min[0], pos[1]+min[1], pos[0]+min[0], pos[1]+max[1], epsx, epsy) ||
-              mouse_on_side(co, pos[0]+min[0], pos[1]+max[1], pos[0]+max[0], pos[1]+max[1], epsx, epsy) ||
-              mouse_on_side(co, pos[0]+max[0], pos[1]+min[1], pos[0]+max[0], pos[1]+max[1], epsx, epsy);
+       return mouse_on_side(co, pos[0] + min[0], pos[1] + min[1], pos[0] + max[0], pos[1] + min[1], epsx, epsy) ||
+              mouse_on_side(co, pos[0] + min[0], pos[1] + min[1], pos[0] + min[0], pos[1] + max[1], epsx, epsy) ||
+              mouse_on_side(co, pos[0] + min[0], pos[1] + max[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy) ||
+              mouse_on_side(co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy);
+}
+
+static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx, float epsy)
+{
+       float dist = dist_to_crns(co, pos, crns);
+
+       return dist < MAX2(epsx, epsy);
 }
 
 static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *track)
 {
-       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
+       int framenr = ED_space_clip_clip_framenr(sc);
+       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
+       float pat_min[2], pat_max[2];
        float epsx, epsy;
        int width, height;
 
        ED_space_clip_size(sc, &width, &height);
 
-       epsx = MIN4(track->pat_min[0]-track->search_min[0], track->search_max[0]-track->pat_max[0],
-                  fabsf(track->pat_min[0]), fabsf(track->pat_max[0])) / 2;
-       epsy = MIN4(track->pat_min[1]-track->search_min[1], track->search_max[1]-track->pat_max[1],
-                  fabsf(track->pat_min[1]), fabsf(track->pat_max[1])) / 2;
+       BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+
+       epsx = MIN4(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0],
+                   fabsf(pat_min[0]), fabsf(pat_max[0])) / 2;
+       epsy = MIN4(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1],
+                   fabsf(pat_min[1]), fabsf(pat_max[1])) / 2;
 
        epsx = MAX2(epsx, 2.0f / width);
        epsy = MAX2(epsy, 2.0f / height);
 
        if (sc->flag & SC_SHOW_MARKER_SEARCH) {
-               if (mouse_on_rect(co, marker->pos, track->search_min, track->search_max, epsx, epsy))
+               if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy))
                        return TRACK_AREA_SEARCH;
        }
 
-       if ((marker->flag & MARKER_DISABLED)== 0) {
+       if ((marker->flag & MARKER_DISABLED) == 0) {
                if (sc->flag & SC_SHOW_MARKER_PATTERN)
-                       if (mouse_on_rect(co, marker->pos, track->pat_min, track->pat_max, epsx, epsy))
+                       if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy))
                                return TRACK_AREA_PAT;
 
                epsx = 12.0f / width;
                epsy = 12.0f / height;
 
-               if (fabsf(co[0]-marker->pos[0]-track->offset[0])< epsx && fabsf(co[1]-marker->pos[1]-track->offset[1])<=epsy)
+               if (fabsf(co[0] - marker->pos[0] - track->offset[0]) < epsx &&
+                   fabsf(co[1] - marker->pos[1] - track->offset[1]) <= epsy)
+               {
                        return TRACK_AREA_POINT;
+               }
        }
 
        return TRACK_AREA_NONE;
@@ -702,9 +885,24 @@ static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *trac
 static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
 {
        float d1, d2, d3, d4;
-       float p[2] = {co[0]-pos[0], co[1]-pos[1]};
-       float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]},
-             v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};
+       float p[2] = {co[0] - pos[0], co[1] - pos[1]};
+       float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
+       float v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};
+
+       d1 = dist_to_line_segment_v2(p, v1, v2);
+       d2 = dist_to_line_segment_v2(p, v2, v3);
+       d3 = dist_to_line_segment_v2(p, v3, v4);
+       d4 = dist_to_line_segment_v2(p, v4, v1);
+
+       return MIN4(d1, d2, d3, d4);
+}
+
+static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
+{
+       float d1, d2, d3, d4;
+       float p[2] = {co[0] - pos[0], co[1] - pos[1]};
+       float *v1 = crns[0], *v2 = crns[1],
+             *v3 = crns[2], *v4 = crns[3];
 
        d1 = dist_to_line_segment_v2(p, v1, v2);
        d2 = dist_to_line_segment_v2(p, v2, v3);
@@ -718,29 +916,31 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas
 {
        MovieTrackingTrack *track = NULL, *cur;
        float mindist = 0.0f;
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        cur = tracksbase->first;
        while (cur) {
-               MovieTrackingMarker *marker = BKE_tracking_get_marker(cur, sc->user.framenr);
+               MovieTrackingMarker *marker = BKE_tracking_get_marker(cur, framenr);
 
                if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc, cur, marker)) {
                        float dist, d1, d2 = FLT_MAX, d3 = FLT_MAX;
 
-                       d1 = sqrtf((co[0]-marker->pos[0]-cur->offset[0])*(co[0]-marker->pos[0]-cur->offset[0])+
-                                         (co[1]-marker->pos[1]-cur->offset[1])*(co[1]-marker->pos[1]-cur->offset[1])); /* distance to marker point */
+                       /* distance to marker point */
+                       d1 = sqrtf((co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) +
+                                          (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1]));
 
                        /* distance to pattern boundbox */
                        if (sc->flag & SC_SHOW_MARKER_PATTERN)
-                               d2 = dist_to_rect(co, marker->pos, cur->pat_min, cur->pat_max);
+                               d2 = dist_to_crns(co, marker->pos, marker->pattern_corners);
 
                        /* distance to search boundbox */
                        if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur))
-                               d3 = dist_to_rect(co, marker->pos, cur->search_min, cur->search_max);
+                               d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max);
 
                        /* choose minimal distance. useful for cases of overlapped markers. */
                        dist = MIN3(d1, d2, d3);
 
-                       if (track == NULL || dist<mindist) {
+                       if (track == NULL || dist < mindist) {
                                track = cur;
                                mindist = dist;
                        }
@@ -791,7 +991,7 @@ static int mouse_select(bContext *C, float co[2], int extend)
 
        BKE_tracking_dopesheet_tag_update(tracking);
 
-       WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+       WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -821,7 +1021,7 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
                        clip->tracking.act_track = slidedata->track;
 
-                       WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+                       WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
                        MEM_freeN(slidedata);
 
@@ -845,7 +1045,8 @@ void CLIP_OT_select(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = select_exec;
        ot->invoke = select_invoke;
-       ot->poll = ED_space_clip_tracking_poll;
+       //ot->poll = ED_space_clip_tracking_poll; // so mask view can Ctrl+RMB markers
+       ot->poll = ED_space_clip_view_clip_poll;
 
        /* flags */
        ot->flag = OPTYPE_UNDO;
@@ -869,6 +1070,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
        rcti rect;
        rctf rectf;
        int change = FALSE, mode, extend;
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        /* get rectangle from operator */
        rect.xmin = RNA_int_get(op->ptr, "xmin");
@@ -886,11 +1088,11 @@ static int border_select_exec(bContext *C, wmOperator *op)
        track = tracksbase->first;
        while (track) {
                if ((track->flag & TRACK_HIDDEN) == 0) {
-                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
+                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
 
                        if (MARKER_VISIBLE(sc, track, marker)) {
                                if (BLI_in_rctf(&rectf, marker->pos[0], marker->pos[1])) {
-                                       BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
+                                       BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode != GESTURE_MODAL_SELECT);
                                }
                                else if (!extend) {
                                        BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, 1);
@@ -906,7 +1108,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
-               WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
                return OPERATOR_FINISHED;
        }
@@ -934,6 +1136,97 @@ void CLIP_OT_select_border(wmOperatorType *ot)
        WM_operator_properties_gesture_border(ot, TRUE);
 }
 
+
+static int do_lasso_select_marker(bContext *C, int mcords[][2], short moves, short select)
+{
+       ARegion *ar = CTX_wm_region(C);
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip(sc);
+       MovieTracking *tracking = &clip->tracking;
+       MovieTrackingTrack *track;
+       ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
+       rcti rect;
+       int change = FALSE;
+       int framenr = ED_space_clip_clip_framenr(sc);
+
+       /* get rectangle from operator */
+       BLI_lasso_boundbox(&rect, mcords, moves);
+
+       /* do actual selection */
+       track = tracksbase->first;
+       while (track) {
+               if ((track->flag & TRACK_HIDDEN) == 0) {
+                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
+
+                       if (MARKER_VISIBLE(sc, track, marker)) {
+                               float screen_co[2];
+
+                               /* marker in screen coords */
+                               ED_clip_point_stable_pos__reverse(sc, ar, marker->pos, screen_co);
+
+                               if (BLI_in_rcti(&rect, screen_co[0], screen_co[1]) &&
+                                   BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
+                               {
+                                       BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, !select);
+                               }
+
+                               change = TRUE;
+                       }
+               }
+
+               track = track->next;
+       }
+
+       if (change) {
+               BKE_tracking_dopesheet_tag_update(tracking);
+
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+       }
+
+       return change;
+}
+
+static int clip_lasso_select_exec(bContext *C, wmOperator *op)
+{
+       int mcords_tot;
+       int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+
+       if (mcords) {
+               short select;
+
+               select = !RNA_boolean_get(op->ptr, "deselect");
+               do_lasso_select_marker(C, mcords, mcords_tot, select);
+
+               MEM_freeN(mcords);
+
+               return OPERATOR_FINISHED;
+       }
+       return OPERATOR_PASS_THROUGH;
+}
+
+void CLIP_OT_select_lasso(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Lasso Select";
+       ot->description = "Select markers using lasso selection";
+       ot->idname = "CLIP_OT_select_lasso";
+
+       /* api callbacks */
+       ot->invoke = WM_gesture_lasso_invoke;
+       ot->modal = WM_gesture_lasso_modal;
+       ot->exec = clip_lasso_select_exec;
+       ot->poll = ED_space_clip_tracking_poll;
+       ot->cancel = WM_gesture_lasso_cancel;
+
+       /* flags */
+       ot->flag = OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+       RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
+       RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first");
+}
+
 /********************** circle select operator *********************/
 
 static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
@@ -957,6 +1250,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
        int x, y, radius, width, height, mode, change = FALSE;
        float zoomx, zoomy, offset[2], ellipse[2];
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        /* get operator properties */
        x = RNA_int_get(op->ptr, "x");
@@ -978,10 +1272,10 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        track = tracksbase->first;
        while (track) {
                if ((track->flag & TRACK_HIDDEN) == 0) {
-                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr);
+                       MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
 
                        if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) {
-                               BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
+                               BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode != GESTURE_MODAL_SELECT);
 
                                change = TRUE;
                        }
@@ -993,7 +1287,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
-               WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
                return OPERATOR_FINISHED;
        }
@@ -1015,7 +1309,7 @@ void CLIP_OT_select_circle(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
@@ -1035,7 +1329,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
        MovieTrackingMarker *marker;
        ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
        int action = RNA_enum_get(op->ptr, "action");
-       int framenr = sc->user.framenr;
+       int framenr = ED_space_clip_clip_framenr(sc);
        int has_selection = FALSE;
 
        if (action == SEL_TOGGLE) {
@@ -1057,7 +1351,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
 
        track = tracksbase->first;
        while (track) {
-               if ((track->flag & TRACK_HIDDEN)==0) {
+               if ((track->flag & TRACK_HIDDEN) == 0) {
                        marker = BKE_tracking_get_marker(track, framenr);
 
                        if (MARKER_VISIBLE(sc, track, marker)) {
@@ -1092,7 +1386,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
 
        BKE_tracking_dopesheet_tag_update(tracking);
 
-       WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+       WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -1109,7 +1403,7 @@ void CLIP_OT_select_all(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        WM_operator_properties_select_all(ot);
 }
@@ -1125,21 +1419,22 @@ static int select_groped_exec(bContext *C, wmOperator *op)
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
        int group = RNA_enum_get(op->ptr, "group");
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        track = tracksbase->first;
        while (track) {
                int ok = FALSE;
 
-               marker = BKE_tracking_get_marker(track, sc->user.framenr);
+               marker = BKE_tracking_get_marker(track, framenr);
 
                if (group == 0) { /* Keyframed */
-                       ok = marker->framenr == sc->user.framenr && (marker->flag & MARKER_TRACKED)==0;
+                       ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED) == 0;
                }
                else if (group == 1) { /* Estimated */
-                       ok = marker->framenr != sc->user.framenr;
+                       ok = marker->framenr != framenr;
                }
                else if (group == 2) { /* tracked */
-                       ok = marker->framenr == sc->user.framenr && (marker->flag & MARKER_TRACKED);
+                       ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED);
                }
                else if (group == 3) { /* locked */
                        ok = track->flag & TRACK_LOCKED;
@@ -1174,7 +1469,7 @@ static int select_groped_exec(bContext *C, wmOperator *op)
 
        BKE_tracking_dopesheet_tag_update(tracking);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -1199,10 +1494,10 @@ void CLIP_OT_select_grouped(wmOperatorType *ot)
 
        /* api callbacks */
        ot->exec = select_groped_exec;
-       ot->poll = ED_space_clip_tracking_size_poll;
+       ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* proeprties */
        RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
@@ -1232,7 +1527,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip)
        int tot = 0;
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
-       int framenr = sc->user.framenr;
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        track = tracksbase->first;
        while (track) {
@@ -1254,10 +1549,10 @@ static void clear_invisible_track_selection(SpaceClip *sc, MovieClip *clip)
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
        int hidden = 0;
 
-       if ((sc->flag & SC_SHOW_MARKER_PATTERN)==0)
+       if ((sc->flag & SC_SHOW_MARKER_PATTERN) == 0)
                hidden |= TRACK_AREA_PAT;
 
-       if ((sc->flag & SC_SHOW_MARKER_SEARCH)==0)
+       if ((sc->flag & SC_SHOW_MARKER_SEARCH) == 0)
                hidden |= TRACK_AREA_SEARCH;
 
        if (hidden) {
@@ -1276,7 +1571,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit
 {
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
-       int framenr = sc->user.framenr;
+       int framenr = ED_space_clip_clip_framenr(sc);
        int frames_limit = 0;
 
        clear_invisible_track_selection(sc, clip);
@@ -1284,7 +1579,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit
        track = tracksbase->first;
        while (track) {
                if (TRACK_VIEW_SELECTED(sc, track)) {
-                       if ((track->flag & TRACK_HIDDEN)==0 && (track->flag & TRACK_LOCKED)==0) {
+                       if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
                                BKE_tracking_ensure_marker(track, framenr);
 
                                if (track->frames_limit) {
@@ -1326,7 +1621,7 @@ static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backward
 
        track_init_markers(sc, clip, &frames_limit);
 
-       tmj->sfra = sc->user.framenr;
+       tmj->sfra = ED_space_clip_clip_framenr(sc);
        tmj->clip = clip;
        tmj->backwards = backwards;
 
@@ -1343,6 +1638,8 @@ static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backward
                        tmj->efra = MIN2(tmj->efra, tmj->sfra + frames_limit);
        }
 
+       tmj->efra = BKE_movieclip_remap_scene_to_clip_frame(clip, tmj->efra);
+
        if (settings->speed != TRACKING_SPEED_FASTEST) {
                tmj->delay = 1.0f / scene->r.frs_sec * 1000.0f;
 
@@ -1391,15 +1688,15 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo
                        if (!BKE_tracking_next(tmj->context))
                                break;
 
-                       exec_time = PIL_check_seconds_timer()-start_time;
+                       exec_time = PIL_check_seconds_timer() - start_time;
                        if (tmj->delay > (float)exec_time)
-                               PIL_sleep_ms(tmj->delay-(float)exec_time);
+                               PIL_sleep_ms(tmj->delay - (float)exec_time);
                }
                else if (!BKE_tracking_next(tmj->context))
                                break;
 
                *do_update = TRUE;
-               *progress = (float)(framenr-tmj->sfra) / (tmj->efra-tmj->sfra);
+               *progress = (float)(framenr - tmj->sfra) / (tmj->efra - tmj->sfra);
 
                if (tmj->backwards)
                        framenr--;
@@ -1427,15 +1724,15 @@ static void track_markers_freejob(void *tmv)
        TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
 
        tmj->clip->tracking_context = NULL;
-       tmj->scene->r.cfra = tmj->lastfra;
-       ED_update_for_newframe(tmj->main, tmj->scene, tmj->screen, 0);
+       tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip, tmj->lastfra);
+       ED_update_for_newframe(tmj->main, tmj->scene, 0);
 
        BKE_tracking_sync(tmj->context);
        BKE_tracking_context_free(tmj->context);
 
        MEM_freeN(tmj);
 
-       WM_main_add_notifier(NC_SCENE|ND_FRAME, tmj->scene);
+       WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene);
 }
 
 static int track_markers_exec(bContext *C, wmOperator *op)
@@ -1444,13 +1741,13 @@ static int track_markers_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip(sc);
        Scene *scene = CTX_data_scene(C);
        struct MovieTrackingContext *context;
-       int framenr = sc->user.framenr;
+       int framenr = ED_space_clip_clip_framenr(sc);
        int sfra = framenr, efra;
        int backwards = RNA_boolean_get(op->ptr, "backwards");
        int sequence = RNA_boolean_get(op->ptr, "sequence");
        int frames_limit;
 
-       if (track_count_markers(sc, clip)==0)
+       if (track_count_markers(sc, clip) == 0)
                return OPERATOR_CANCELLED;
 
        track_init_markers(sc, clip, &frames_limit);
@@ -1462,10 +1759,14 @@ static int track_markers_exec(bContext *C, wmOperator *op)
 
        /* limit frames to be tracked by user setting */
        if (frames_limit) {
-               if (backwards) efra = MAX2(efra, sfra-frames_limit);
-               else efra = MIN2(efra, sfra+frames_limit);
+               if (backwards)
+                       efra = MAX2(efra, sfra - frames_limit);
+               else
+                       efra = MIN2(efra, sfra + frames_limit);
        }
 
+       efra = BKE_movieclip_remap_scene_to_clip_frame(clip, efra);
+
        if (!track_markers_check_direction(backwards, framenr, efra))
                return OPERATOR_CANCELLED;
 
@@ -1487,10 +1788,10 @@ static int track_markers_exec(bContext *C, wmOperator *op)
        BKE_tracking_context_free(context);
 
        /* update scene current frame to the lastes tracked frame */
-       scene->r.cfra = framenr;
+       scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 
        return OPERATOR_FINISHED;
 }
@@ -1513,7 +1814,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
        if (clip->tracking_context)
                return OPERATOR_CANCELLED;
 
-       if (track_count_markers(sc, clip)==0)
+       if (track_count_markers(sc, clip) == 0)
                return OPERATOR_CANCELLED;
 
        if (!sequence)
@@ -1534,8 +1835,10 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
         * with fixed FPS. To deal with editor refresh we have to synchronize
         * tracks from job and tracks in clip. Do this in timer callback
         * to prevent threading conflicts. */
-       if (tmj->delay>0) WM_jobs_timer(steve, tmj->delay/1000.0f, NC_MOVIECLIP|NA_EVALUATED, 0);
-       else WM_jobs_timer(steve, 0.2, NC_MOVIECLIP|NA_EVALUATED, 0);
+       if (tmj->delay > 0)
+               WM_jobs_timer(steve, tmj->delay / 1000.0f, NC_MOVIECLIP | NA_EVALUATED, 0);
+       else
+               WM_jobs_timer(steve, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0);
 
        WM_jobs_callbacks(steve, track_markers_startjob, NULL, track_markers_updatejob, NULL);
 
@@ -1554,7 +1857,7 @@ static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *eve
 {
        /* no running tracking, remove handler and pass through */
        if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C)))
-               return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+               return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
 
        /* running tracking */
        switch (event->type) {
@@ -1576,7 +1879,7 @@ void CLIP_OT_track_markers(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = track_markers_exec;
        ot->invoke = track_markers_invoke;
-       ot->poll = ED_space_clip_tracking_frame_poll;
+       ot->poll = ED_space_clip_tracking_poll;
        ot->modal = track_markers_modal;
 
        /* flags */
@@ -1691,8 +1994,8 @@ static void solve_camera_freejob(void *scv)
 
        DAG_id_tag_update(&clip->id, 0);
 
-       WM_main_add_notifier(NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, NULL);
+       WM_main_add_notifier(NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
 
        /* update active clip displayed in scene buttons */
        WM_main_add_notifier(NC_SCENE, scene);
@@ -1753,12 +2056,12 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
 
        /* hide reconstruction statistics from previous solve */
        reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
 
        /* setup job */
        steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Solve Camera", WM_JOB_PROGRESS);
        WM_jobs_customdata(steve, scj, solve_camera_freejob);
-       WM_jobs_timer(steve, 0.1, NC_MOVIECLIP|NA_EVALUATED, 0);
+       WM_jobs_timer(steve, 0.1, NC_MOVIECLIP | NA_EVALUATED, 0);
        WM_jobs_callbacks(steve, solve_camera_startjob, NULL, solve_camera_updatejob, NULL);
 
        G.afbreek = 0;
@@ -1776,7 +2079,7 @@ static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *even
 {
        /* no running solver, remove handler and pass through */
        if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C)))
-               return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+               return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
 
        /* running tracking */
        switch (event->type) {
@@ -1802,7 +2105,7 @@ void CLIP_OT_solve_camera(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** clear solution operator *********************/
@@ -1832,8 +2135,8 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
 
        DAG_id_tag_update(&clip->id, 0);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -1850,7 +2153,7 @@ void CLIP_OT_clear_solution(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** clear track operator *********************/
@@ -1863,22 +2166,23 @@ static int clear_track_path_exec(bContext *C, wmOperator *op)
        ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
        int action = RNA_enum_get(op->ptr, "action");
        int clear_active = RNA_boolean_get(op->ptr, "clear_active");
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        if (clear_active) {
                track = BKE_tracking_active_track(&clip->tracking);
-               BKE_tracking_clear_path(track, sc->user.framenr, action);
+               BKE_tracking_clear_path(track, framenr, action);
        }
        else {
                track = tracksbase->first;
                while (track) {
                        if (TRACK_VIEW_SELECTED(sc, track))
-                               BKE_tracking_clear_path(track, sc->user.framenr, action);
+                               BKE_tracking_clear_path(track, framenr, action);
 
                        track = track->next;
                }
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -1902,7 +2206,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* proeprties */
        RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
@@ -1919,10 +2223,11 @@ static int disable_markers_exec(bContext *C, wmOperator *op)
        ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track = tracksbase->first;
        int action = RNA_enum_get(op->ptr, "action");
+       int framenr = ED_space_clip_clip_framenr(sc);
 
        while (track) {
-               if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) {
-                       MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr);
+               if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+                       MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, framenr);
 
                        if (action == 0)
                                marker->flag |= MARKER_DISABLED;
@@ -1936,7 +2241,7 @@ static int disable_markers_exec(bContext *C, wmOperator *op)
 
        DAG_id_tag_update(&clip->id, 0);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -1960,7 +2265,7 @@ void CLIP_OT_disable_markers(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
@@ -1973,13 +2278,13 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
        Object *camera = scene->camera;
        Base *base;
 
-       if (camera && BKE_object_movieclip_get(scene, camera, 0)==clip)
+       if (camera && BKE_object_movieclip_get(scene, camera, 0) == clip)
                return camera;
 
        base = scene->base.first;
        while (base) {
                if (base->object->type == OB_CAMERA) {
-                       if (BKE_object_movieclip_get(scene, base->object, 0)==clip) {
+                       if (BKE_object_movieclip_get(scene, base->object, 0) == clip) {
                                camera = base->object;
                                break;
                        }
@@ -2015,18 +2320,22 @@ static Object *get_orientation_object(bContext *C)
 
 static int set_orientation_poll(bContext *C)
 {
-       if (ED_space_clip_tracking_size_poll(C)) {
+       SpaceClip *sc = CTX_wm_space_clip(C);
+
+       if (sc) {
                Scene *scene = CTX_data_scene(C);
-               SpaceClip *sc = CTX_wm_space_clip(C);
                MovieClip *clip = ED_space_clip(sc);
-               MovieTracking *tracking = &clip->tracking;
-               MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking);
 
-               if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
-                       return TRUE;
-               }
-               else {
-                       return OBACT != NULL;
+               if (clip) {
+                       MovieTracking *tracking = &clip->tracking;
+                       MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking);
+
+                       if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+                               return TRUE;
+                       }
+                       else {
+                               return OBACT != NULL;
+                       }
                }
        }
 
@@ -2144,7 +2453,7 @@ static int set_origin_exec(bContext *C, wmOperator *op)
 
                track = track->next;
        }
-       mul_v3_fl(median, 1.0f/selected_count);
+       mul_v3_fl(median, 1.0f / selected_count);
 
        BKE_get_tracking_mat(scene, camera, mat);
 
@@ -2162,8 +2471,8 @@ static int set_origin_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(&clip->id, 0);
        DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2180,7 +2489,7 @@ void CLIP_OT_set_origin(wmOperatorType *ot)
        ot->poll = set_orientation_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_boolean(ot->srna, "use_median", 0, "Use Median", "Set origin to median point of selected bundles");
@@ -2254,7 +2563,7 @@ static void set_axis(Scene *scene,  Object *ob, MovieClip *clip, MovieTrackingOb
                else {
                        copy_v3_v3(mat[1], vec);
 
-                       if (is_camera || fabsf(vec[2])<1e-3f) {
+                       if (is_camera || fabsf(vec[2]) < 1e-3f) {
                                mat[1][2] = 0.0f;
                                mat[2][0] = 0.0f; mat[2][1] = 0.0f; mat[2][2] = 1.0f;
                                cross_v3_v3v3(mat[0], mat[1], mat[2]);
@@ -2318,7 +2627,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
                           {1.0f, 0.0f, 0.0f, 0.0f},
                           {0.0f, 0.0f, 0.0f, 1.0f}};   /* 90 degrees Y-axis rotation matrix */
 
-       if (count_selected_bundles(C)!=3) {
+       if (count_selected_bundles(C) != 3) {
                BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor");
 
                return OPERATOR_CANCELLED;
@@ -2339,7 +2648,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
 
        /* get 3 bundles to use as reference */
        track = tracksbase->first;
-       while (track && tot<3) {
+       while (track && tot < 3) {
                if (track->flag & TRACK_HAS_BUNDLE && TRACK_VIEW_SELECTED(sc, track)) {
                        mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
 
@@ -2389,7 +2698,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
                BKE_object_apply_mat4(object, newmat, 0, 0);
 
                /* make camera have positive z-coordinate */
-               if (object->loc[2]<0) {
+               if (object->loc[2] < 0) {
                        invert_m4(rot);
                        mult_m4_m4m4(newmat, rot, mat);
                        BKE_object_apply_mat4(object, newmat, 0, 0);
@@ -2405,8 +2714,8 @@ static int set_plane_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(&clip->id, 0);
        DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2429,7 +2738,7 @@ void CLIP_OT_set_plane(wmOperatorType *ot)
        ot->poll = set_orientation_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "plane", plane_items, 0, "Plane", "Plane to be used for orientation");
@@ -2449,7 +2758,7 @@ static int set_axis_exec(bContext *C, wmOperator *op)
        ListBase *tracksbase;
        int axis = RNA_enum_get(op->ptr, "axis");
 
-       if (count_selected_bundles(C)!=1) {
+       if (count_selected_bundles(C) != 1) {
                BKE_report(op->reports, RPT_ERROR, "Single track with bundle should be selected to define axis");
 
                return OPERATOR_CANCELLED;
@@ -2477,8 +2786,8 @@ static int set_axis_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(&clip->id, 0);
        DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2501,7 +2810,7 @@ void CLIP_OT_set_axis(wmOperatorType *ot)
        ot->poll = set_orientation_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "axis", axis_actions, 0, "Axis", "Axis to use to align bundle along");
@@ -2551,7 +2860,7 @@ static int do_set_scale(bContext *C, wmOperator *op, int scale_solution)
 
        sub_v3_v3(vec[0], vec[1]);
 
-       if (len_v3(vec[0])>1e-5f) {
+       if (len_v3(vec[0]) > 1e-5f) {
                scale = dist / len_v3(vec[0]);
 
                if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
@@ -2561,7 +2870,7 @@ static int do_set_scale(bContext *C, wmOperator *op, int scale_solution)
                else if (!scale_solution) {
                        Object *solver_camera = object_solver_camera(scene, object);
 
-                       object->size[0] = object->size[1] = object->size[2] = 1.0f/scale;
+                       object->size[0] = object->size[1] = object->size[2] = 1.0f / scale;
 
                        if (solver_camera) {
                                object->size[0] /= solver_camera->size[0];
@@ -2578,8 +2887,8 @@ static int do_set_scale(bContext *C, wmOperator *op, int scale_solution)
                if (object)
                        DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
-               WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
-               WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+               WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
+               WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
        }
 
        return OPERATOR_FINISHED;
@@ -2614,7 +2923,7 @@ void CLIP_OT_set_scale(wmOperatorType *ot)
        ot->poll = set_orientation_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX,
@@ -2625,16 +2934,20 @@ void CLIP_OT_set_scale(wmOperatorType *ot)
 
 static int set_solution_scale_poll(bContext *C)
 {
-       if (ED_space_clip_tracking_size_poll(C)) {
-               SpaceClip *sc = CTX_wm_space_clip(C);
+       SpaceClip *sc = CTX_wm_space_clip(C);
+
+       if (sc) {
                MovieClip *clip = ED_space_clip(sc);
-               MovieTracking *tracking = &clip->tracking;
-               MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking);
 
-               return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0;
+               if (clip) {
+                       MovieTracking *tracking = &clip->tracking;
+                       MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking);
+
+                       return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0;
+               }
        }
 
-       return 0;
+       return FALSE;
 }
 
 static int set_solution_scale_exec(bContext *C, wmOperator *op)
@@ -2666,7 +2979,7 @@ void CLIP_OT_set_solution_scale(wmOperatorType *ot)
        ot->poll = set_solution_scale_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX,
@@ -2686,10 +2999,10 @@ static int set_center_principal_exec(bContext *C, wmOperator *UNUSED(op))
        if (width == 0 || height == 0)
                return OPERATOR_CANCELLED;
 
-       clip->tracking.camera.principal[0] = ((float)width)/2.0f;
-       clip->tracking.camera.principal[1] = ((float)height)/2.0f;
+       clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
+       clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -2706,7 +3019,7 @@ void CLIP_OT_set_center_principal(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** hide tracks operator *********************/
@@ -2745,7 +3058,7 @@ static int hide_tracks_exec(bContext *C, wmOperator *op)
 
        BKE_tracking_dopesheet_tag_update(tracking);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2762,7 +3075,7 @@ void CLIP_OT_hide_tracks(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected tracks");
@@ -2787,7 +3100,7 @@ static int hide_tracks_clear_exec(bContext *C, wmOperator *UNUSED(op))
 
        BKE_tracking_dopesheet_tag_update(tracking);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2804,7 +3117,7 @@ void CLIP_OT_hide_tracks_clear(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** detect features operator *********************/
@@ -2841,8 +3154,14 @@ static int detect_features_exec(bContext *C, wmOperator *op)
        int min_trackability = RNA_int_get(op->ptr, "min_trackability");
        int min_distance = RNA_int_get(op->ptr, "min_distance");
        int place_outside_layer = 0;
+       int framenr = ED_space_clip_clip_framenr(sc);
        bGPDlayer *layer = NULL;
 
+       if (!ibuf) {
+               BKE_report(op->reports, RPT_ERROR, "Feature detection requires valid clip frame");
+               return OPERATOR_CANCELLED;
+       }
+
        if (placement != 0) {
                layer = detect_get_layer(clip);
                place_outside_layer = placement == 2;
@@ -2857,12 +3176,12 @@ static int detect_features_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
-       BKE_tracking_detect_fast(tracking, tracksbase, ibuf, sc->user.framenr, margin,
+       BKE_tracking_detect_fast(tracking, tracksbase, ibuf, framenr, margin,
                                min_trackability, min_distance, layer, place_outside_layer);
 
        IMB_freeImBuf(ibuf);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2883,10 +3202,10 @@ void CLIP_OT_detect_features(wmOperatorType *ot)
 
        /* api callbacks */
        ot->exec = detect_features_exec;
-       ot->poll = ED_space_clip_tracking_frame_poll;
+       ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "placement", placement_items, 0, "Placement", "Placement for detected features");
@@ -2914,8 +3233,9 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
 
                delta = pos == 1 ? 1 : -1;
 
-               while (sc->user.framenr+delta >= SFRA && sc->user.framenr+delta <= EFRA) {
-                       MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, sc->user.framenr+delta);
+               while (sc->user.framenr + delta >= SFRA && sc->user.framenr + delta <= EFRA) {
+                       int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr + delta);
+                       MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr);
 
                        if (!marker || marker->flag & MARKER_DISABLED)
                                break;
@@ -2925,7 +3245,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
        }
        else {  /* to to failed frame */
                if (clip->tracking.reconstruction.flag & TRACKING_RECONSTRUCTED) {
-                       int a = sc->user.framenr;
+                       int a = ED_space_clip_clip_framenr(sc);
                        MovieTracking *tracking = &clip->tracking;
                        MovieTrackingObject *object = BKE_tracking_active_object(tracking);
 
@@ -2933,13 +3253,13 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
 
                        a += delta;
 
-                       while (a+delta >= SFRA && a+delta <= EFRA) {
+                       while (a + delta >= SFRA && a + delta <= EFRA) {
                                MovieReconstructedCamera *cam;
 
                                cam = BKE_tracking_get_reconstructed_camera(tracking, object, a);
 
                                if (!cam) {
-                                       sc->user.framenr = a;
+                                       sc->user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, a);
 
                                        break;
                                }
@@ -2953,10 +3273,10 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
                CFRA = sc->user.framenr;
                sound_seek_scene(CTX_data_main(C), CTX_data_scene(C));
 
-               WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+               WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, NULL);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -2981,7 +3301,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "position", position_items, 0, "Position", "Position to jump to");
@@ -3021,7 +3341,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
                track = next;
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3035,10 +3355,10 @@ void CLIP_OT_join_tracks(wmOperatorType *ot)
 
        /* api callbacks */
        ot->exec = join_tracks_exec;
-       ot->poll = ED_space_clip_tracking_size_poll;
+       ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** lock tracks operator *********************/
@@ -3064,7 +3384,7 @@ static int lock_tracks_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3088,7 +3408,7 @@ void CLIP_OT_lock_tracks(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Lock action to execute");
@@ -3121,7 +3441,7 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
                track = track->next;
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3138,7 +3458,7 @@ void CLIP_OT_track_copy_color(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** add 2d stabilization tracks operator *********************/
@@ -3155,7 +3475,7 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
 
        track = tracksbase->first;
        while (track) {
-               if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_USE_2D_STAB)==0) {
+               if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_USE_2D_STAB) == 0) {
                        track->flag |= TRACK_USE_2D_STAB;
                        stab->tot_track++;
 
@@ -3169,7 +3489,7 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
                stab->ok = 0;
 
                DAG_id_tag_update(&clip->id, 0);
-               WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+               WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
        }
 
        return OPERATOR_FINISHED;
@@ -3187,7 +3507,7 @@ void CLIP_OT_stabilize_2d_add(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** remove 2d stabilization tracks operator *********************/
@@ -3211,7 +3531,7 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
                                stab->act_track--;
                                stab->tot_track--;
 
-                               if (stab->act_track<0)
+                               if (stab->act_track < 0)
                                        stab->act_track = 0;
 
                                update = 1;
@@ -3229,7 +3549,7 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
                stab->ok = 0;
 
                DAG_id_tag_update(&clip->id, 0);
-               WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+               WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
        }
 
        return OPERATOR_FINISHED;
@@ -3247,7 +3567,7 @@ void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** select 2d stabilization tracks operator *********************/
@@ -3273,7 +3593,7 @@ static int stabilize_2d_select_exec(bContext *C, wmOperator *UNUSED(op))
        }
 
        if (update)
-               WM_event_add_notifier(C, NC_MOVIECLIP|ND_SELECT, clip);
+               WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3290,7 +3610,7 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** set 2d stabilization rotation track operator *********************/
@@ -3309,7 +3629,7 @@ static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op))
                stab->ok = 0;
 
                DAG_id_tag_update(&clip->id, 0);
-               WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+               WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
        }
 
        return OPERATOR_FINISHED;
@@ -3327,7 +3647,7 @@ void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** clean tracks operator *********************/
@@ -3342,30 +3662,30 @@ static int is_track_clean(MovieTrackingTrack *track, int frames, int del)
        if (del)
                new_markers = MEM_callocN(markersnr*sizeof(MovieTrackingMarker), "track cleaned markers");
 
-       for (a = 0; a<markersnr; a++) {
+       for (a = 0; a < markersnr; a++) {
                int end = 0;
 
                if (prev == -1) {
-                       if ((markers[a].flag & MARKER_DISABLED)==0)
+                       if ((markers[a].flag & MARKER_DISABLED) == 0)
                                prev = a;
                        else
                                start_disabled = 1;
                }
 
                if (prev >= 0) {
-                       end =  a == markersnr-1;
-                       end |= (a < markersnr-1) && (markers[a].framenr != markers[a+1].framenr-1 ||
-                                                    markers[a].flag & MARKER_DISABLED);
+                       end =  a == markersnr - 1;
+                       end |= (a < markersnr - 1) && (markers[a].framenr != markers[a + 1].framenr - 1 ||
+                                                      markers[a].flag & MARKER_DISABLED);
                }
 
                if (end) {
                        int segok = 1, len = 0;
 
-                       if (a != prev && markers[a].framenr != markers[a-1].framenr+1)
-                               len = a-prev;
+                       if (a != prev && markers[a].framenr != markers[a - 1].framenr + 1)
+                               len = a - prev;
                        else if (markers[a].flag & MARKER_DISABLED)
-                               len = a-prev;
-                       else len = a-prev+1;
+                               len = a - prev;
+                       else len = a - prev + 1;
 
                        if (frames) {
                                if (len < frames) {
@@ -3386,7 +3706,7 @@ static int is_track_clean(MovieTrackingTrack *track, int frames, int del)
 
                                        /* place disabled marker in front of current segment */
                                        if (start_disabled) {
-                                               memcpy(new_markers+count, markers+prev, sizeof(MovieTrackingMarker));
+                                               memcpy(new_markers + count, markers + prev, sizeof(MovieTrackingMarker));
                                                new_markers[count].framenr--;
                                                new_markers[count].flag |= MARKER_DISABLED;
 
@@ -3394,7 +3714,7 @@ static int is_track_clean(MovieTrackingTrack *track, int frames, int del)
                                                start_disabled = 0;
                                        }
 
-                                       memcpy(new_markers+count, markers+prev, t*sizeof(MovieTrackingMarker));
+                                       memcpy(new_markers + count, markers + prev, t * sizeof(MovieTrackingMarker));
                                        count += t;
                                }
                                else if (markers[a].flag & MARKER_DISABLED) {
@@ -3443,11 +3763,11 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
        while (track) {
                next = track->next;
 
-               if ((track->flag & TRACK_HIDDEN)==0 && (track->flag & TRACK_LOCKED)==0) {
+               if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
                        int ok = 1;
 
                        ok = (is_track_clean(track, frames, action == TRACKING_CLEAN_DELETE_SEGMENT)) &&
-                           (error == 0.0f || (track->flag & TRACK_HAS_BUNDLE)==0  || track->error < error);
+                           (error == 0.0f || (track->flag & TRACK_HAS_BUNDLE) == 0  || track->error < error);
 
                        if (!ok) {
                                if (action == TRACKING_CLEAN_SELECT) {
@@ -3476,7 +3796,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
                track = next;
        }
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|ND_SELECT, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3518,7 +3838,7 @@ void CLIP_OT_clean_tracks(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
        RNA_def_int(ot->srna, "frames", 0, 0, INT_MAX, "Tracked Frames",
@@ -3538,7 +3858,7 @@ static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op))
 
        BKE_tracking_new_object(tracking, "Object");
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3555,7 +3875,7 @@ void CLIP_OT_tracking_object_new(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** remove tracking object *********************/
@@ -3576,7 +3896,7 @@ static int tracking_object_remove_exec(bContext *C, wmOperator *op)
 
        BKE_tracking_remove_object(tracking, object);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3593,7 +3913,7 @@ void CLIP_OT_tracking_object_remove(wmOperatorType *ot)
        ot->poll = ED_space_clip_tracking_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /********************** copy tracks to clipboard operator *********************/
@@ -3647,7 +3967,7 @@ static int paste_tracks_exec(bContext *C, wmOperator *UNUSED(op))
 
        BKE_tracking_clipboard_paste_tracks(tracking, object);
 
-       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
 
        return OPERATOR_FINISHED;
 }
@@ -3664,5 +3984,5 @@ void CLIP_OT_paste_tracks(wmOperatorType *ot)
        ot->poll = paste_tracks_poll;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }