Small refactor of mask sliding operator
[blender.git] / source / blender / editors / transform / transform_conversions.c
index 4d20346f79d256516bdffed492a70baaf6c371bb..8a7caeb30601325de16a37cd325c9666415a7940 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_gpencil_types.h"
 #include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -87,6 +88,7 @@
 #include "BKE_sequencer.h"
 #include "BKE_tessmesh.h"
 #include "BKE_tracking.h"
+#include "BKE_mask.h"
 
 
 #include "ED_anim_api.h"
 #include "ED_types.h"
 #include "ED_uvedit.h"
 #include "ED_clip.h"
+#include "ED_mask.h"
 #include "ED_util.h"  /* for crazyspace correction */
 
 #include "WM_api.h"            /* for WM_event_add_notifier to deal with stabilization nodes */
@@ -1393,10 +1396,10 @@ static void createTransCurveVerts(bContext *C, TransInfo *t)
                                if (bezt->hide==0) {
                                        TransDataCurveHandleFlags *hdata = NULL;
 
-                                       if (            propmode ||
-                                                       ((bezt->f2 & SELECT) && hide_handles) ||
-                                                       ((bezt->f1 & SELECT) && hide_handles == 0)
-                                         ) {
+                                       if (propmode ||
+                                           ((bezt->f2 & SELECT) && hide_handles) ||
+                                           ((bezt->f1 & SELECT) && hide_handles == 0))
+                                       {
                                                copy_v3_v3(td->iloc, bezt->vec[0]);
                                                td->loc= bezt->vec[0];
                                                copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:0]);
@@ -1455,10 +1458,10 @@ static void createTransCurveVerts(bContext *C, TransInfo *t)
                                                count++;
                                                tail++;
                                        }
-                                       if (            propmode ||
-                                                       ((bezt->f2 & SELECT) && hide_handles) ||
-                                                       ((bezt->f3 & SELECT) && hide_handles == 0)
-                                         ) {
+                                       if (propmode ||
+                                           ((bezt->f2 & SELECT) && hide_handles) ||
+                                           ((bezt->f3 & SELECT) && hide_handles == 0))
+                                       {
                                                copy_v3_v3(td->iloc, bezt->vec[2]);
                                                td->loc= bezt->vec[2];
                                                copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:2]);
@@ -1885,7 +1888,8 @@ static void get_edge_center(float cent_r[3], BMVert *eve)
 }
 
 /* way to overwrite what data is edited with transform */
-static void VertsToTransData(TransInfo *t, TransData *td, BMEditMesh *em, BMVert *eve, float *bweight)
+static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx,
+                                                        BMEditMesh *em, BMVert *eve, float *bweight)
 {
        td->flag = 0;
        //if (key)
@@ -1919,12 +1923,23 @@ static void VertsToTransData(TransInfo *t, TransData *td, BMEditMesh *em, BMVert
                td->val = bweight;
                td->ival = bweight ? *(bweight) : 1.0f;
        }
+       else if (t->mode == TFM_SKIN_RESIZE) {
+               MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
+                                                    eve->head.data,
+                                                    CD_MVERT_SKIN);
+               /* skin node size */
+               td->ext = tx;
+               copy_v3_v3(tx->isize, vs->radius);
+               tx->size = vs->radius;
+               td->val = vs->radius;
+       }
 }
 
 static void createTransEditVerts(bContext *C, TransInfo *t)
 {
        ToolSettings *ts = CTX_data_tool_settings(C);
        TransData *tob = NULL;
+       TransDataExtension *tx = NULL;
        BMEditMesh *em = BMEdit_FromObject(t->obedit);
        BMesh *bm = em->bm;
        BMVert *eve;
@@ -2030,6 +2045,10 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
        else t->total = countsel;
 
        tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
+       if (t->mode == TFM_SKIN_RESIZE) {
+               tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension),
+                                                                 "TransObData ext");
+       }
 
        copy_m3_m4(mtx, t->obedit->obmat);
        invert_m3_m3(smtx, mtx);
@@ -2081,7 +2100,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
                        if (propmode || selstate[a]) {
                                float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT);
                                
