diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index d08786e6ba8..c2a26c8c1041228c6e4298 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -6621960,7 +6621960,7 @@ def _template_items_clip_tool_tweak_selectionkm_mask_editing(params):
{"properties": [
("extend", False),
("deselect_all", True),
- ("activate_selected", params.select_mouse == 'LEFTMOUSE')]}
+ ("use_tweak_transform("mask.select_more", params.select_mouse == 'RIGHTMOUSE')]}
),
]
@@ -6631,7 +6631,7 @@ def _template_items_clip_tool_tweak_selection(params):
{"properties": [
("extend"{"type": 'NUMPAD_PLUS', False),
("deselect_all""value": 'PRESS', True),
- ("activate_selected""ctrl": True, True)]}
+ ("use_tweak_transform""repeat": True}, False)]}None),
("mask.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
)*_template_items_hide_reveal_actions("mask.hide_view_set", "mask.hide_view_clear"),
@@ -6641,9 +6641,9 @@ def _template_items_clip_tool_tweak_selection(params):- ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True}, None),
+ # ("clip.select", {"type": params.select_mouse, def _template_items_clip_tool_tweak(params):
return ["value": 'PRESS', "ctrl": True}, None),
("clip.change_frame""mask.cyclic_toggle", {"type": 'LEFTMOUSE'C', "value": 'PRESS'}, None),
- *_template_items_clip_tool_tweak_selection(params"alt": True}, None),
("clip.slide_marker""mask.handle_type_set", {"type": 'LEFTMOUSE'V', "value": 'PRESS'}, None),
("clip.slide_plane_marker", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None)"mask.normals_make_consistent",
+ *_template_items_clip_tool_tweak_selection@@ -3188,10 +3188,10 @@ def km_clip_editor(params),
]:
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h ("clip.frame_jump", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "alt": True, "repeat": True},
index 89278794baa..b0a2382046f 100644 {"properties": [("position", 'PATHSTART')]}),
--- a/source/blender/editors/space_clip/clip_intern.h ("clip.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+++ b/source/blender/editors/space_clip/clip_intern.h- ("clip.select", {"type": params.select_mouse, "value": 'PRESS'},
@@ -188,11 +188,6 @@ void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);- {"properties": [("deselect_all", not params.legacy)]}),
- ("clip.select", {"type": params.select_mouse, /* tracking_ops.c */"value": 'PRESS', "shift": True},
-/* Find track which can be slid in a proximity of the given event.- {"properties": [("extend", True)]}),
- * Uses the same distance tolerance rule as the "Slide Marker" operator.+ # ("clip.select", {"type": params.select_mouse, */"value": 'PRESS'},
-struct MovieTrackingTrack *tracking_find_slidable_track_in_proximity(struct bContext *C+ # {"properties": [("deselect_all", not params.legacy)]}),
-+ const float co[2]);# ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
-+ # {"properties": [("extend", True)]}),
void CLIP_OT_add_marker(struct wmOperatorType *ot); *_template_items_select_actions(params, "clip.select_all"),
void CLIP_OT_add_marker_at_click(struct wmOperatorType *ot); ("clip.select_box", {"type": 'B', "value": 'PRESS'}, None),
void CLIP_OT_delete_track(struct wmOperatorType *ot); ("clip.select_circle", {"type": 'C', "value": 'PRESS'}, None),
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c@@ -6623,6 +6623,8 @@ def _template_items_clip_tool_tweak_selection(params):
index ca224b04da5..f325a4f518f 100644 ("deselect_all", True),
--- a/source/blender/editors/space_clip/tracking_ops.c ("activate_selected", params.select_mouse == 'LEFTMOUSE')]}
+++ b/source/blender/editors/space_clip/tracking_ops.c ),
@@ -635,12 +635,6 @@ static MovieTrackingTrack *tracking_marker_check_slide(+ ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
return NULL;+ {"properties": [("extend", True)]}),
} ]
-struct MovieTrackingTrack *tracking_find_slidable_track_in_proximity(struct bContext *C,
- const float co[2])
-{
- return tracking_marker_check_slide(C, co, NULL, NULL, NULL);
-}
-
static void *slide_marker_customdata(bContext *C, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C); if params.select_mouse == 'RIGHTMOUSE':
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index b6d458a7780..f21f3a6fdc5cca09e7f049 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -11,6 +11,7 @@
#include "DNA_scene_types.h"
#include "BLI_lasso_2d.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
@@ -36,226 +37,411 @@432 @@
#include "clip_intern.h" /* own include */
#include "tracking_ops_intern.h" /* own include */
-static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2]);
+/* -------------------------------------------------------------------- */
+/** \name Point track marker picking.
+ * \{ */
-/********************** mouse select operator *********************/
+typedef enum eTrackPickAreaDetail {
+ TRACK_PICK_AREA_DETAIL_NONE,
+
+ /* Position of the marker (when area is TRACK_AREA_POINT).
+ * Position of the pattern corner when area is TRACK_AREA_PAT and corner != -1. */
+ TRACK_PICK_AREA_DETAIL_POSITION,
+
+ /* Size and offset of the search area. */
+ TRACK_PICK_AREA_DETAIL_SIZE,
+ TRACK_PICK_AREA_DETAIL_OFFSET,
+
+ /* "Widget" used to define pattern rotation and scale. */
+ TRACK_PICK_AREA_DETAIL_TILT_SIZE,
+
+ /* Edge of pattern or search area. */
+ TRACK_PICK_AREA_DETAIL_EDGE,
+} eTrackPickAreaDetail;
+
+typedef struct TrackPickResult {
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker;
-static int mouse_on_side(
- const float co[2], float x1, float y1, float x2, float y2, float epsx, float epsy)
+ /* Picked area of the track. Is a single element from eTrackArea (no multiple choices are
+ * possible). */
+ eTrackArea area;
+ eTrackPickAreaDetail area_detail;
+
+ /* When a pattern corner is picked is 0-based index of the corner.
+ * Otherwise is -1. */
+ int corner_index;
+
+ /* Distance to the pick measured in squared pixels. */
+ float distance_px_squared;
+} TrackPickResult;
+
+BLI_INLINE TrackPickResult track_pick_result_make_null(void)
{
- if (x1 > x2) {
- SWAP(float, x1, x2);
- }
+ TrackPickResult result = {NULL};
+
+ result.area = TRACK_AREA_NONE;
+ result.area_detail = TRACK_PICK_AREA_DETAIL_NONE;
+ result.corner_index = -1;
+ result.distance_px_squared = FLT_MAX;
+
+ return result;
+}
- if (y1 > y2) {
- SWAP(float, y1, y2);
- }+BLI_INLINE bool track_pick_result_can_slide(const TrackPickResult *pick_result)
+ result.area = TRACK_AREA_NONE;+{
+ result.area_detail = TRACK_PICK_AREA_DETAIL_NONE;+ if (pick_result->marker == NULL) {
+ result.corner_index = -1;+ return false;
+ result.distance_px_squared = FLT_MAX; }
- return (co[0] >= x1 - epsx && co[0] <= x2 + epsx) && (co[1] >= y1 - epsy && co[1] <= y2 + epsy);
+ return pick_result;t->area_detail != TRACK_PICK_AREA_DETAIL_EDGE;
}
-static int mouse_on_rect(const float co[2],
- const float pos[2],
- const float min[2],
- const float max[2],
- float epsx,
- float epsy)
+static void slide_marker_tilt_slider_relative(const float pattern_corners[4][2], float r_slider[2])
{
- 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);
+ add_v2_v2v2(r_slider, pattern_corners[1], pattern_corners[2]);
}
-static int mouse_on_crns(
- const float co[2], const float pos[2], const float crns[4][2], float epsx, float epsy)
+static void slide_marker_tilt_slider(const float marker_pos[2],
+ const float pattern_corners[4][2],
+ float r_slider[2])
{
- float dist = dist_to_crns(co, pos, crns);
-
- return dist < max_ff(epsx, epsy);
+ slide_marker_tilt_slider_relative(pattern_corners, r_slider);
+ add_v2_v2(r_slider, marker_pos);
}+}
-static int track_mouse_area(const bContext *C, const float co[2]- return dist < max_ff(epsx, MovieTrackingTrack *track)epsy);
+static float mouse_to_slide_zone_distance_squared(const float co[2],
+ const float slide_zone[2],
+ int width,
+ int height)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
- int framenr = ED_space_clip_get_clip_frame_number(sc);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- float pat_min[2], pat_max[2];
- float epsx, epsy;
- int width, height;
-
- ED_space_clip_get_size(sc, &width, &height);+{
+ const float pixel_co[2] = {co[0] * width, co[1] * height},
+ pixel_slide_zone[2] = {slide_zone[0] * width, slide_zone[1] * height};
+ return square_f(pixel_co[0] - pixel_slide_zone[0]) + square_f(pixel_co[1] - pixel_slide_zone[1]);
+} }
- BKE_-static int tracking_marker_pattern_minmax(marker, pat_min_mouse_area(const bContext *C, pat_max);
-
- epsx = min_ffff(pat_min[0] - marker->search_min[0],
- marker->search_max[0] - pat_max[0],
- fabsf(pat_min[0]),
- fabsf(pat_max[0])) /
- 2;
- epsy = min_ffff(pat_min[1] - marker->search_min[1],
- marker->search_max[1] - pat_max[1],
- fabsf(pat_min[1]),
- fabsf(pat_max[1])) /
- 2;
-
- epsx = max_ff(epsxconst float co[2], 2.0f / width);MovieTrackingTrack *track)
- epsy = max_ff(epsy, 2.0f / height);+static float mouse_to_search_corner_distance_squared(
-+ const MovieTrackingMarker *marker, const float co[2], int corner, int width, int height)
- if (sc->flag & SC_SHOW_MARKER_SEARCH) {
- if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy)) {- SpaceClip *sc = CTX_wm_space_clip(C);
- return TRACK_AREA_SEARCH;- int framenr = ED_space_clip_get_clip_frame_number(sc);
- }- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+static- float mouse_to_search_corner_distance_squared(pat_min[2], pat_max[2];
+ const MovieTrackingMarker *marker, const- float co[2], int corner, int widtht epsx, int height)epsy;
+{- int width, height;
+ float side_zone[2];
+ if (corner == 0) {
+ side_zone[0] = marker->pos[0] + marker->search_max[0];
+ side_zone[1] = marker->pos[1] + marker->search_min[1];
}+ }
+ else {
+ side_zone[0] = marker->pos[0] + marker->search_min[0];
+ side_zone[1] = marker->pos[1] + marker->search_max[1];
+ }
+ return mouse_to_slide_zone_distance_squared(co, side_zone, width, height);
+}
- if ((marker->flag & MARKER_DISABLED) == 0) {
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- if (mouse_on_crns(co, marker->pos, marker->pattern_cornersED_space_clip_get_size(sc, epsx&width, 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) {
- return TRACK_AREA_POINT&height);
+static float mouse_to_closest_pattern_corner_distance_squared(
+ const MovieTrackingMarker *marker, const float co[2], int width, int height, int *r_corner)
+{
+ float min_distance_squared = FLT_MAX;
+ for (int i = 0; i < 4; i++) {
+ float corner_co[2];
+ add_v2_v2v2(corner_co, marker->pattern_corners[i], marker->pos);
+ float distance_squared = mouse_to_slide_zone_distance_squared(co, corner_co, width, height);
+ if (distance_squared < min_distance_squared) {
+ min_distance_squared = distance_squared;
+ *r_corner = i;
}
+ }
-
- return TRACK_AREA_NONE;+ }
+ return min_distance_squared;
}
-static float dist_to_rect(const float co[2],
- const float pos[2],
- const float min[2],+}
- const float max[2])+
+static float mouse_to_offset_distance_squared(const MovieTrackingTrack *track,
+ const MovieTrackingMarker *marker,
+ const float co[2],
+ int width,
+ int height)
{
- float d1, d2, d3, d4;
- const float p[2] = {co[0] - pos[0], co[1] - pos[1]};
- const float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
- const float v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};
-
- d1 = dist_squared_to_line_segment_v2(p, v1, v2);
- d2 = dist_squared_to_line_segment_v2(p, v2, v3);
- d3 = dist_squared_to_line_segment_v2(p, v3, v4);
- d4 = dist_squared_to_line_segment_v2(p, v4, v1);+{
+ float pos[2];
+ add_v2_v2v2(pos, marker->pos, track->offset);
+ return mouse_to_slide_zone_distance_squared(co, pos, width, height);
+}
- return sqrtf(min_ffff(d1, d2- BKE_tracking_marker_pattern_minmax(marker, d3pat_min, d4));pat_max);
+static float mouse_to_tilt_distance_squared(const MovieTrackingMarker *marker,
+ const float co[2],
+ int width,
+ int height)
+{
+ float slider[2];
+ slide_marker_tilt_slider(marker->pos, marker->pattern_corners, slider);
+ return mouse_to_slide_zone_distance_squared(co, slider, width, height);
}+}
-/* Distance to quad defined by its corners, corners are relative to pos */- epsx = min_ffff(pat_min[0] - marker->search_min[0],
-static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2]) marker->search_max[0] - pat_max[0],
- fabsf(pat_min[0]),
- fabsf(pat_max[0])) /
- 2;
- epsy = min_ffff(pat_min[1] - marker->search_min[1],
- marker->search_max[1] - pat_max[1],
- fabsf(pat_min[1]),
- fabsf(pat_max[1])) /
- 2;
+static float mouse_to_closest_corners_edge_distance_squared(const float co[2],
+ const float corners_offset[2],
+ const float corners[4][2],
+ int width,
+ int height)
{
- float d1, d2, d3, d4;
- const float p[2] = {co[0] - pos[0], co[1] - pos[1]};
- const float *v1 = crns[0], *v2 = crns[1];
- const float *v3 = crns[2], *v4 = crns[3];+{
+ const float co_px[2] = {co[0] * width, co[1] * height};
+
- epsx = max_ff(epsx, 2.0f / width);
- epsy = max_ff(epsy, 2.0f / height);
+ float prev_corner_co_px[2];
+ add_v2_v2v2(prev_corner_co_px, corners_offset, corners[3]);
+ prev_corner_co_px[0] *= width;
+ prev_corner_co_px[1] *= height;
+
- if (sc->flag & SC_SHOW_MARKER_SEARCH) {
- if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy)) {
- return TRACK_AREA_SEARCH;
- }
- }
+ float min_distance_squared = FLT_MAX;
+
- if ((marker->flag & MARKER_DISABLED) == 0) {
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy)) {
- return TRACK_AREA_PAT;
- }
- }
+ for (int i = 0; i < 4; ++i) {
+ float corner_co_px[2];
+ add_v2_v2v2(corner_co_px, corners_offset, corners[i]);
+ corner_co_px[0] *= width;
+ corner_co_px[1] *= height;
- d1 = dist_squared_to_line_segment_v2(p, v1, v2);
- d2 = dist_squared_to_line_segment_v2(p, v2, v3);
- d3 = dist_squared_to_line_segment_v2(p, v3, v4) epsx = 12.0f / width;
- d4 = dist_squared_to_line_segment_v2(p, v4, v1);- epsy = 12.0f / height;
+ const float distance_squared = dist_squared_to_line_segment_v2(
+ co_px, corner_co_px, prev_corner_co_px);
- return sqrtf(min_ffff(d1, d2, d3, d4)) 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;
+ if (distance_squared < min_distance_squared) {
+ min_distance_squared = distance_squared;
+ }
+
+ copy_v2_v2(prev_corner_co_px, corner_co_px);
+ } }
+
- return TRACK_AREA_NONE;
+ return min_distance_squared;
}
-/* Same as above, but all the coordinates are absolute */-static float dist_to_rect(const float co[2],
-static float dist_to_crns_abs(const float co[2], const float corners[4] const float pos[2],
- const float min[2],
- const float max[2])
+static float mouse_to_closest_pattern_edge_distance_squared(const MovieTrackingMarker *marker,
+ const float co[2],
+ int width,
+ int height)
{
- float d1, d2, d3, d4;
- const float *v1 = corners[0p[2] = {co[0] - pos[0], *v2 = cornerco[1] - pos[1];};
- const float *v3 = corners[2v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
- const float v3[2] = {max[0], max[1]}, v4[2] = {min[0], *v4 = corners[3];max[1]};
+ return mouse_to_closest_corners_edge_distance_squared(
+ co, marker->pos, marker->pattern_corners, width, height);
+}
- d1 = dist_squared_to_line_segment_v2(cop, v1, v2);
- d2 = dist_squared_to_line_segment_v2(cop, v2, v3);
- d3 = dist_squared_to_line_segment_v2(cop, v3, v4);
- d4 = dist_squared_to_line_segment_v2(cop, v4, v1);
+static float mouse_to_closest_search_edge_distance_squared(const MovieTrackingMarker *marker,
+ const float co[2],
+ int width,
+ int height)
+{
+ const float corners[4][2] = {
+ {marker->search_min[0], marker->search_min[1]},
+ {marker->search_max[0], marker->search_min[1]},
+ {marker->search_max[0], marker->search_max[1]},
+ {marker->search_min[0], marker->search_max[1]},
+ };
- return sqrtf(min_ffff(d1, d2, d3, d4));
+ return mouse_to_closest_corners_edge_distance_squared(co, marker->pos, corners, width, height);
}
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc,
- ListBase *tracksbase,
- const float co[2],/* Distance to quad defined by its corners, corners are relative to pos */
- -static float dist_to_crns(const float co[2], const float *r_distancepos[2], const float crns[4][2])
+static TrackPickResult tracking_pick_point_track(bContext *C, const float co[2])
{
- MovieTrackingTrack *track = NULL- float d1, *cur;
- float mindist = 0.0f;d2, d3, d4;
- int framenr = ED_space_clip_get_clip_frame_number(sc);- const float p[2] = {co[0] - pos[0], co[1] - pos[1]};
+ SpaceClip *space_clip = CTX_wm_space_clip(C);- const float *v1 = crns[0], *v2 = crns[1];
- cur = tracksbase->first;- const float *v3 = crns[2], *v4 = crns[3];
- while (cur) {+ SpaceClip *space_clip = CTX_wm_space_clip(C);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(cur, framenr);+
+ int width, height;
+ ED_space_clip_get_size(space_clip, &width, &height);
+ if (width == 0 || height == 0) {
+ return track_pick_result_make_null();
+ }
- if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc- d1 = dist_squared_to_line_segment_v2(p, curv1, marker)) {v2);
- float dist- d2 = dist_squared_to_line_segment_v2(p, v2, v3);
- d3 = dist_squared_to_line_segment_v2(p, v3, d1v4);
- d4 = dist_squared_to_line_segment_v2(p, d2 = FLT_MAXv4, d3 = FLT_MAX;v1);
+ MovieClip *clip = ED_space_clip_get_clip(space_clip);
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(&clip->tracking);
+ const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
+
+ const float distance_tolerance_px_squared = (12.0f * 12.0f) / space_clip->zoom;
+ TrackPickResult pick_result = track_pick_result_make_null();
+
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_base) {
+ const bool is_track_selected = TRACK_VIEW_SELECTED(space_clip, track);
+
+ // XXX
+ // if (!TRACK_VIEW_SELECTED(space_clip, track) || (track->flag & TRACK_LOCKED)) {
+ // continue;
+ // }
+
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ // XXX
+ // if (marker->flag & MARKER_DISABLED) {
+ // continue;
+ // }
+
+ float distance_squared;
+
+ /* Initialize the current pick with the offset point of the track. */
+ TrackPickResult current_pick = track_pick_result_make_null();
+ current_pick.track = track;
+ current_pick.marker = marker;
+ current_pick.area = TRACK_AREA_POINT;
+ current_pick.distance_px_squared = mouse_to_offset_distance_squared(
+ track, marker, co, width, height);
+
+ /* If search area is visible, check how close to its sliding zones mouse is. */
+ if (is_track_selected && (space_clip->flag & SC_SHOW_MARKER_SEARCH)) {
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 1, width, height);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.area = TRACK_AREA_SEARCH;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_OFFSET;
+ current_pick.distance_px_squared = distance_squared;
+ }
- /* distance to marker point */
- d1 = sqrtf(
- (co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) +return sqrtf(min_ffff(d1, d2, d3, d4));
- (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1]));-}
+ distance_squared = mouse_to_search_corner_distance_squared(marker, co, 0, width, height);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.area = TRACK_AREA_SEARCH;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_SIZE;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
- /* distance to pattern boundbox */-/* Same as above, but all the coordinates are absolute */
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {-static float dist_to_crns_abs(const float co[2], const float corners[4][2])
- d2 = dist_to_crns(co-{
- float d1, d2, d3, d4;
- const float *v1 = corners[0], marker->pos*v2 = corners[1];
- const float *v3 = corners[2], marker->pattern_*v4 = corners);[3];
+ /* If pattern area is visible, check which corner is closest to the mouse. */
+ if (space_clip->flag & SC_SHOW_MARKER_PATTERN) {
+ int current_corner = -1;
+ distance_squared = mouse_to_closest_pattern_corner_distance_squared(
+ marker, co, width, height, ¤t_corner);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.area = TRACK_AREA_PAT;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_POSITION;
+ current_pick.corner_index = current_corner;
+ current_pick.distance_px_squared = distance_squared;
+ }
- /*- d1 = distance to search boundbox */_squared_to_line_segment_v2(co, v1, v2);
- d2 = dist_squared_to_line_segment_v2(co, v2, v3);
- if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc- d3 = dist_squared_to_line_segment_v2(co, v3, cur)) {v4);
- d3- d4 = dist_to_rect(co, marker->possquared_to_line_segment_v2(co, marker->search_minv4, marker->search_max);v1);
+ /* Here we also check whether the mouse is actually closer to the widget which controls scale
+ * and tilt. */
+ distance_squared = mouse_to_tilt_distance_squared(m// XXX: Support for Slide Marker, co, width, height);.
+ if (distance_squared < current_pick.distance_px_squared) {false) {
+ current_pick.area = TRACK_AREA_PAT;distance_squared = mouse_to_tilt_distance_squared(marker, co, width, height);
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_TILT_SIZE;if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.distance_px_squared = distance_squared;area = TRACK_AREA_PAT;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_TILT_SIZE;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
+ }
- /* choose minimal distance. useful for cases of overlapped markers.- return sqrtf(min_ffff(d1, */
- dist = min_fff(d1d2, d2d3, d3);d4));
+ /* Whenever a manipulation "widgets" are not within distance tolerance test the edges as well.
+ * This allows to pick tracks by clicking on the pattern/search areas edges but prefer to use
+ * more actionable "widget" for sliding. */
+ if (current_pick.distance_px_squared > distance_tolerance_px_squared) {
+ if (is_track_selected && (space_clip->flag & SC_SHOW_MARKER_SEARCH)) {
+ distance_squared = mouse_to_closest_search_edge_distance_squared(
+ marker, co, width, height);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.area = TRACK_AREA_SEARCH;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_EDGE;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
- if (track == NULL || dist < mindist) {
- track = cur;
- mindist = dist;+
+ if (space_clip->flag & SC_SHOW_MARKER_PATTERN) {
+ distance_squared = mouse_to_closest_pattern_edge_distance_squared(
+ marker, co, width, height);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.area = TRACK_AREA_PAT;
+ current_pick.area_detail = TRACK_PICK_AREA_DETAIL_EDGE;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
+ }
- cur = cur->next;+
+ if (current_pick.distance_px_squared < pick_result.distance_px_squared) {
+ pick_result = current_pick;
+ }
}+ }
- *r_distance = mindist;+
+ if (pick_result.distance_px_squared > distance_tolerance_px_squared) {
+ return track_pick_result_make_null();
+ }
- return track;+
+ return pick_result;
}
-static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc,
- ListBase *plane_tracks_base,
- const float co[2],
- float *r_distance)float *r_distance)
-{
- MovieTrackingTrack *track = NULL, *cur;
- float mindist = 0.0f;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+/** \} */
+
- cur = tracksbase->first;
- while (cur) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(cur, framenr);
+/* -------------------------------------------------------------------- */
+/** \name Plane track marker picking.
+ * \{ */
+
- if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc, cur, marker)) {
- float dist, d1, d2 = FLT_MAX, d3 = FLT_MAX;
+typedef struct PlaneTrackPickResult {
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingPlaneMarker *plane_marker;
+
- /* 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]));
+ /* When not equal to -1 denotes the index of the corner which was the closest to the requested
+ * coordinate. */
+ int corner_index;
+
- /* distance to pattern boundbox */
- if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- d2 = dist_to_crns(co, marker->pos, marker->pattern_corners);
- }
+ /* Distance to the pick measured in squared pixels. */
+ float distance_px_squared;
+} PlaneTrackPickResult;
+
- /* distance to search boundbox */
+BLI_INLINE PlaneTrackPickResult plane_track_pick_result_make_null(void)- if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur)) {
- d3 = dist_to_rect(co, marker->pos, marker->search_min, {marker->search_max);
- MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;- }
- float min_distance = 0.0f;+BLI_INLINE PlaneTrackPickResult plane_track_pick_result_make_null(void)
- int framenr = ED_space_clip_get_clip_frame_number(sc);+{
+ PlaneTrackPickResult result = {NULL};
- for (current_plane_track = plane_tracks_base->first;- /* choose minimal distance. current_plane_track;
- current_plane_track = current_plane_track->next) {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track,useful for cases of overlapped markers. */
- framenr);dist = min_fff(d1, d2, d3);
+ result.corner_index = -1;
+ result.distance_px_squared = FLT_MAX;
- if ((current_plane_ if (track->flag & TRACK_HIDDEN) == 0) { == NULL || dist < mindist) {
- float distance = dist_to_crns_abs(co, plane_marker->corners); track = cur;
- if (plane_track == NULL || mindistance < min_ = distance) {;
- plane_track = current_plane_track;}
- min_distance = distance;}
+ return result;
+}
+
- cur = cur->next;
+BLI_INLINE bool plane_track_pick_result_can_slide(const PlaneTrackPickResult *pick_result)
+{
+ if (pick_result->plane_marker == NULL) {
+ return false;
}
- *r_distance = mindist;
+ return pick_result->corner_index != -1;
+}
- return track;
+static float mouse_to_plane_slide_zone_distance_squared(const float co[2],
+ const float slide_zone[2],
+ int width,
+ int height)
+{
+ const float pixel_co[2] = {co[0] * width, co[1] * height};
+ const float pixel_slide_zone[2] = {slide_zone[0] * width, slide_zone[1] * height};
+ return square_f(pixel_co[0] - pixel_slide_zone[0]) + square_f(pixel_co[1] - pixel_slide_zone[1]);
+} }
+
-static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc,
- ListBase *plane_tracks_base,
- const float co[2],
- float *r_distance)
+static PlaneTrackPickResult tracking_pick_plane_track(bContext *C, const float co[2])
+{ {
- MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
- float min_distance = 0.0f;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+
+ int width, height;
+ ED_space_clip_get_size(space_clip, &width, &height);
+ if (width == 0 || height == 0) {
+ return plane_track_pick_result_make_null();
+ }
+
+ MovieClip *clip = ED_space_clip_get_clip(space_clip);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
+
+ const float distance_tolerance_px_squared = (12.0f * 12.0f) / space_clip->zoom;
+ PlaneTrackPickResult pick_result = plane_track_pick_result_make_null();
+
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track != NULL;
+ plane_track = plane_track->next) {
+ // XXX:
+ // if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ // continue;
+ // }
+
- for (current_plane_track = plane_tracks_base->first; current_plane_track;
- current_plane_track = current_plane_track->next) {
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track,
- framenr);
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
- if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
- float distance = dist_to_crns_abs(co, plane_marker->corners);
- if (plane_track == NULL || distance < min_distance) {
- plane_track = current_plane_track;
- min_distance = distance;
+ PlaneTrackPickResult current_pick = plane_track_pick_result_make_null();
+ current_pick.plane_track = plane_track;
+ current_pick.plane_marker = plane_marker;
+
+ for (int i = 0; i < 4; i++) {
+ const float distance_squared = mouse_to_plane_slide_zone_distance_squared(
+ co, plane_marker->corners[i], width, height);
+
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.corner_index = i;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
+
+ if (current_pick.distance_px_squared > distance_tolerance_px_squared) {
+ const float zero_offset[2] = {0.0f, 0.0f};
+ const float distance_squared = mouse_to_closest_corners_edge_distance_squared(
+ co, zero_offset, plane_marker->corners, width, height);
+ if (distance_squared < current_pick.distance_px_squared) {
+ current_pick.corner_index = -1;
+ current_pick.distance_px_squared = distance_squared;
+ }
+ }
+
+ if (current_pick.distance_px_squared < pick_result.distance_px_squared) {
+ pick_result = current_pick;
+ }
}
- *r_distance = min_distance;
+ if (pick_result.distance_px_squared > distance_tolerance_px_squared) {
+ return plane_track_pick_result_make_null();
+ }
- return plane_track;
+ return pick_result;
}
+/** \} */
+
+/********************** mouse select operator *********************/
+
void ed_tracking_deselect_all_tracks(ListBase *tracks_base)
{
MovieTrackingTrack *track;
@@ -298,60 +484,20303,6 +510,7 @@ static int select_exec(bContext *C, wmOperator *op)
float co[2];
RNA_float_get_array(op->ptr, "location", co);
- /* Special code which allows to slide a marker which belongs to currently selected but not yet
- * active track. If such track is found activate it and return pass-though so that marker slide
- * operator can be used immediately after.
- * This logic makes it convenient to slide markers when left mouse selection is used. Without it
- * selection will be lost which causes inconvenience for the VFX artist. */
- const bool activate_selected = RNA_boolean_get(op->ptr, "activate_selected");
- if (activate_selected) { * operator can be used immediately after.
- MovieTrackingTrack *track = tracking_find_slidable_track_in_proximity(C, * This logic makes it convenient to slide markers when left mouse selection is used. co);Without it
- if (track != NULL) { * selection will be lost which causes inconvenience for the VFX artist. */
- MovieClip *clip_iter = ED_space_clip_get_clip(sc);+ // XXX: Find a better way (maybe via track_pick_result_can_slide). Also, support plane tracks.
-
- clip_iter->tracking.act_track = track;
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
- DEG_id_tag_update(&clip_iter->id const bool activate_selected = RNA_boolean_get(op->ptr, ID_RECALC_SELECT);"activate_selected");
- if (activate_selected) {
- return OPERATOR_PASS_THROUGH; MovieTrackingTrack *track = tracking_find_slidable_track_in_proximity(C, co);
- }@@ -318,40 +526,20 @@ static int select_exec(bContext *C, wmOperator *op)
- } }
- }
- float distance_to_track, distance_to_plane_track;
-
- MovieTrackingTrack *track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
- MovieTrackingPlaneTrack *plane_track = find_nearest_plane_track(
- sc, plane_tracks_base, co, &distance_to_plane_track);
+ const TrackPickResult track_pick = tracking_pick_point_track(C, co);
+ const PlaneTrackPickResult plane_track_pick = tracking_pick_plane_track(C, co);
ClipViewLockState lock_state;
ED_clip_view_lock_state_store(C, &lock_state);
- /* Do not select beyond some reasonable distance, that is useless and
- * prevents the 'deselect on nothing' behavior. */
- if (distance_to_track > 0.05f) {
- track = NULL;
- }
- if (distance_to_plane_track > 0.05f) {
- plane_track = NULL;
- }
-
- /* Between track and plane we choose closest to the mouse for selection here. */
- if (track && plane_track) {
- if (distance_to_track < distance_to_plane_track) {
- plane_track = NULL;
- }
- else {
- track = NULL;
- }
- }
-
- if (track) {
+ if (track_pick.track != NULL ||
+ track_pick.distance_px_squared < plane_track_pick.distance_px_squared) {
if (!extend) {
ed_tracking_deselect_all_plane_tracks(plane_tracks_base);
}
- int area = track_mouse_area(C, co, track);
+ MovieTrackingTrack *track = track_pick.track;
+ int area = track_pick.area;
if (!extend || !TRACK_VIEW_SELECTED(sc, track)) {
area = TRACK_AREA_ALL;
@@ -376,11 +52264,13 @@ static int select_exec(bContext *C, wmOperator *op)
clip->tracking.act_plane_track = NULL;
}
}
- else if (plane_track) {
+ else if (plane_track_pick.plane_track != NULL) {
if (!extend) {
ed_tracking_deselect_all_tracks(tracksbase);
}
+ MovieTrackingPlaneTrack *plane_track = plane_track_pick.plane_track;
+
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
if (extend) {
plane_track->flag &= ~SELECT;
@@ -407,8 +555,166 +597,22 @@ static int select_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- /* Pass-through + finished to allow tweak to transform. */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ if (RNA_boolean_get(op->ptr+ /* This is a bit implicit, "use_tweak_transform")) {but when the selection operator is used from a LMB Add Marker and
+ /* P* tweak tool we do not want the pass-through + finished to allow tweak to transformhere and only want selection to happen. */This way
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;* the selection operator will not fall-through to Add Marker operator. */
+ }+ if (activate_selected) {
+ if (track_pick_result_can_slide(&track_pick) ||
+ if (track_pick.+ plane_track == NULL && plane_track_pick._pick_result_can_slide(&plane_track == NULL) {_pick)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+
+ return OPERATOR_FINISHED;
}
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -454,12 +610,11 @@ void CLIP_OT_select(wmOperatorType *ot)
"Deselect all when nothing under the cursor"); if (track_pick.track == NULL && plane_track_pick.plane_track == NULL) {
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(
- ot->srna,
- "activate_selected",
- 0,
- "Activate Selected",
- "When selecting already selected track activate it and do not alter others selection")+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ prop = RNA_def_boolean(ot->srna,+ }
+ "use_tweak_transform",
+ 0,return OPERATOR_FINISHED;
+ "Use Tweak Transform",+ }
+ "Allow tweak transform after running this operator");
RNA_def_property_flag(prop,/* Pass-through + finished to allow tweak to transform. PROP_SKIP_SAVE);*/
RNA_def_float_vector(return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}