[Bf-blender-cvs] [25f8381d9f3] temp-angavrilov: Shape Keys: support locking to protect from accidental editing.

Alexander Gavrilov noreply at git.blender.org
Tue Jan 24 16:31:36 CET 2023


Commit: 25f8381d9f39d9720dd957435a0c8493e5c95daf
Author: Alexander Gavrilov
Date:   Tue Jan 24 16:53:10 2023 +0200
Branches: temp-angavrilov
https://developer.blender.org/rB25f8381d9f39d9720dd957435a0c8493e5c95daf

Shape Keys: support locking to protect from accidental editing.

It is very common for graphical editors with layers to support
locking individual layers to protect them from accidental edits due
to misclicks. Blender itself already supports locking vertex groups.
This adds lock toggles for shape keys, with lock/unlock all operators.

The flags are checked by sculpt brushes, edit mode transform tools,
and Smooth, Propagate and Blend From Shape operators. This selection
aims to cover operations that only deform the mesh, where the shape
key selection matters. Topology changing operations always apply to
all keys, and thus incorrect shape key selection is less impactful.

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

M	release/scripts/startup/bl_ui/properties_data_mesh.py
M	source/blender/blenkernel/BKE_key.h
M	source/blender/blenkernel/intern/key.cc
M	source/blender/editors/include/ED_mesh.h
M	source/blender/editors/mesh/editmesh_tools.c
M	source/blender/editors/mesh/mesh_data.cc
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_ops.c
M	source/blender/editors/object/object_shapekey.c
M	source/blender/editors/sculpt_paint/sculpt.cc
M	source/blender/editors/transform/transform_convert_curve.c
M	source/blender/editors/transform/transform_convert_lattice.c
M	source/blender/editors/transform/transform_convert_mesh.c
M	source/blender/editors/transform/transform_convert_sculpt.c
M	source/blender/makesdna/DNA_key_types.h
M	source/blender/makesrna/intern/rna_key.c

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

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 714dcca9673..98b4cfc9f1d 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -70,6 +70,9 @@ class MESH_MT_shape_key_context_menu(Menu):
         op.all = True
         op.apply_mix = True
         layout.separator()
+        layout.operator("object.shape_key_lock", icon='LOCKED', text="Lock All").action = 'LOCK'
+        layout.operator("object.shape_key_lock", icon='UNLOCKED', text="Unlock All").action = 'UNLOCK'
+        layout.separator()
         layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move to Top").type = 'TOP'
         layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
 
@@ -140,6 +143,7 @@ class MESH_UL_shape_keys(UIList):
             else:
                 row.label(text="")
             row.prop(key_block, "mute", text="", emboss=False)
+            row.prop(key_block, "lock_shape", text="", emboss=False)
         elif self.layout_type == 'GRID':
             layout.alignment = 'CENTER'
             layout.label(text="", icon_value=icon)
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index d868969f9b9..10c95253f38 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -87,9 +87,13 @@ struct KeyBlock *BKE_keyblock_add(struct Key *key, const char *name);
  */
 struct KeyBlock *BKE_keyblock_add_ctime(struct Key *key, const char *name, bool do_force);
 /**
- * Get the appropriate #KeyBlock given an index.
+ * Get the appropriate #KeyBlock given an index, excluding the first (0th) key. Key may be null.
  */
 struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
+/**
+ * Get the appropriate #KeyBlock given an index. Key may be null.
+ */
+struct KeyBlock *BKE_keyblock_find_index(struct Key *key, int index);
 /**
  * Get the appropriate #KeyBlock given a name to search for.
  */
diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc
index 7d835c2464d..b8ff350917e 100644
--- a/source/blender/blenkernel/intern/key.cc
+++ b/source/blender/blenkernel/intern/key.cc
@@ -1899,12 +1899,7 @@ KeyBlock *BKE_keyblock_from_object(Object *ob)
 {
   Key *key = BKE_key_from_object(ob);
 
-  if (key) {
-    KeyBlock *kb = static_cast<KeyBlock *>(BLI_findlink(&key->block, ob->shapenr - 1));
-    return kb;
-  }
-
-  return nullptr;
+  return BKE_keyblock_find_index(key, ob->shapenr - 1);
 }
 
 KeyBlock *BKE_keyblock_from_object_reference(Object *ob)
@@ -1935,6 +1930,15 @@ KeyBlock *BKE_keyblock_from_key(Key *key, int index)
   return nullptr;
 }
 
+KeyBlock *BKE_keyblock_find_index(Key *key, int index)
+{
+  if (key) {
+    return static_cast<KeyBlock *>(BLI_findlink(&key->block, index));
+  }
+
+  return nullptr;
+}
+
 KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])
 {
   return static_cast<KeyBlock *>(BLI_findstring(&key->block, name, offsetof(KeyBlock, name)));
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 8ab6e31bef3..b3d831eccf5 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -584,6 +584,8 @@ int ED_mesh_sculpt_color_add(struct Mesh *me,
 void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail);
 void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode);
 
+bool ED_mesh_has_locked_shape_key(struct Mesh *me);
+
 /**
  * Returns the pinned mesh, the mesh from the pinned object, or the mesh from the active object.
  */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 620d6c2ea5e..58f6ec3a4cb 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2666,6 +2666,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
 
   const Scene *scene = CTX_data_scene(C);
   ViewLayer *view_layer = CTX_data_view_layer(C);