-                               VertsToTransData(t, tob, em, eve, bweight);
+                               VertsToTransData(t, tob, tx, em, eve, bweight);
+                               if (tx)
+                                       tx++;
 
                                /* selected */
                                if (selstate[a]) tob->flag |= TD_SELECTED;
@@ -2180,7 +2201,6 @@ void flushTransNodes(TransInfo *t)
        if (t->total==1) {
                ED_node_link_intersect_test(t->sa, 1);
        }
-       
 }
 
 /* *** SEQUENCE EDITOR *** */
@@ -3705,9 +3725,9 @@ void flushTransGraphData(TransInfo *t)
                        switch (sipo->autosnap) {
                                case SACTSNAP_FRAME: /* snap to nearest frame (or second if drawing seconds) */
                                        if (sipo->flag & SIPO_DRAWTIME)
-                                               td2d->loc[0] = (float)(floorf((td2d->loc[0]/secf) + 0.5f) * secf);
+                                               td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
                                        else
-                                               td2d->loc[0] = (float)(floorf(td2d->loc[0]+0.5f));
+                                               td2d->loc[0] = floor((double)td2d->loc[0] + 0.5);
                                        break;
                                
                                case SACTSNAP_MARKER: /* snap to nearest marker */
@@ -3715,7 +3735,7 @@ void flushTransGraphData(TransInfo *t)
                                        break;
                        }
                }
-               
+
                /* we need to unapply the nla-mapping from the time in some situations */
                if (adt)
                        td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
