Fix T91923: Save/Apply as Shape Key ignores shape keys

Support virtual modifiers when using applying the modifier as a shape.
This commit is contained in:
Campbell Barton 2021-11-10 00:33:22 +11:00
parent 0b01b81754
commit 65c5ebf577
Notes: blender-bot 2023-02-14 08:38:11 +01:00
Referenced by commit 929a210608, Fix T97758: Applying modifiers bakes shape-keys
Referenced by issue #103929, Applying Data Transfer Modifier - only the active Shape Key is taken into account
Referenced by issue #97758, Regression: Applying Vertex Weight Mix modifier bakes all shape keys with values > 0 into a selected shape key or Basis
Referenced by issue #91923, Save/Apply as Shape Key ignores active shape keys
3 changed files with 51 additions and 10 deletions

View File

@ -209,6 +209,7 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
struct ModifierData *md_eval,
const bool use_virtual_modifiers,
const bool build_shapekey_layers);
/* Copies a nomain-Mesh into an existing Mesh. */

View File

@ -1277,10 +1277,16 @@ static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
}
}
/**
* \param use_virtual_modifiers: When enabled calculate virtual-modifiers before applying `md_eval`
* support this since virtual-modieirs are not modifiers from auser perspective,
* allowing shape keys to be included with the modifier being applied, see: T91923.
*/
Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob_eval,
ModifierData *md_eval,
const bool use_virtual_modifiers,
const bool build_shapekey_layers)
{
Mesh *me = ob_eval->runtime.data_orig ? (Mesh *)ob_eval->runtime.data_orig :
@ -1303,22 +1309,49 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
BKE_keyblock_convert_to_mesh(kb, me);
}
if (mti->type == eModifierTypeType_OnlyDeform) {
int numVerts;
float(*deformedVerts)[3] = BKE_mesh_vert_coords_alloc(me, &numVerts);
Mesh *mesh_temp = (Mesh *)BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE);
int numVerts = 0;
float(*deformedVerts)[3] = nullptr;
result = (Mesh *)BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE);
if (use_virtual_modifiers) {
VirtualModifierData virtualModifierData;
for (ModifierData *md_eval_virt =
BKE_modifiers_get_virtual_modifierlist(ob_eval, &virtualModifierData);
md_eval_virt && (md_eval_virt != ob_eval->modifiers.first);
md_eval_virt = md_eval_virt->next) {
if (!BKE_modifier_is_enabled(scene, md_eval_virt, eModifierMode_Realtime)) {
continue;
}
/* All virtual modifiers are deform modifiers. */
const ModifierTypeInfo *mti_virt = BKE_modifier_get_info((ModifierType)md_eval_virt->type);
BLI_assert(mti_virt->type == eModifierTypeType_OnlyDeform);
if (mti_virt->type != eModifierTypeType_OnlyDeform) {
continue;
}
if (deformedVerts == nullptr) {
deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
}
mti_virt->deformVerts(md_eval_virt, &mectx, mesh_temp, deformedVerts, numVerts);
}
}
if (mti->type == eModifierTypeType_OnlyDeform) {
if (deformedVerts == nullptr) {
deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
}
result = mesh_temp;
mti->deformVerts(md_eval, &mectx, result, deformedVerts, numVerts);
BKE_mesh_vert_coords_apply(result, deformedVerts);
if (build_shapekey_layers) {
add_shapekey_layers(result, me);
}
MEM_freeN(deformedVerts);
}
else {
Mesh *mesh_temp = (Mesh *)BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE);
if (deformedVerts != nullptr) {
BKE_mesh_vert_coords_apply(mesh_temp, deformedVerts);
}
if (build_shapekey_layers) {
add_shapekey_layers(mesh_temp, me);
@ -1332,6 +1365,10 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
}
}
if (deformedVerts != nullptr) {
MEM_freeN(deformedVerts);
}
return result;
}

View File

@ -666,12 +666,13 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports),
static Mesh *modifier_apply_create_mesh_for_modifier(Depsgraph *depsgraph,
Object *object,
ModifierData *md_eval,
bool use_virtual_modifiers,
bool build_shapekey_layers)
{
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
Mesh *mesh_applied = BKE_mesh_create_derived_for_modifier(
depsgraph, scene_eval, object_eval, md_eval, build_shapekey_layers);
depsgraph, scene_eval, object_eval, md_eval, use_virtual_modifiers, build_shapekey_layers);
return mesh_applied;
}
@ -708,7 +709,8 @@ static bool modifier_apply_shape(Main *bmain,
return false;
}
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, false);
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(
depsgraph, ob, md_eval, true, false);
if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return false;
@ -767,7 +769,8 @@ static bool modifier_apply_obdata(
}
}
else {
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, true);
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(
depsgraph, ob, md_eval, true, true);
if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return false;