Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_clip/clip_utils.c')
-rw-r--r--source/blender/editors/space_clip/clip_utils.c226
1 files changed, 222 insertions, 4 deletions
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index c7f2a027ba8..271ec219809 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -27,10 +27,12 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
+#include "BKE_mask.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
@@ -44,6 +46,7 @@
#include "WM_types.h"
#include "ED_clip.h"
+#include "ED_mask.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -395,16 +398,231 @@ void clip_delete_plane_track(bContext *C, MovieClip *clip, MovieTrackingPlaneTra
DEG_id_tag_update(&clip->id, 0);
}
-void clip_view_center_to_point(SpaceClip *sc, float x, float y)
+/* Calculate space clip offset to be centered at the given point. */
+void clip_view_offset_for_center_to_point(
+ SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y)
{
int width, height;
+ ED_space_clip_get_size(sc, &width, &height);
+
float aspx, aspy;
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
+
+ *r_offset_x = (x - 0.5f) * width * aspx;
+ *r_offset_y = (y - 0.5f) * height * aspy;
+}
+
+void clip_view_center_to_point(SpaceClip *sc, float x, float y)
+{
+ clip_view_offset_for_center_to_point(sc, x, y, &sc->xof, &sc->yof);
+}
+
+static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2])
+{
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingTrack *track;
+ int width, height;
+ bool ok = false;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ INIT_MINMAX2(min, max);
ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
- sc->xof = (x - 0.5f) * width * aspx;
- sc->yof = (y - 0.5f) * height * aspy;
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (marker) {
+ float pos[3];
+
+ pos[0] = marker->pos[0] + track->offset[0];
+ pos[1] = marker->pos[1] + track->offset[1];
+ pos[2] = 0.0f;
+
+ /* undistortion happens for normalized coords */
+ if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
+ /* undistortion happens for normalized coords */
+ ED_clip_point_undistorted_pos(sc, pos, pos);
+ }
+
+ pos[0] *= width;
+ pos[1] *= height;
+
+ mul_v3_m4v3(pos, sc->stabmat, pos);
+
+ minmax_v2v2_v2(min, max, pos);
+
+ ok = true;
+ }
+ }
+
+ track = track->next;
+ }
+
+ return ok;
+}
+
+static bool tracking_has_selection(SpaceClip *space_clip)
+{
+ MovieClip *clip = ED_space_clip_get_clip(space_clip);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
+
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
+ if (!TRACK_VIEW_SELECTED(space_clip, track)) {
+ continue;
+ }
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ if (marker != NULL) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool mask_has_selection(const bContext *C, bool include_handles)
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ if (mask == NULL) {
+ return false;
+ }
+
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
+ if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
+ for (int i = 0; i < spline->tot_point; i++) {
+ const MaskSplinePoint *point = &spline->points[i];
+ const BezTriple *bezt = &point->bezt;
+ if (!MASKPOINT_ISSEL_ANY(point)) {
+ continue;
+ }
+ if (bezt->f2 & SELECT) {
+ return true;
+ }
+
+ if (!include_handles) {
+ /* Ignore handles. */
+ }
+ else if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ return true;
+ }
+ else {
+ if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
+ return true;
+ }
+ if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool selected_boundbox(const bContext *C, float min[2], float max[2], bool include_handles)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ if (sc->mode == SC_MODE_TRACKING) {
+ return selected_tracking_boundbox(sc, min, max);
+ }
+
+ if (ED_mask_selected_minmax(C, min, max, include_handles)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
+ ED_space_clip_get_size(sc, &width, &height);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, min, min);
+ BKE_mask_coord_to_movieclip(clip, &sc->user, max, max);
+ min[0] *= width;
+ min[1] *= height;
+ max[0] *= width;
+ max[1] *= height;
+ return true;
+ }
+ return false;
+}
+
+bool clip_view_calculate_view_selection(
+ const bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+
+ int frame_width, frame_height;
+ ED_space_clip_get_size(sc, &frame_width, &frame_height);
+
+ if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) {
+ return false;
+ }
+
+ /* NOTE: The `fit` argument is set to truth when doing "View to Selected" operator, and it set to
+ * false when this function is used for Lock-to-Selection functionality. When locking to
+ * selection the handles are to be ignored. So we can derive the `include_handles` from `fit`.
+ *
+ * TODO(sergey): Make such decision more explicit. Maybe pass use-case for the calculation to
+ * tell operator from lock-to-selection apart. */
+ float min[2], max[2];
+ if (!selected_boundbox(C, min, max, fit)) {
+ return false;
+ }
+
+ /* center view */
+ clip_view_offset_for_center_to_point(sc,
+ (max[0] + min[0]) / (2 * frame_width),
+ (max[1] + min[1]) / (2 * frame_height),
+ r_offset_x,
+ r_offset_y);
+
+ const int w = max[0] - min[0];
+ const int h = max[1] - min[1];
+
+ /* set zoom to see all selection */
+ *r_zoom = sc->zoom;
+ if (w > 0 && h > 0) {
+ ARegion *region = CTX_wm_region(C);
+
+ int width, height;
+ float zoomx, zoomy, newzoom, aspx, aspy;
+
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
+
+ width = BLI_rcti_size_x(&region->winrct) + 1;
+ height = BLI_rcti_size_y(&region->winrct) + 1;
+
+ zoomx = (float)width / w / aspx;
+ zoomy = (float)height / h / aspy;
+
+ newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy));
+
+ if (fit) {
+ *r_zoom = newzoom;
+ }
+ }
+
+ return true;
+}
+
+/* Returns truth if lock-to-selection is enabled and possible.
+ * Locking to selection is not possible if there is no selection. */
+bool clip_view_has_locked_selection(const bContext *C)
+{
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+
+ if ((space_clip->flag & SC_LOCK_SELECTION) == 0) {
+ return false;
+ }
+
+ if (space_clip->mode == SC_MODE_TRACKING) {
+ return tracking_has_selection(space_clip);
+ }
+
+ return mask_has_selection(C, false);
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)