Fix T84850: "Lock to Selection" causes unwanted jumps

Adding new tracks, mask points, mask primitives, changing selection was
causing an unwanted jumps in the view.

This change makes it so those operations are preserving view offset.

Differential Revision: https://developer.blender.org/D10146
This commit is contained in:
Sergey Sharybin 2021-01-19 14:28:44 +01:00
parent 3d3b6d94e6
commit 66f8835f9c
Notes: blender-bot 2023-02-13 19:51:07 +01:00
Referenced by issue #85535, Motion tracking - locking by "L" key is not centering view.
Referenced by issue #84850, "Lock to Selection" in Clip Editor messes up Mask Editing
15 changed files with 375 additions and 130 deletions

View File

@ -99,6 +99,30 @@ void ED_space_clip_set_clip(struct bContext *C,
struct Mask *ED_space_clip_get_mask(struct SpaceClip *sc);
void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask);
/* Locked state is used to preserve current clip editor viewport upon changes. Example usage:
*
* ...
*
* ClipViewLockState lock_state;
* ED_clip_view_lock_state_store(C, &lock_state);
*
* <change selection>
*
* ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
*
* These function are to be used from space clip editor context only. Otherwise debug builds will
* assert, release builds will crash. */
typedef struct ClipViewLockState {
float offset_x, offset_y;
float lock_offset_x, lock_offset_y;
float zoom;
} ClipViewLockState;
void ED_clip_view_lock_state_store(const struct bContext *C, ClipViewLockState *state);
void ED_clip_view_lock_state_restore_no_jump(const struct bContext *C,
const ClipViewLockState *state);
/* ** clip_ops.c ** */
void ED_operatormacros_clip(void);

View File

@ -63,7 +63,10 @@ void ED_mask_point_pos__reverse(
struct ScrArea *area, struct ARegion *region, float x, float y, float *xr, float *yr);
void ED_mask_cursor_location_get(struct ScrArea *area, float cursor[2]);
bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]);
bool ED_mask_selected_minmax(const struct bContext *C,
float min[2],
float max[2],
bool include_handles);
/* mask_draw.c */
void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type);

View File

