Fix T96205: Active shape key gets lost upon edit mode undo

Regression in d961adb866,
it's important that for the Mesh used for undo storage matches
the shape-key instead of using the coordinates of the Basis key.

Prior to bfdbc78466 a different method of
restoring the basis shape-key coordinates was used (restoring from the
input `Mesh.mvert` array). When undo wrote the edit-mesh into the mesh
this was always NULL so the basis shape keys coordinates were never
used.

Now a parameter has been added so undo can use the active shape for the
meshes vertex coordinates.

Reviewed By: sergey

Maniphest Tasks: T96205

Ref D14258
This commit is contained in:
Campbell Barton 2022-03-07 21:31:48 +11:00
parent 073d2390f0
commit 72e20785e1
Notes: blender-bot 2023-02-14 08:08:54 +01:00
Referenced by issue #96205, Active shape key gets lost upon edit mode undo
3 changed files with 24 additions and 8 deletions

View File

@ -691,8 +691,16 @@ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey)
* \param bm: The source BMesh.
* \param key: The destination key.
* \param mvert: The destination vertex array (in some situations it's coordinates are updated).
* \param active_shapekey_to_mvert: When editing a non-basis shape key, the coordinates for the
* basis are typically copied into the `mvert` array since it makes sense for the meshes
* vertex coordinates to match the "Basis" key.
* When enabled, skip this step and copy #BMVert.co directly to #MVert.co,
* See #BMeshToMeshParams.active_shapekey_to_mvert doc-string.
*/
static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert)
static void bm_to_mesh_shape(BMesh *bm,
Key *key,
MVert *mvert,
const bool active_shapekey_to_mvert)
{
KeyBlock *actkey = static_cast<KeyBlock *>(BLI_findlink(&key->block, bm->shapenr - 1));
@ -776,12 +784,14 @@ static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert)
* In this case it's important to overwrite these coordinates with the basis-keys coordinates. */
bool update_vertex_coords_from_refkey = false;
int cd_shape_offset_refkey = -1;
if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) {
const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey);
if (refkey_uuid != -1) {
cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid);
if (cd_shape_offset_refkey != -1) {
update_vertex_coords_from_refkey = true;
if (active_shapekey_to_mvert == false) {
if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) {
const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey);
if (refkey_uuid != -1) {
cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid);
if (cd_shape_offset_refkey != -1) {
update_vertex_coords_from_refkey = true;
}
}
}
}
@ -1151,7 +1161,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
if (me->key) {
bm_to_mesh_shape(bm, me->key, me->mvert);
bm_to_mesh_shape(bm, me->key, me->mvert, params->active_shapekey_to_mvert);
}
/* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */

View File

@ -69,6 +69,11 @@ struct BMeshToMeshParams {
* that have become invalid from updating the shape-key, see T71865.
*/
uint update_shapekey_indices : 1;
/**
* Instead of copying the basis shape-key into the #MVert array,
* copy the #BMVert.co directly to #MVert.co (used for reading undo data).
*/
uint active_shapekey_to_mvert : 1;
struct CustomData_MeshMasks cd_mask_extra;
};
/**

View File

@ -615,6 +615,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
.calc_object_remap = false,
.update_shapekey_indices = false,
.cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX},
.active_shapekey_to_mvert = true,
}));
um->selectmode = em->selectmode;