diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2020-07-01 17:38:07 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2020-07-08 11:06:57 +0300 |
commit | 01c8aa12a17775cce03106a576f3c498d28131e4 (patch) | |
tree | 0ec11befa4e3444fd94256736ba0f09e0317dc92 /source/blender/editors/object/object_modifier.c | |
parent | 7fcb6bc59c85beab36dbfcec91d0cfaf5291f029 (diff) |
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
Diffstat (limited to 'source/blender/editors/object/object_modifier.c')
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 110 |
1 files changed, 85 insertions, 25 deletions
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); } |