@ -507,6 +507,9 @@ static int add_vertex_handle_cyclic(
static int add_vertex_exec(bContext *C, wmOperator *op)
{
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
Mask *mask = CTX_data_edit_mask(C);
if (mask == NULL) {
/* if there's no active mask, create one */
@ -548,6 +551,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}
@ -690,6 +695,9 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
static int create_primitive_from_points(
bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
ScrArea *area = CTX_wm_area(C);
int size = RNA_float_get(op->ptr, "size");
@ -752,6 +760,8 @@ static int create_primitive_from_points(
DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}

View File

@ -184,3 +184,39 @@ void ED_operatormacros_mask(void)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lock-to-selection viewport preservation
* \{ */
void ED_mask_view_lock_state_store(const bContext *C, MaskViewLockState *state)
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
if (space_clip != NULL) {
ED_clip_view_lock_state_store(C, &state->space_clip_state);
}
}
void ED_mask_view_lock_state_restore_no_jump(const bContext *C, const MaskViewLockState *state)
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
if (space_clip != NULL) {
if ((space_clip->flag & SC_LOCK_SELECTION) == 0) {
/* Early output if the editor is not locked to selection.
* Avoids forced dependency graph evaluation here. */
return;
}
/* Mask's lock-to-selection requres deformed splines to be evaluated to calculate bounds of
* points after animation has been evaluated. The restore-no-jump type of function does
* calculation of new offset for the view for an updated state of mask to cancel the offset out
* by modifying locked offset. In order to do such calculation mask needs to be evaluated after
* modification by an operator. */
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
(void)depsgraph;
ED_clip_view_lock_state_restore_no_jump(C, &state->space_clip_state);
}
}
/** \} */

View File

@ -23,6 +23,8 @@
#pragma once
#include "ED_clip.h"
struct Mask;
struct bContext;
struct wmOperatorType;
@ -92,6 +94,19 @@ void ED_mask_select_flush_all(struct Mask *mask);
bool ED_maskedit_poll(struct bContext *C);
bool ED_maskedit_mask_poll(struct bContext *C);
/* Generalized solution for preserving editor viewport when making changes while lock-to-selection
* is enabled.
* Any mask operator can use this API, without worrying that some editors do not have an idea of
* lock-to-selection. */
typedef struct MaskViewLockState {
ClipViewLockState space_clip_state;
} MaskViewLockState;
void ED_mask_view_lock_state_store(const struct bContext *C, MaskViewLockState *state);
void ED_mask_view_lock_state_restore_no_jump(const struct bContext *C,
const MaskViewLockState *state);
/* mask_query.c */
bool ED_mask_find_nearest_diff_point(const struct bContext *C,
struct Mask *mask,

View File

@ -226,6 +226,12 @@ typedef struct SlidePointData {
int width, height;
float prev_mouse_coord[2];
/* Previous clip coordinate which was resolved from mouse position (0, 0).
* Is used to compansate for view offste moving in-between of mouse events when
* lock-to-selection is enabled. */
float prev_zero_coord[2];
float no[2];
bool is_curvature_only, is_accurate, is_initial_feather, is_overall_feather;
@ -431,6 +437,9 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
const float threshold = 19;
eMaskWhichHandle which_handle;
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
ED_mask_mouse_pos(area, region, event->mval, co);
ED_mask_get_size(area, &width, &height);
@ -530,7 +539,15 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
}
customdata->which_handle = which_handle;
{
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
DEG_id_tag_update(&mask->id, 0);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
}
ED_mask_mouse_pos(area, region, event->mval, customdata->prev_mouse_coord);
ED_mask_mouse_pos(area, region, (int[2]){0, 0}, customdata->prev_zero_coord);
}
return customdata;
@ -655,10 +672,24 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_mask_mouse_pos(area, region, event->mval, co);
sub_v2_v2v2(delta, co, data->prev_mouse_coord);
copy_v2_v2(data->prev_mouse_coord, co);
/* Compensate for possibly moved view offset since the last event.
* The idea is to see how mapping of a fixed and known position did change. */
{
float zero_coord[2];
ED_mask_mouse_pos(area, region, (int[2]){0, 0}, zero_coord);
float zero_delta[2];
sub_v2_v2v2(zero_delta, zero_coord, data->prev_zero_coord);
sub_v2_v2(delta, zero_delta);
copy_v2_v2(data->prev_zero_coord, zero_coord);
}
if (data->is_accurate) {
mul_v2_fl(delta, 0.2f);
}
copy_v2_v2(data->prev_mouse_coord, co);
if (data->action == SLIDE_ACTION_HANDLE) {
float new_handle[2];
@ -966,6 +997,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C,
float u, co[2];
BezTriple *next_bezt;
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
if (!ED_mask_find_nearest_diff_point(C,
@ -1047,6 +1081,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C,
mask_layer->act_point = point;
ED_mask_select_flush_all(mask);
DEG_id_tag_update(&mask->id, 0);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return slide_data;
}

View File

@ -604,7 +604,7 @@ void ED_mask_point_pos__reverse(
*yr = co[1];
}
bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2])
bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2], bool include_handles)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Mask *mask = CTX_data_edit_mask(C);
@ -638,22 +638,29 @@ bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2])
}
if (bezt->f2 & SELECT) {
minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]);
ok = true;
}
if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
if (!include_handles) {
/* Ignore handles. */
}
else if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle);
minmax_v2v2_v2(min, max, handle);
ok = true;
}
else {
if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle);
minmax_v2v2_v2(min, max, handle);
ok = true;
}
if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle);
minmax_v2v2_v2(min, max, handle);
ok = true;
}
}
ok = true;
}
}
}

View File

@ -214,12 +214,17 @@ static int select_all_exec(bContext *C, wmOperator *op)
Mask *mask = CTX_data_edit_mask(C);
int action = RNA_enum_get(op->ptr, "action");
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
ED_mask_select_toggle_all(mask, action);
ED_mask_select_flush_all(mask);
DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}
@ -261,6 +266,9 @@ static int select_exec(bContext *C, wmOperator *op)
eMaskWhichHandle which_handle;
const float threshold = 19;
MaskViewLockState lock_state;
ED_mask_view_lock_state_store(C, &lock_state);
RNA_float_get_array(op->ptr, "location", co);
point = ED_mask_point_find_nearest(
@ -324,6 +332,8 @@ static int select_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}
@ -364,12 +374,15 @@ static int select_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}
if (deselect_all) {
/* For clip editor tracks, leave deselect all to clip editor. */
if (!ED_clip_can_select(C)) {
ED_mask_deselect_all(C);
ED_mask_view_lock_state_restore_no_jump(C, &lock_state);
return OPERATOR_FINISHED;
}
}

View File