+  int tot_selected = 0, tot_locked = 0;
   uint objects_len = 0;
   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
       scene, view_layer, CTX_wm_view3d(C), &objects_len);
@@ -2681,6 +2682,13 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
       continue;
     }
 
+    if (ED_mesh_has_locked_shape_key(me)) {
+      tot_locked++;
+      continue;
+    }
+
+    tot_selected++;
+
     /* mirror before smooth */
     if (((Mesh *)obedit->data)->symmetry & ME_SYMMETRY_X) {
       EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
@@ -2743,6 +2751,15 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
   }
   MEM_freeN(objects);
 
+  if (tot_locked) {
+    BKE_report(op->reports, RPT_WARNING, "The active shape key is locked");
+    return tot_selected ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+  }
+  if (tot_selected == 0) {
+    BKE_report(op->reports, RPT_WARNING, "No selected vertex");
+    return OPERATOR_CANCELLED;
+  }
+
   return OPERATOR_FINISHED;
 }
 
@@ -2783,7 +2800,7 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
 
 static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
 {
-  int tot_unselected = 0;
+  int tot_selected = 0, tot_locked = 0;
   const Scene *scene = CTX_data_scene(C);
   ViewLayer *view_layer = CTX_data_view_layer(C);
 
@@ -2809,10 +2826,16 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
     bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
 
     if (em->bm->totvertsel == 0) {
-      tot_unselected++;
       continue;
     }
 
+    if (ED_mesh_has_locked_shape_key(me)) {
+      tot_locked++;
+      continue;
+    }
+
+    tot_selected++;
+
     /* Mirror before smooth. */
     if (((Mesh *)obedit->data)->symmetry & ME_SYMMETRY_X) {
       EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
@@ -2854,7 +2877,11 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
   }
   MEM_freeN(objects);
 
-  if (tot_unselected == objects_len) {
+  if (tot_locked > 0) {
+    BKE_report(op->reports, RPT_WARNING, "The active shape key is locked");
+    return tot_selected ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+  }
+  if (tot_selected == 0) {
     BKE_report(op->reports, RPT_WARNING, "No selected vertex");
     return OPERATOR_CANCELLED;
   }
@@ -3718,6 +3745,7 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
   ViewLayer *view_layer = CTX_data_view_layer(C);
   int tot_shapekeys = 0;
   int tot_selected_verts_objects = 0;
+  int tot_locked = 0;
 
   uint objects_len = 0;
   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@@ -3730,6 +3758,24 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
     if (em->bm->totvertsel == 0) {
       continue;
     }
+
+    /* Check for locked shape keys. */
+    if (me->key) {
+      bool found = false;
+
+      LISTBASE_FOREACH(KeyBlock *, kb, &me->key->block) {
+        if (kb->flag & KEYBLOCK_LOCKED_SHAPE) {
+          found = true;
+          break;
+        }
+      }
+
+      if (found) {
+        tot_locked++;
+        continue;
+      }
+    }
+
     tot_selected_verts_objects++;
 
     if (shape_propagate(em)) {
@@ -3745,6 +3791,10 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
   }
   MEM_freeN(objects);
 
+  if (tot_locked > 0) {
+    BKE_report(op->reports, RPT_ERROR, "The mesh has locked shape keys");
+    return tot_selected_verts_objects ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+  }
   if (tot_selected_verts_objects == 0) {
     BKE_report(op->reports, RPT_ERROR, "No selected vertex");
     return OPERATOR_CANCELLED;
@@ -3814,7 +3864,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
     kb_ref = BLI_findlink(&key_ref->block, shape_ref);
   }
 
-  int tot_selected_verts_objects = 0;
+  int tot_selected_verts_objects = 0, tot_locked = 0;
   uint objects_len = 0;
   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
       scene, view_layer, CTX_wm_view3d(C), &objects_len);
@@ -3829,6 +3879,12 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
     if (em->bm->totvertsel == 0) {
       continue;
     }
+
+    if (ED_mesh_has_locked_shape_key(me)) {
+      tot_locked++;
+      continue;
+    }
+
     tot_selected_verts_objects++;
 
     if (!key) {
@@ -3871,6 +3927,10 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
   }
   MEM_freeN(objects);
 
+  if (tot_locked > 0) {
+    BKE_report(op->reports, RPT_ERROR, "The active shape key is locked");
+    return tot_selected_verts_objects ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+  }
   if (tot_selected_verts_objects == 0) {
     BKE_report(op->reports, RPT_ERROR, "No selected vertex");
     return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc
index db60f253cb2..40b7f27ba00 100644
--- a/source/blender/editors/mesh/mesh_data.cc
+++ b/source/blender/editors/mesh/mesh_data.cc
@@ -7,6 +7,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_key_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
@@ -23,6 +24,7 @@
 #include "BKE_context.h"
 #include "BKE_customdata.h"
 #include "BKE_editmesh.h"
+#include "BKE_key.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
 #include "BKE_report.h"
@@ -1513,6 +1515,15 @@ void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
   ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
 }
 
+bool ED_mesh_has_locked_shape_key(Mesh *me)
+{
+  BLI_assert(me->edit_mesh && me->edit_mesh->bm);
+
+  KeyBlock *key_block = BKE_keyblock_find_index(me->key, me->edit_mesh->bm->shapenr - 1);
+
+  return key_block && (key_block->flag & KEYBLOCK_LOCKED_SHAPE) != 0;
+}
+
 Mesh *ED_mesh_context(bContext *C)
 {
   Mesh *mesh = static_cast<Mesh *>(CTX_data_poi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list