@@ -3844,7 +3864,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
                        if (seq->type == SEQ_META) {
                                /* Meta's can only directly be moved between channels since they
                                 * don't have their start and length set directly (children affect that)
-                                * since this Meta is nested we don't need any of its data infact.
+                                * since this Meta is nested we don't need any of its data in fact.
                                 * calc_sequence() will update its settings when run on the toplevel meta */
                                *flag= 0;
                                *count= 0;
@@ -4438,7 +4458,7 @@ static void set_trans_object_base_flags(TransInfo *t)
 
                        if (parsel) {
                                /* rotation around local centers are allowed to propagate */
-                               if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)  && t->around == V3D_LOCAL) {
+                               if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL) {
                                        base->flag |= BA_TRANSFORM_CHILD;
                                }
                                else {
@@ -4487,7 +4507,7 @@ static int count_proportional_objects(TransInfo *t)
        Base *base;
 
        /* rotations around local centers are allowed to propagate, so we take all objects */
-       if (!((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)  && t->around == V3D_LOCAL)) {
+       if (!((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL)) {
                /* mark all parents */
                for (base= scene->base.first; base; base= base->next) {
                        if (TESTBASELIB_BGMODE(v3d, scene, base)) {
@@ -4844,7 +4864,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
                /* marker transform, not especially nice but we may want to move markers
                 * at the same time as keyframes in the dope sheet. */
                if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
-                       /* cant use TFM_TIME_EXTEND
+                       /* cant use TFM_TIME_EXTEND
                         * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
 
                        if (t->mode == TFM_SEQ_SLIDE) {
@@ -4859,10 +4879,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
        }
        else if (t->spacetype == SPACE_NODE) {
                SpaceNode *snode= (SpaceNode *)t->sa->spacedata.first;
-               ED_node_update_hierarchy(C, snode->edittree);
-               
-               if (canceled == 0)
+               if (canceled == 0) {
+                       ED_node_post_apply_transform(C, snode->edittree);
+                       
                        ED_node_link_insert(t->sa);
+               }
                
                /* clear link line */
                ED_node_link_intersect_test(t->sa, 0);
@@ -4879,6 +4900,24 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
                                WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
                        }
                }
+               else if (t->options & CTX_MASK) {
+                       SpaceClip *sc = t->sa->spacedata.first;
+                       Mask *mask = ED_space_clip_mask(sc);
+
+                       if (t->scene->nodetree) {
+                               /* tracks can be used for stabilization nodes,
+                                * flush update for such nodes */
+                               nodeUpdateID(t->scene->nodetree, &mask->id);
+                               WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL);
+                       }
+
+                       /* TODO - dont key all masks... */
+                       if (IS_AUTOKEY_ON(t->scene)) {
+                               Scene *scene = t->scene;
+
+                               ED_mask_layer_shape_auto_key_all(mask, CFRA);
+                       }
+               }
        }
        else if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
@@ -5374,23 +5413,24 @@ typedef struct TransDataTracking {
        short coord;
 } TransDataTracking;
 
-static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track,
-                                  int area, float *loc, float *rel, float *off)
+static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
+                                  MovieTrackingTrack *track, MovieTrackingMarker *marker,
+                                  int area, float loc[2], float rel[2], const float off[2], float aspx, float aspy)
 {
        int anchor = area == TRACK_AREA_POINT && off;
 
        tdt->mode = transDataTracking_ModeTracks;
 
        if (anchor) {
-               td2d->loc[0] = rel[0]; /* hold original location */
-               td2d->loc[1] = rel[1];
+               td2d->loc[0] = rel[0] * aspx; /* hold original location */
+               td2d->loc[1] = rel[1] * aspy;
 
                tdt->loc= loc;
                td2d->loc2d = loc; /* current location */
        }
        else {
-               td2d->loc[0] = loc[0]; /* hold original location */
-               td2d->loc[1] = loc[1];
+               td2d->loc[0] = loc[0] * aspx; /* hold original location */
+               td2d->loc[1] = loc[1] * aspy;
 
                td2d->loc2d = loc; /* current location */
        }
@@ -5404,8 +5444,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
 
        if (rel) {
                if (!anchor) {
-                       td2d->loc[0] += rel[0];
-                       td2d->loc[1] += rel[1];
+                       td2d->loc[0] += rel[0] * aspx;
+                       td2d->loc[1] += rel[1] * aspy;
                }
 
                copy_v2_v2(tdt->srelative, rel);
@@ -5416,9 +5456,12 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
 
        td->flag = 0;
        td->loc = td2d->loc;
-       copy_v3_v3(td->center, td->loc);
        copy_v3_v3(td->iloc, td->loc);
 
+       //copy_v3_v3(td->center, td->loc);
+       td->center[0] = marker->pos[0] * aspx;
+       td->center[1] = marker->pos[1] * aspy;
+
        memset(td->axismtx, 0, sizeof(td->axismtx));
        td->axismtx[2][2] = 1.0f;
 
@@ -5433,26 +5476,36 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
 }
 
 static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d,
-                             TransDataTracking *tdt, MovieTrackingTrack *track)
+                             TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy)
 {
        MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr);
 
        tdt->flag = marker->flag;
-       marker->flag &= ~(MARKER_DISABLED|MARKER_TRACKED);
+       marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
 
-       markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, track->offset, marker->pos, track->offset);
+       markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
+                             track->offset, marker->pos, track->offset, aspx, aspy);
 
-       if (track->flag & SELECT)
-               markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, marker->pos, NULL, NULL);
+       if (track->flag & SELECT) {
+               markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
+                                     marker->pos, NULL, NULL, aspx, aspy);
+       }
 
        if (track->pat_flag & SELECT) {
-               markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_min, marker->pos, NULL);
-               markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_max, marker->pos, NULL);
+               int a;
+
+               for (a = 0; a < 4; a++) {
+                       markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT,
+                                             marker->pattern_corners[a], marker->pos, NULL, aspx, aspy);
+               }
        }
 
        if (track->search_flag & SELECT) {
-               markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_min, marker->pos, NULL);
-               markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_max, marker->pos, NULL);
+               markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
+                                     marker->search_min, marker->pos, NULL, aspx, aspy);
+
+               markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
+                                     marker->search_max, marker->pos, NULL, aspx, aspy);
        }
 }
 
@@ -5479,6 +5532,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
        MovieTrackingMarker *marker;
        TransDataTracking *tdt;
        int framenr = sc->user.framenr;
+       float aspx, aspy;
 
        /* count */
        t->total = 0;
