[Bf-blender-cvs] [01c8aa12a17] master: Apply Modifier: support applying as shape key and keeping the modifier.

Alexander Gavrilov noreply at git.blender.org
Wed Jul 8 10:08:26 CEST 2020


Commit: 01c8aa12a17775cce03106a576f3c498d28131e4
Author: Alexander Gavrilov
Date:   Wed Jul 1 17:38:07 2020 +0300
Branches: master
https://developer.blender.org/rB01c8aa12a17775cce03106a576f3c498d28131e4

Apply Modifier: support applying as shape key and keeping the modifier.

This can be useful to save the result of a cloth simulation as a
shape key without destroying the simulation, so it's possible to
e.g. re-run it to get other shapes, or simply use the new shape
key to start the simulation already in a draped state.

It also makes sense to allow applying as shape key even when the
mesh is shared, because the operation itself just adds a shape
key. To support this, split the apply operator into Apply and
Apply As Shapekey so that they can have different poll callbacks.

Differential Revision: https://developer.blender.org/D8173

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

M	source/blender/editors/include/ED_object.h
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_modifier.c
M	source/blender/editors/object/object_ops.c
M	source/blender/modifiers/intern/MOD_ui_common.c

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

diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index a851eb735b8..5ec4de5d597 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -389,7 +389,8 @@ bool ED_object_modifier_apply(struct Main *bmain,
                               struct Scene *scene,
                               struct Object *ob,
                               struct ModifierData *md,
-                              int mode);
+                              int mode,
+                              bool keep_modifier);
 int ED_object_modifier_copy(struct ReportList *reports,
                             struct Object *ob,
                             struct ModifierData *md);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index afc87c0caba..9dc204b9083 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -167,6 +167,7 @@ void OBJECT_OT_modifier_move_up(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_move_down(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_move_to_index(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_apply(struct wmOperatorType *ot);
+void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot);
 void OBJECT_OT_modifier_convert(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
 void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 74109563929..6c929ad781e 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -822,7 +822,8 @@ bool ED_object_modifier_apply(Main *bmain,
                               Scene *scene,
                               Object *ob,
                               ModifierData *md,
-                              int mode)
+                              int mode,
+                              bool keep_modifier)
 {
   int prev_mode;
 
@@ -830,7 +831,7 @@ bool ED_object_modifier_apply(Main *bmain,
     BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
     return false;
   }
-  if (ID_REAL_USERS(ob->data) > 1) {
+  if (mode != MODIFIER_APPLY_SHAPE && ID_REAL_USERS(ob->data) > 1) {
     BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
     return false;
   }
@@ -869,8 +870,11 @@ bool ED_object_modifier_apply(Main *bmain,
   }
 
   md_eval->mode = prev_mode;
-  BLI_remlink(&ob->modifiers, md);
-  BKE_modifier_free(md);
+
+  if (!keep_modifier) {
+    BLI_remlink(&ob->modifiers, md);
+    BKE_modifier_free(md);
+  }
 
   BKE_object_free_derived_caches(ob);
 
@@ -1326,7 +1330,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
 /** \name Apply Modifier Operator
  * \{ */
 
-static bool modifier_apply_poll(bContext *C)
+static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
 {
   if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false)) {
     return false;
@@ -1341,7 +1345,7 @@ static bool modifier_apply_poll(bContext *C)
     CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data");
     return false;
   }
-  if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
+  if (!allow_shared && (ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
     CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data");
     return false;
   }
@@ -1356,14 +1360,18 @@ static bool modifier_apply_poll(bContext *C)
   return true;
 }
 
-static int modifier_apply_exec(bContext *C, wmOperator *op)
+static bool modifier_apply_poll(bContext *C)
+{
+  return modifier_apply_poll_ex(C, false);
+}
+
+static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier)
 {
   Main *bmain = CTX_data_main(C);
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
   Scene *scene = CTX_data_scene(C);
   Object *ob = ED_object_active_context(C);
   ModifierData *md = edit_modifier_property_get(op, ob, 0);
-  int apply_as = RNA_enum_get(op->ptr, "apply_as");
 
   if (md == NULL) {
     return OPERATOR_CANCELLED;
@@ -1373,7 +1381,8 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
   char name[MAX_NAME];
   strcpy(name, md->name);
 
-  if (!ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) {
+  if (!ED_object_modifier_apply(
+          bmain, op->reports, depsgraph, scene, ob, md, apply_as, keep_modifier)) {
     return OPERATOR_CANCELLED;
   }
 
@@ -1388,6 +1397,11 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
   return OPERATOR_FINISHED;
 }
 
+static int modifier_apply_exec(bContext *C, wmOperator *op)
+{
+  return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_DATA, false);
+}
+
 static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
   int retval;
@@ -1397,16 +1411,6 @@ static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *eve
   return retval;
 }
 
-static const EnumPropertyItem modifier_apply_as_items[] = {
-    {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
-    {MODIFIER_APPLY_SHAPE,
-     "SHAPE",
-     0,
-     "New Shape",
-     "Apply deform-only modifier to a new shape on this object"},
-    {0, NULL, 0, NULL, NULL},
-};
-
 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
 {
   ot->name = "Apply Modifier";
@@ -1420,12 +1424,68 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 
-  RNA_def_enum(ot->srna,
-               "apply_as",
-               modifier_apply_as_items,
-               MODIFIER_APPLY_DATA,
-               "Apply as",
-               "How to apply the modifier to the geometry");
+  edit_modifier_properties(ot);
+  edit_modifier_report_property(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Apply Modifier As Shapekey Operator
+ * \{ */
+
+static bool modifier_apply_as_shapekey_poll(bContext *C)
+{
+  return modifier_apply_poll_ex(C, true);
+}
+
+static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op)
+{
+  bool keep = RNA_boolean_get(op->ptr, "keep_modifier");
+
+  return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_SHAPE, keep);
+}
+
+static int modifier_apply_as_shapekey_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  int retval;
+  if (edit_modifier_invoke_properties(C, op, event, &retval)) {
+    return modifier_apply_as_shapekey_exec(C, op);
+  }
+  else {
+    return retval;
+  }
+}
+
+static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED(C),
+                                                        struct wmOperatorType *UNUSED(op),
+                                                        struct PointerRNA *values)
+{
+  bool keep = RNA_boolean_get(values, "keep_modifier");
+
+  if (keep) {
+    return BLI_strdup("Apply modifier as a new shapekey and keep it in the stack");
+  }
+
+  return NULL;
+}
+
+void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot)
+{
+  ot->name = "Apply Modifier As Shapekey";
+  ot->description = "Apply modifier as a new shapekey and remove from the stack";
+  ot->idname = "OBJECT_OT_modifier_apply_as_shapekey";
+
+  ot->invoke = modifier_apply_as_shapekey_invoke;
+  ot->exec = modifier_apply_as_shapekey_exec;
+  ot->poll = modifier_apply_as_shapekey_poll;
+  ot->get_description = modifier_apply_as_shapekey_get_description;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+  RNA_def_boolean(
+      ot->srna, "keep_modifier", false, "Keep Modifier", "Do not remove the modifier from stack");
   edit_modifier_properties(ot);
   edit_modifier_report_property(ot);
 }
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index e28bbb3fb1c..92880e5a114 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -130,6 +130,7 @@ void ED_operatortypes_object(void)
   WM_operatortype_append(OBJECT_OT_modifier_move_down);
   WM_operatortype_append(OBJECT_OT_modifier_move_to_index);
   WM_operatortype_append(OBJECT_OT_modifier_apply);
+  WM_operatortype_append(OBJECT_OT_modifier_apply_as_shapekey);
   WM_operatortype_append(OBJECT_OT_modifier_convert);
   WM_operatortype_append(OBJECT_OT_modifier_copy);
   WM_operatortype_append(OBJECT_OT_multires_subdivide);
diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c
index 137f52782a9..01b9e972086 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.c
+++ b/source/blender/modifiers/intern/MOD_ui_common.c
@@ -231,12 +231,19 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v)
 
   /* Apply as shapekey. */
   if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) {
-    uiItemEnumO(layout,
-                "OBJECT_OT_modifier_apply",
-                CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply As Shapekey"),
-                ICON_SHAPEKEY_DATA,
-                "apply_as",
-                MODIFIER_APPLY_SHAPE);
+    uiItemBooleanO(layout,
+                   CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply As Shapekey"),
+                   ICON_SHAPEKEY_DATA,
+                   "OBJECT_OT_modifier_apply_as_shapekey",
+                   "keep_modifier",
+                   false);
+
+    uiItemBooleanO(layout,
+                   CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Save As Shapekey"),
+                   ICON_SHAPEKEY_DATA,
+                   "OBJECT_OT_modifier_apply_as_shapekey",
+                   "keep_modifier",
+                   true);
   }
 
   /* Duplicate. */



More information about the Bf-blender-cvs mailing list