@ -327,118 +327,18 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
}
}
static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2])
bool ED_clip_view_selection(const bContext *C, ARegion *UNUSED(region), bool fit)
{
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);
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 selected_boundbox(const bContext *C, float min[2], float max[2])
{
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)) {
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 ED_clip_view_selection(const bContext *C, ARegion *region, bool fit)
{
SpaceClip *sc = CTX_wm_space_clip(C);
int w, h, frame_width, frame_height;
float min[2], max[2];
ED_space_clip_get_size(sc, &frame_width, &frame_height);
if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) {
float offset_x, offset_y;
float zoom;
if (!clip_view_calculate_view_selection(C, fit, &offset_x, &offset_y, &zoom)) {
return false;
}
if (!selected_boundbox(C, min, max)) {
return false;
}
/* center view */
clip_view_center_to_point(
sc, (max[0] + min[0]) / (2 * frame_width), (max[1] + min[1]) / (2 * frame_height));
w = max[0] - min[0];
h = max[1] - min[1];
/* set zoom to see all selection */
if (w > 0 && h > 0) {
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 || sc->zoom > newzoom) {
sc->zoom = newzoom;
}
}
SpaceClip *sc = CTX_wm_space_clip(C);
sc->xof = offset_x;
sc->yof = offset_y;
sc->zoom = zoom;
return true;
}
@ -1177,3 +1077,47 @@ void clip_start_prefetch_job(const bContext *C)
/* and finally start the job */
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
void ED_clip_view_lock_state_store(const bContext *C, ClipViewLockState *state)
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
BLI_assert(space_clip != NULL);
state->offset_x = space_clip->xof;
state->offset_y = space_clip->yof;
state->zoom = space_clip->zoom;
state->lock_offset_x = 0.0f;
state->lock_offset_y = 0.0f;
if ((space_clip->flag & SC_LOCK_SELECTION) == 0) {
return;
}
if (!clip_view_calculate_view_selection(
C, false, &state->offset_x, &state->offset_y, &state->zoom)) {
return;
}
state->lock_offset_x = space_clip->xlockof;
state->lock_offset_y = space_clip->ylockof;
}
void ED_clip_view_lock_state_restore_no_jump(const bContext *C, const ClipViewLockState *state)
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
BLI_assert(space_clip != NULL);
if ((space_clip->flag & SC_LOCK_SELECTION) == 0) {
return;
}
float offset_x, offset_y;
float zoom;
if (!clip_view_calculate_view_selection(C, false, &offset_x, &offset_y, &zoom)) {
return;
}
space_clip->xlockof = state->offset_x + state->lock_offset_x - offset_x;
space_clip->ylockof = state->offset_y + state->lock_offset_y - offset_y;
}

View File

@ -171,8 +171,13 @@ void clip_delete_plane_track(struct bContext *C,
struct MovieClip *clip,
struct MovieTrackingPlaneTrack *plane_track);
void clip_view_offset_for_center_to_point(
SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y);
void clip_view_center_to_point(SpaceClip *sc, float x, float y);
bool clip_view_calculate_view_selection(
const struct bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom);
void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
/* tracking_ops.c */

View File

@ -1840,8 +1840,16 @@ void CLIP_OT_cursor_set(wmOperatorType *ot)
static int lock_selection_togglee_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceClip *space_clip = CTX_wm_space_clip(C);
ClipViewLockState lock_state;
ED_clip_view_lock_state_store(C, &lock_state);
space_clip->flag ^= SC_LOCK_SELECTION;
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
return OPERATOR_FINISHED;
}

View File

@ -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,152 @@ 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;
float aspx, aspy;
ED_space_clip_get_size(sc, &width, &height);
float aspx, aspy;
ED_space_clip_get_aspect(sc, &aspx, &aspy);
sc->xof = (x - 0.5f) * width * aspx;
sc->yof = (y - 0.5f) * height * 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);
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 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` argment 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 deriver the `include_handles` from `fit`.
*
* TODO(sergey): Make such decision more explicit. Maybe pass usecase 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;
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)

View File

@ -88,17 +88,16 @@ static int add_marker_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
float pos[2];
ClipViewLockState lock_state;
ED_clip_view_lock_state_store(C, &lock_state);
RNA_float_get_array(op->ptr, "location", pos);
if (!add_marker(C, pos[0], pos[1])) {
return OPERATOR_CANCELLED;
}
/* Reset offset from locked position, so frame jumping wouldn't be so
* confusing.
*/
sc->xlockof = 0;
sc->ylockof = 0;
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);

View File

@ -304,6 +304,9 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const
track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
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) {
@ -377,10 +380,7 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const
ED_mask_deselect_all(C);
}
if (!extend) {
sc->xlockof = 0.0f;
sc->ylockof = 0.0f;
}
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
BKE_tracking_dopesheet_tag_update(tracking);
@ -867,15 +867,20 @@ static int select_all_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
int action = RNA_enum_get(op->ptr, "action");
const int action = RNA_enum_get(op->ptr, "action");
ClipViewLockState lock_state;
ED_clip_view_lock_state_store(C, &lock_state);
bool has_selection = false;
ED_clip_select_all(sc, action, &has_selection);
if (!has_selection) {
sc->flag &= ~SC_LOCK_SELECTION;
}
else {
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
}
BKE_tracking_dopesheet_tag_update(tracking);

View File

@ -900,7 +900,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
}
}
else if (ED_space_image_check_show_maskedit(sima, obedit)) {
if (!ED_mask_selected_minmax(C, min, max)) {
if (!ED_mask_selected_minmax(C, min, max, true)) {
return OPERATOR_CANCELLED;
}
}