diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index ac5b4fe52f4..90b3901c002 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -54,7 +54,8 @@ class CLIP_HT_header(Header): if clip: if sc.view == 'CLIP': layout.prop(sc, "mode", text="") - if sc.view == 'GRAPH': + layout.prop(sc, "pivot_point", text="", icon_only=True) + elif sc.view == 'GRAPH': row = layout.row(align=True) if sc.show_filters: diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index bb944eaf429..2e30f756b43 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7612,6 +7612,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) { MovieClip *clip; + bScreen *sc; for (clip = main->movieclip.first; clip; clip = clip->id.next) { MovieTrackingTrack *track; @@ -7643,6 +7644,24 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track = track->next; } } + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + if (sclip->around == 0) { + sclip->around = V3D_CENTROID; + } + } + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 846100b0d19..7e1505b652f 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -58,6 +58,7 @@ struct Mask *ED_space_clip_mask(struct SpaceClip *sc); void ED_space_clip_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy); void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy); +void ED_space_clip_aspect_dimension_aware(struct SpaceClip *sc, float *aspx, float *aspy); void ED_space_clip_mask_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_mask_aspect(struct SpaceClip *sc, float *aspx, float *aspy); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index afcd18dfbe8..f16ef21b707 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -249,9 +249,15 @@ void ED_space_clip_size(SpaceClip *sc, int *width, int *height) void ED_space_clip_mask_size(SpaceClip *sc, int *width, int *height) { - if(!sc->mask) { - *width= 0; - *height= 0; + /* quite the same as ED_space_clip_size, but it also runs aspect correction on output resolution + * this is needed because mask should be rasterized with exactly the same resolution as + * currently displaying frame and it doesn't have access to aspect correction currently + * used for display. (sergey) + */ + + if (!sc->mask) { + *width = 0; + *height = 0; } else { float aspx, aspy; @@ -306,6 +312,33 @@ void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy) *aspx = *aspy = 1.0f; } +void ED_space_clip_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy) +{ + int w, h; + + /* most of tools does not require aspect to be returned with dimensions correction + * due to they're invariant to this stuff, but some transformation tools like rotation + * should be aware of aspect correction caused by different resolution in different + * directions. + * mainly this is sued for transformation stuff + */ + + ED_space_clip_aspect(sc, aspx, aspy); + ED_space_clip_size(sc, &w, &h); + + *aspx *= (float)w; + *aspy *= (float)h; + + if(*aspx < *aspy) { + *aspy= *aspy / *aspx; + *aspx= 1.0f; + } + else { + *aspx= *aspx / *aspy; + *aspy= 1.0f; + } +} + void ED_clip_update_frame(const Main *mainp, int cfra) { wmWindowManager *wm; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index b4810a22608..6ebcaf4ea16 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -35,6 +35,7 @@ #include "DNA_scene_types.h" #include "DNA_mask_types.h" #include "DNA_movieclip_types.h" +#include "DNA_view3d_types.h" /* for pivot point */ #include "MEM_guardedalloc.h" @@ -239,6 +240,7 @@ static SpaceLink *clip_new(const bContext *C) sc->zoom = 1.0f; sc->path_length = 20; sc->scopes.track_preview_height = 120; + sc->around = V3D_LOCAL; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for clip"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d3626851173..06bcf11bfe4 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -244,21 +244,17 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) } else if (t->spacetype==SPACE_CLIP) { float v[2]; + float aspx = 1.0f, aspy = 1.0f; copy_v2_v2(v, vec); - if (t->options & CTX_MOVIECLIP) { - float aspx, aspy; - ED_space_clip_aspect(t->sa->spacedata.first, &aspx, &aspy); - v[0] /= aspx; - v[1] /= aspy; - } - else if (t->options & CTX_MASK) { - float aspx, aspy; + if (t->options & CTX_MOVIECLIP) + ED_space_clip_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); + else if (t->options & CTX_MASK) ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); - v[0] /= aspx; - v[1] /= aspy; - } + + v[0] /= aspx; + v[1] /= aspy; UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); } @@ -316,12 +312,10 @@ void applyAspectRatio(TransInfo *t, float vec[2]) if (t->options & CTX_MOVIECLIP) { - int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); - vec[0] *= width / aspx; - vec[1] *= height / aspy; + vec[0] /= aspx; + vec[1] /= aspy; } else if (t->options & CTX_MASK) { ED_space_clip_mask_aspect(sc, &aspx, &aspy); @@ -357,12 +351,10 @@ void removeAspectRatio(TransInfo *t, float vec[2]) float aspx, aspy; if (t->options & CTX_MOVIECLIP) { - int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); - vec[0] *= aspx / width; - vec[1] *= aspy / height; + vec[0] *= aspx; + vec[1] *= aspy; } else if (t->options & CTX_MASK) { ED_space_clip_aspect(sc, &aspx, &aspy); @@ -711,7 +703,7 @@ int transformEvent(TransInfo *t, wmEvent *event) t->redraw |= TREDRAW_HARD; } else if (t->mode == TFM_TRANSLATION) { - if(t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { restoreTransObjects(t); t->flag ^= T_ALT_TRANSFORM; @@ -721,7 +713,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_ROTATE: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -748,6 +740,14 @@ int transformEvent(TransInfo *t, wmEvent *event) initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; } + else if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } + } break; case TFM_MODAL_SNAP_INV_ON: @@ -976,7 +976,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case RKEY: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE)) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -2737,6 +2737,9 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { copy_v3_v3(center, td->center); } + else if (t->options & CTX_MOVIECLIP) { + copy_v3_v3(center, td->center); + } else { copy_v3_v3(center, t->center); } @@ -3020,6 +3023,10 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short { center = td->center; } + + if (t->options & CTX_MOVIECLIP) { + center = td->center; + } } if (t->flag & T_POINTS) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 1ea32b78a9e..85d54c0d6e3 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5388,23 +5388,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, float *rel, float *off, 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 */ } @@ -5418,8 +5419,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); @@ -5430,9 +5431,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; @@ -5447,28 +5451,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); - 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, marker->pattern_corners[0], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[1], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[2], marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, marker->pattern_corners[3], 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, + track->search_min, marker->pos, NULL, aspx, aspy); + + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, + track->search_max, marker->pos, NULL, aspx, aspy); } } @@ -5495,6 +5507,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) MovieTrackingMarker *marker; TransDataTracking *tdt; int framenr = sc->user.framenr; + float aspx, aspy; /* count */ t->total = 0; @@ -5522,6 +5535,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"); @@ -5534,7 +5549,7 @@ 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++; @@ -5704,9 +5719,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); @@ -5774,10 +5786,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); @@ -5785,31 +5801,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; atotal; a++, td2d++, td++, tdt++) { if (tdt->mode == transDataTracking_ModeTracks) { + float loc2d[2]; + + 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 (tdt->area == TRACK_AREA_POINT && tdt->relative) { - float d[2], d2[2]; + 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); + 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, loc2d, tdt->soffset); + sub_v2_v2(d, tdt->srelative); + + sub_v2_v2v2(d2, loc2d, tdt->srelative); + + for (a= 0; amarkersnr; a++) + add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); + + negate_v2_v2(td2d->loc2d, d); } - - sub_v2_v2v2(d, td2d->loc, tdt->soffset); - sub_v2_v2(d, tdt->srelative); - - sub_v2_v2v2(d2, td2d->loc, tdt->srelative); - - for (a= 0; amarkersnr; 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); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d2f27b87b8c..e3ca0957c25 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -660,6 +660,10 @@ static void recalcData_spaceclip(TransInfo *t) if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); } + else if (t->mode == TFM_ROTATION) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + } } track = track->next; @@ -1114,6 +1118,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->view = &ar->v2d; t->around = sipo->around; } + else if (t->spacetype==SPACE_CLIP) { + SpaceClip *sclip = sa->spacedata.first; + t->view = &ar->v2d; + t->around = sclip->around; + } else { if (ar) { // XXX for now, get View2D from the active region diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 640961f80f2..da07ffd7f9a 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -532,7 +532,7 @@ typedef struct SpaceClip { short dope_sort; /* sort order in dopesheet view */ short dope_flag; /* dopsheet view flags */ - int pad3; + int around; /* pivot point for transforms */ /* **** mask editing **** */ struct Mask *mask; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d63110c4646..b2c13f8717a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2989,6 +2989,16 @@ static void rna_def_space_clip(BlenderRNA *brna) {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)"}, + {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, + "Individual Origins", "Pivot around each object's own origin"}, + {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point", + "Pivot around the median point of selected objects"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SpaceClipEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceClip"); RNA_def_struct_ui_text(srna, "Space Clip Editor", "Clip editor space data"); @@ -3182,6 +3192,13 @@ static void rna_def_space_clip(BlenderRNA *brna) 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"); + RNA_def_property_enum_items(prop, pivot_items); + RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); + /* ** dopesheet ** */ /* dopesheet sort */