[Bf-blender-cvs] [66f8835f9c0] master: Fix T84850: "Lock to Selection" causes unwanted jumps

Sergey Sharybin noreply at git.blender.org
Tue Jan 26 16:23:13 CET 2021


Commit: 66f8835f9c03e7736297b5995a68e1455ed14e2a
Author: Sergey Sharybin
Date:   Tue Jan 19 14:28:44 2021 +0100
Branches: master
https://developer.blender.org/rB66f8835f9c03e7736297b5995a68e1455ed14e2a

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

===================================================================

M	source/blender/editors/include/ED_clip.h
M	source/blender/editors/include/ED_mask.h
M	source/blender/editors/mask/mask_add.c
M	source/blender/editors/mask/mask_edit.c
M	source/blender/editors/mask/mask_intern.h
M	source/blender/editors/mask/mask_ops.c
M	source/blender/editors/mask/mask_query.c
M	source/blender/editors/mask/mask_select.c
M	source/blender/editors/space_clip/clip_editor.c
M	source/blender/editors/space_clip/clip_intern.h
M	source/blender/editors/space_clip/clip_ops.c
M	source/blender/editors/space_clip/clip_utils.c
M	source/blender/editors/space_clip/tracking_ops.c
M	source/blender/editors/space_clip/tracking_select.c
M	source/blender/editors/space_image/image_ops.c

===================================================================

diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 0a66c439f79..56494f87bfe 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -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);
 
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index bcf52da3f69..b20dae694fc 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -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);
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index d7b3d74bc7e..1226cc57359 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -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;
 }
 
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 663ae0097ad..e6c6424e5f0 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -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);
+  }
+}
+
+/** \} */
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index f6990583383..ee1784011ea 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -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,
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 25cc39bf9a0..00a1dfb7d87 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -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;
 }
 
diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c
index cfd57ca3477..8f4f14a1ba8 100644
--- a/source/blender/editors/mask/mask_query.c
+++ b/source/blender/editors/mask/mask_query.c
@@ -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 bConte

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list