svn merge ^/trunk/blender -r47603:47611
authorCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2012 14:49:07 +0000 (14:49 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2012 14:49:07 +0000 (14:49 +0000)
1  2 
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/makesrna/intern/rna_space.c

index 429a3b3d86ac47291463f2285ddbbb462ebd7ef7,ce65127c89696f916d3fec050fa1db6314401ba4..007ec3c5250745490114cdd5e44db8761e7fa0e3
@@@ -2797,6 -2797,99 +2797,99 @@@ static void posttrans_gpd_clean (bGPdat
        }
  }
  
+ /* Called by special_aftertrans_update to make sure selected gp-frames replace
+  * any other gp-frames which may reside on that frame (that are not selected).
+  * It also makes sure sorted are still stored in chronological order after
+  * transform.
+  */
+ static void posttrans_mask_clean(Mask *mask)
+ {
+       MaskLayer *masklay;
+       for (masklay = mask->masklayers.first; masklay; masklay= masklay->next) {
+               ListBase sel_buffer = {NULL, NULL};
+               MaskLayerShape *masklay_shape, *masklay_shape_new;
+               MaskLayerShape *masklay_shape_sort, *masklay_shape_sort_new;
+               /* loop 1: loop through and isolate selected gp-frames to buffer
+                * (these need to be sorted as they are isolated)
+                */
+               for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape_new) {
+                       short added= 0;
+                       masklay_shape_new= masklay_shape->next;
+                       if (masklay_shape->flag & GP_FRAME_SELECT) {
+                               BLI_remlink(&masklay->splines_shapes, masklay_shape);
+                               /* find place to add them in buffer
+                                * - go backwards as most frames will still be in order,
+                                *   so doing it this way will be faster
+                                */
+                               for (masklay_shape_sort= sel_buffer.last; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort->prev) {
+                                       /* if current (masklay_shape) occurs after this one in buffer, add! */
+                                       if (masklay_shape_sort->frame < masklay_shape->frame) {
+                                               BLI_insertlinkafter(&sel_buffer, masklay_shape_sort, masklay_shape);
+                                               added= 1;
+                                               break;
+                                       }
+                               }
+                               if (added == 0)
+                                       BLI_addhead(&sel_buffer, masklay_shape);
+                       }
+               }
+               /* error checking: it is unlikely, but may be possible to have none selected */
+               if (sel_buffer.first == NULL)
+                       continue;
+               /* if all were selected (i.e. masklay->splines_shapes is empty), then just transfer sel-buf over */
+               if (masklay->splines_shapes.first == NULL) {
+                       masklay->splines_shapes.first= sel_buffer.first;
+                       masklay->splines_shapes.last= sel_buffer.last;
+                       continue;
+               }
+               /* loop 2: remove duplicates of splines_shapes in buffers */
+               for (masklay_shape= masklay->splines_shapes.first; masklay_shape && sel_buffer.first; masklay_shape= masklay_shape_new) {
+                       masklay_shape_new= masklay_shape->next;
+                       /* loop through sel_buffer, emptying stuff from front of buffer if ok */
+                       for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort && masklay_shape; masklay_shape_sort= masklay_shape_sort_new) {
+                               masklay_shape_sort_new= masklay_shape_sort->next;
+                               /* if this buffer frame needs to go before current, add it! */
+                               if (masklay_shape_sort->frame < masklay_shape->frame) {
+                                       /* transfer buffer frame to splines_shapes list (before current) */
+                                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                                       BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
+                               }
+                               /* if this buffer frame is on same frame, replace current with it and stop */
+                               else if (masklay_shape_sort->frame == masklay_shape->frame) {
+                                       /* transfer buffer frame to splines_shapes list (before current) */
+                                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                                       BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
+                                       /* get rid of current frame */
+                                       BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+                               }
+                       }
+               }
+               /* if anything is still in buffer, append to end */
+               for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort_new) {
+                       masklay_shape_sort_new= masklay_shape_sort->next;
+                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                       BLI_addtail(&masklay->splines_shapes, masklay_shape_sort);
+               }
+               /* NOTE: this is the only difference to grease pencil code above */
+               BKE_mask_layer_shape_sort(masklay);
+       }
+ }
  /* Called during special_aftertrans_update to make sure selected keyframes replace
   * any other keyframes which may reside on that frame (that is not selected).
   */
@@@ -2936,6 -3029,27 +3029,27 @@@ static int count_gplayer_frames(bGPDlay
        return count;
  }
  