@@ -5494,7 +5548,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
                                t->total++;
 
                        if (track->pat_flag & SELECT)
-                               t->total+= 2;
+                               t->total+= 4;
 
                        if (track->search_flag & SELECT)
                                t->total+= 2;
@@ -5506,6 +5560,8 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
        if (t->total == 0)
                return;
 
+       ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy);
+
        td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransTracking TransData");
        td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransTracking TransData2D");
        tdt = t->customData = MEM_callocN(t->total*sizeof(TransDataTracking), "TransTracking TransDataTracking");
@@ -5518,25 +5574,23 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
                if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
                        marker = BKE_tracking_get_marker(track, framenr);
 
-                       trackToTransData(sc, td, td2d, tdt, track);
+                       trackToTransData(sc, td, td2d, tdt, track, aspx, aspy);
 
                        /* offset */
                        td++;
                        td2d++;
                        tdt++;
 
-                       if ((marker->flag & MARKER_DISABLED) == 0) {
-                               if (track->flag & SELECT) {
-                                       td++;
-                                       td2d++;
-                                       tdt++;
-                               }
+                       if (track->flag & SELECT) {
+                               td++;
+                               td2d++;
+                               tdt++;
+                       }
 
-                               if (track->pat_flag & SELECT) {
-                                       td += 2;
-                                       td2d += 2;
-                                       tdt +=2;
-                               }
+                       if (track->pat_flag & SELECT) {
+                               td += 4;
+                               td2d += 4;
+                               tdt += 4;
                        }
 
                        if (track->search_flag & SELECT) {
@@ -5688,9 +5742,6 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
        if (!clip || width == 0 || height == 0)
                return;
 
-       if (!ELEM(t->mode, TFM_RESIZE, TFM_TRANSLATION))
-               return;
-
        if (ar->regiontype == RGN_TYPE_PREVIEW) {
                /* transformation was called from graph editor */
                createTransTrackingCurvesData(C, t);
@@ -5758,10 +5809,14 @@ static void cancelTransTracking(TransInfo *t)
 
 void flushTransTracking(TransInfo *t)
 {
+       SpaceClip *sc = t->sa->spacedata.first;
        TransData *td;
        TransData2D *td2d;
        TransDataTracking *tdt;
        int a;
+       float aspx, aspy;
+
+       ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy);
 
        if (t->state == TRANS_CANCEL)
                cancelTransTracking(t);
@@ -5769,31 +5824,46 @@ void flushTransTracking(TransInfo *t)
        /* flush to 2d vector from internally used 3d vector */
        for (a=0, td= t->data, td2d= t->data2d, tdt= t->customData; a<t->total; a++, td2d++, td++, tdt++) {
                if (tdt->mode == transDataTracking_ModeTracks) {
-                       if (t->flag & T_ALT_TRANSFORM) {
-                               if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
-                                       float d[2], d2[2];
+                       float loc2d[2];
 
-                                       if (!tdt->smarkers) {
-                                               tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers");
-                                               for (a = 0; a < tdt->markersnr; a++)
-                                                       copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
-                                       }
+                       if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
+                               continue;
+                       }
 
-                                       sub_v2_v2v2(d, td2d->loc, tdt->soffset);
-                                       sub_v2_v2(d, tdt->srelative);
+                       loc2d[0] = td2d->loc[0] / aspx;
+                       loc2d[1] = td2d->loc[1] / aspy;
 
-                                       sub_v2_v2v2(d2, td2d->loc, tdt->srelative);
+                       if (t->flag & T_ALT_TRANSFORM) {
+                               if (t->mode == TFM_RESIZE) {
+                                       if (tdt->area != TRACK_AREA_PAT)
+                                               continue;
+                               }
+                               else if (t->mode == TFM_TRANSLATION) {
+                                       if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
+                                               float d[2], d2[2];
+
+                                               if (!tdt->smarkers) {
+                                                       tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers");
+                                                       for (a = 0; a < tdt->markersnr; a++)
+                                                               copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
+                                               }
 
-                                       for (a= 0; a<tdt->markersnr; a++)
-                                               add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
+                                               sub_v2_v2v2(d, loc2d, tdt->soffset);
+                                               sub_v2_v2(d, tdt->srelative);
 
-                                       negate_v2_v2(td2d->loc2d, d);
+                                               sub_v2_v2v2(d2, loc2d, tdt->srelative);
+
+                                               for (a= 0; a<tdt->markersnr; a++)
+                                                       add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
+
+                                               negate_v2_v2(td2d->loc2d, d);
+                                       }
                                }
                        }
 
                        if (tdt->area!=TRACK_AREA_POINT || tdt->relative==0) {
-                               td2d->loc2d[0] = td2d->loc[0];
-                               td2d->loc2d[1] = td2d->loc[1];
+                               td2d->loc2d[0] = loc2d[0];
+                               td2d->loc2d[1] = loc2d[1];
 
                                if (tdt->relative)
                                        sub_v2_v2(td2d->loc2d, tdt->relative);
@@ -5805,6 +5875,206 @@ void flushTransTracking(TransInfo *t)
        }
 }
 
+/* * masking * */
+
+typedef struct TransDataMasking{
+       int   is_handle;
+
+       float handle[2], orig_handle[2];
+       float vec[3][3];
+       MaskSplinePoint *point;
+} TransDataMasking;
+
+static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point,
+                                 TransData *td, TransData2D *td2d, TransDataMasking *tdm, int propmode)
+{
+       BezTriple *bezt = &point->bezt;
+       float aspx, aspy;
+       short is_sel_point = MASKPOINT_ISSEL_KNOT(point);
+       short is_sel_any = MASKPOINT_ISSEL_ANY(point);
+
+       tdm->point = point;
+       copy_m3_m3(tdm->vec, bezt->vec);
+
+       ED_space_clip_mask_aspect(sc, &aspx, &aspy);
+
+       if (propmode || is_sel_point) {
+               int i;
+               for (i = 0; i < 3; i++) {
+                       /* CV coords are scaled by aspects. this is needed for rotations and
+                        * proportional editing to be consistent with the stretched CV coords
+                        * that are displayed. this also means that for display and numinput,
+                        * and when the the CV coords are flushed, these are converted each time */
+                       td2d->loc[0] = bezt->vec[i][0]*aspx;
+                       td2d->loc[1] = bezt->vec[i][1]*aspy;
+                       td2d->loc[2] = 0.0f;
+                       td2d->loc2d = bezt->vec[i];
+
+                       td->flag = 0;
+                       td->loc = td2d->loc;
+                       copy_v3_v3(td->center, td->loc);
+                       copy_v3_v3(td->iloc, td->loc);
+
+                       memset(td->axismtx, 0, sizeof(td->axismtx));
+                       td->axismtx[2][2] = 1.0f;
+
+                       td->ext= NULL;
+                       td->val= NULL;
+
+                       if (is_sel_any) {
+                               td->flag |= TD_SELECTED;
+                       }
+                       td->dist= 0.0;
+
+                       unit_m3(td->mtx);
+                       unit_m3(td->smtx);
+
+                       td++;
+                       td2d++;
+               }
+       }
+       else {
+               tdm->is_handle = TRUE;
+
+               BKE_mask_point_handle(point, tdm->handle);
+
+               copy_v2_v2(tdm->orig_handle, tdm->handle);
+
+               td2d->loc[0] = tdm->handle[0]*aspx;
+               td2d->loc[1] = tdm->handle[1]*aspy;
+               td2d->loc[2] = 0.0f;
+               td2d->loc2d = tdm->handle;
+
+               td->flag = 0;
+               td->loc = td2d->loc;
+               copy_v3_v3(td->center, td->loc);
+               copy_v3_v3(td->iloc, td->loc);
+
+               memset(td->axismtx, 0, sizeof(td->axismtx));
+               td->axismtx[2][2] = 1.0f;
+
+               td->ext= NULL;
+               td->val= NULL;
+
+               if (is_sel_any) {
+                       td->flag |= TD_SELECTED;
+               }
+
+               td->dist= 0.0;
+
+               unit_m3(td->mtx);
+               unit_m3(td->smtx);
+
+               td++;
+               td2d++;
+       }
+}
+
+static void createTransMaskingData(bContext *C, TransInfo *t)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       Mask *mask = CTX_data_edit_mask(C);
+       MaskLayer *masklay;
+       TransData *td = NULL;
+       TransData2D *td2d = NULL;
+       TransDataMasking *tdm = NULL;
+       int count = 0, countsel = 0;
+       int propmode = t->flag & T_PROP_EDIT;
+
+       /* count */
+       for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+               MaskSpline *spline = masklay->splines.first;
+
+               if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+                       continue;
+               }
+
+               for (spline = masklay->splines.first; spline; spline = spline->next) {
+                       int i;
+
+                       for (i = 0; i < spline->tot_point; i++) {
+                               MaskSplinePoint *point = &spline->points[i];
+
+                               if (MASKPOINT_ISSEL_ANY(point)) {
+                                       if (MASKPOINT_ISSEL_KNOT(point))
+                                               countsel += 3;
+                                       else
+                                               countsel += 1;
+                               }
+
+                               if (propmode)
+                                       count += 3;
+                       }
+               }
+       }
+
+       /* note: in prop mode we need at least 1 selected */
+       if (countsel == 0) return;
+
+       t->total = (propmode) ? count: countsel;
+       td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransObData(Mask Editing)");
+       /* for each 2d uv coord a 3d vector is allocated, so that they can be
+        * treated just as if they were 3d verts */
+       td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(Mask Editing)");
+       tdm = t->customData = MEM_callocN(t->total*sizeof(TransDataMasking), "TransDataMasking(Mask Editing)");
+
+       t->flag |= T_FREE_CUSTOMDATA;
+
+       /* create data */
+       for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+               MaskSpline *spline = masklay->splines.first;
+
+               if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+                       continue;
+               }
+
+               for (spline = masklay->splines.first; spline; spline = spline->next) {
+                       int i;
+
+                       for (i = 0; i < spline->tot_point; i++) {
+                               MaskSplinePoint *point = &spline->points[i];
+
+                               if (propmode || MASKPOINT_ISSEL_ANY(point)) {
+                                       MaskPointToTransData(sc, point, td, td2d, tdm, propmode);
+
+                                       if (propmode || MASKPOINT_ISSEL_KNOT(point)) {
+                                               td += 3;
+                                               td2d += 3;
+                                               tdm += 3;
+                                       }
+                                       else {
+                                               td++;
+                                               td2d++;
+                                               tdm++;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void flushTransMasking(TransInfo *t)
+{
+       SpaceClip *sc = t->sa->spacedata.first;
+       TransData2D *td;
+       TransDataMasking *tdm;
+       int a;
+       float aspx, aspy, invx, invy;
+
+       ED_space_clip_mask_aspect(sc, &aspx, &aspy);
+       invx = 1.0f/aspx;
+       invy = 1.0f/aspy;
+
+       /* flush to 2d vector from internally used 3d vector */
+       for(a=0, td = t->data2d, tdm = t->customData; a<t->total; a++, td++, tdm++) {
+               td->loc2d[0]= td->loc[0]*invx;
+               td->loc2d[1]= td->loc[1]*invy;
+
+               if (tdm->is_handle)
+                       BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, tdm->orig_handle, tdm->vec);
+       }
+}
+
 void createTransData(bContext *C, TransInfo *t)
 {
        Scene *scene = t->scene;
@@ -5874,6 +6144,15 @@ void createTransData(bContext *C, TransInfo *t)
                t->flag |= T_POINTS|T_2D_EDIT;
                if (t->options & CTX_MOVIECLIP)
                        createTransTrackingData(C, t);
+               else if (t->options & CTX_MASK) {
+                       createTransMaskingData(C, t);
+
+                       if (t->data && (t->flag & T_PROP_EDIT)) {
+                               sort_trans_data(t);     // makes selected become first in array
+                               set_prop_dist(t, TRUE);
+                               sort_trans_data_dist(t);
+                       }
+               }
        }
        else if (t->obedit) {
                t->ext = NULL;