+ /* fully select selected beztriples, but only include if it's on the right side of cfra */
+ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra)
+ {
+       MaskLayerShape *masklayer_shape;
+       int count = 0;
+       if (masklay == NULL)
+               return count;
+       /* only include points that occur on the right side of cfra */
+       for (masklayer_shape= masklay->splines_shapes.first; masklayer_shape; masklayer_shape= masklayer_shape->next) {
+               if (masklayer_shape->flag & MASK_SHAPE_SELECT) {
+                       if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra))
+                               count++;
+               }
+       }
+       return count;
+ }
  /* This function assigns the information to transdata */
  static void TimeToTransData(TransData *td, float *time, AnimData *adt)
  {
@@@ -2998,7 -3112,7 +3112,7 @@@ typedef struct tGPFtransdata 
  } tGPFtransdata;
  
  /* This function helps flush transdata written to tempdata into the gp-frames  */
- void flushTransGPactionData(TransInfo *t)
+ void flushTransIntFrameActionData(TransInfo *t)
  {
        tGPFtransdata *tfd;
        int i;
@@@ -3049,6 -3163,35 +3163,35 @@@ static int GPLayerToTransData (TransDat
        return count;
  }
  
+ /* refer to comment above #GPLayerToTransData, this is the same but for masks */
+ static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra)
+ {
+       MaskLayerShape *masklay_shape;
+       int count= 0;
+       /* check for select frames on right side of current frame */
+       for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape->next) {
+               if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+                       if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
+                               /* memory is calloc'ed, so that should zero everything nicely for us */
+                               td->val= &tfd->val;
+                               td->ival= (float)masklay_shape->frame;
+                               tfd->val= (float)masklay_shape->frame;
+                               tfd->sdata= &masklay_shape->frame;
+                               /* advance td now */
+                               td++;
+                               tfd++;
+                               count++;
+                       }
+               }
+       }
+       return count;
+ }
  static void createTransActionData(bContext *C, TransInfo *t)
  {
        Scene *scene= t->scene;
                return;
        
        /* filter data */
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
        else
                filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
                
                if (ale->type == ANIMTYPE_FCURVE)
                        count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
-               else
+               else if (ale->type == ANIMTYPE_GPLAYER)
                        count += count_gplayer_frames(ale->data, t->frame_side, cfra);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       count += count_masklayer_frames(ale->data, t->frame_side, cfra);
+               else
+                       BLI_assert(0);
        }
        
        /* stop if trying to build list if nothing selected */
        td= t->data;
        td2d = t->data2d;
        
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                if (t->mode == TFM_TIME_SLIDE) {
                        t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata");
                        tfd= (tGPFtransdata *)((float *)(t->customData) + 2);
                        td += i;
                        tfd += i;
                }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       MaskLayer *masklay = (MaskLayer *)ale->data;
+                       int i;
+                       i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra);
+                       td += i;
+                       tfd += i;
+               }
                else {
                        AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
                        FCurve *fcu= (FCurve *)ale->key_data;
@@@ -5004,6 -5159,26 +5159,26 @@@ void special_aftertrans_update(bContex
                                }
                        }
                }
+               else if (ac.datatype == ANIMCONT_MASK) {
+                       /* remove duplicate frames and also make sure points are in order! */
+                               /* 3 cases here for curve cleanups:
+                                * 1) NOTRANSKEYCULL on     -> cleanup of duplicates shouldn't be done
+                                * 2) canceled == 0        -> user confirmed the transform, so duplicates should be removed
+                                * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
+                                */
+                       if ((saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
+                               ((canceled == 0) || (duplicate)))
+                       {
+                               Mask *mask;
+                               // XXX: BAD! this get gpencil datablocks directly from main db...
+                               // but that's how this currently works :/
+                               for (mask = G.main->mask.first; mask; mask = mask->id.next) {
+                                       if (ID_REAL_USERS(mask))
+                                               posttrans_mask_clean(mask);
+                               }
+                       }
+               }
                
                /* marker transform, not especially nice but we may want to move markers
                 * at the same time as keyframes in the dope sheet. 
                }
                
                /* make sure all F-Curves are set correctly */
-               if (ac.datatype != ANIMCONT_GPENCIL)
+               if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                        ANIM_editkeyframes_refresh(&ac);
                
                /* clear flag that was set for time-slide drawing */
@@@ -5413,24 -5588,23 +5588,24 @@@ typedef struct TransDataTracking 
        short coord;
  } TransDataTracking;
  
 -static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track,
 -                                  int area, float loc[2], float rel[2], const float off[2])
 +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 */
        }
  
        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);
  
        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;
  
  }
  
  static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d,
 -                             TransDataTracking *tdt, MovieTrackingTrack *track)
 +                             TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy)
  {
        int framenr = ED_space_clip_clip_framenr(sc);
        MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, 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);
        }
  }
  
@@@ -5533,7 -5694,6 +5708,7 @@@ static void createTransTrackingTracksDa
        MovieTrackingMarker *marker;
        TransDataTracking *tdt;
        int framenr = ED_space_clip_clip_framenr(sc);
 +      float aspx, aspy;
  
        /* count */
        t->total = 0;
                                t->total++;
  
                        if (track->pat_flag & SELECT)
 -                              t->total+= 2;
 +                              t->total+= 4;
  
                        if (track->search_flag & SELECT)
                                t->total+= 2;
        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");
                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) {
@@@ -5743,6 -5903,9 +5918,6 @@@ static void createTransTrackingData(bCo
        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);
@@@ -5810,14 -5973,10 +5985,14 @@@ static void cancelTransTracking(TransIn
  
  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);
        /* 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;
 +                      }
 +
 +                      loc2d[0] = td2d->loc[0] / aspx;
 +                      loc2d[1] = td2d->loc[1] / aspy;
 +
 +                      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);
 +                                              }
  
 -                                      sub_v2_v2v2(d, td2d->loc, tdt->soffset);
 -                                      sub_v2_v2(d, tdt->srelative);
 +                                              sub_v2_v2v2(d, loc2d, tdt->soffset);
 +                                              sub_v2_v2(d, tdt->srelative);
  
 -                                      sub_v2_v2v2(d2, td2d->loc, tdt->srelative);
 +                                              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);
 +                                              for (a= 0; a<tdt->markersnr; a++)
 +                                                      add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
  
 -                                      negate_v2_v2(td2d->loc2d, d);
 +                                              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);
index 46ee80aff5b0b3b08cadf54cf7affcbad6bfa8d5,e0920e323aa7608a377fe98895ea260a70b73ba5..1b8cc14ecacb6e1acf0454dc666f663c27d74316
@@@ -350,9 -350,9 +350,9 @@@ static void recalcData_actedit(TransInf
        ANIM_animdata_context_getdata(&ac);
        
        /* perform flush */
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                /* flush transform values back to actual coordinates */
-               flushTransGPactionData(t);
+               flushTransIntFrameActionData(t);
        }
        else {
                /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
@@@ -643,30 -643,23 +643,30 @@@ static void recalcData_spaceclip(TransI
                MovieClip *clip = ED_space_clip(sc);
                ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking);
                MovieTrackingTrack *track;
 +              int framenr = sc->user.framenr;
  
                flushTransTracking(t);
  
                track = tracksbase->first;
                while (track) {
                        if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) {
 +                              MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
 +
                                if (t->mode == TFM_TRANSLATION) {
                                        if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
 -                                              BKE_tracking_clamp_track(track, CLAMP_PAT_POS);
 +                                              BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS);
                                        if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
 -                                              BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS);
 +                                              BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_POS);
                                }
                                else if (t->mode == TFM_RESIZE) {
                                        if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
 -                                              BKE_tracking_clamp_track(track, CLAMP_PAT_DIM);
 +                                              BKE_tracking_clamp_marker(marker, CLAMP_PAT_DIM);
                                        if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
 -                                              BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
 +                                              BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_DIM);
 +                              }
 +                              else if (t->mode == TFM_ROTATION) {
 +                                      if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
 +                                              BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS);
                                }
                        }
  
index a57c39967fc8abf4dde5ba809bddca40f8d0c926,082c7c406e2c1eacb60d87547871928a6b25cc50..6755f7b7e78e2922f10bd261a733582f3b9c89fa
@@@ -2229,6 -2229,7 +2229,7 @@@ static void rna_def_space_dopesheet(Ble
                {SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
                {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
                {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
+               {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"},
                {0, NULL, 0, NULL, NULL}
        };
                
@@@ -3001,12 -3002,6 +3002,12 @@@ static void rna_def_space_clip(BlenderR
                {0, NULL, 0, NULL, NULL}
        };
  
 +      static EnumPropertyItem gpencil_source_items[] = {
 +              {SC_GPENCIL_SRC_CLIP, "CLIP", 0, "Clip", "Show grease pencil datablock which belongs to movie clip"},
 +              {SC_GPENCIL_SRC_TRACK, "TRACK", 0, "Track", "Show grease pencil datablock which belongs to active track"},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +
        static EnumPropertyItem pivot_items[] = {
                {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
                             "Pivot around bounding box center of selected object(s)"},
        RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
        RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
  
 +      /* grease pencil source */
 +      prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_sdna(prop, NULL, "gpencil_src");
 +      RNA_def_property_enum_items(prop, gpencil_source_items);
 +      RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from");
 +      RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
 +
        /* pivot point */
        prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "around");