Add a 'Apply and Delete All' operation to shapekeys.
Adds a new option to the 'Delete ShpaKeys' operator, which first applies the current mix to the object data, before removing all shapekeys. Request from @JulienKaspar from Blender studio. Reviewed By: JulienKaspar Differential Revision: https://developer.blender.org/D15443
This commit is contained in:
parent
ecf4f4a71f
commit
92ca920c52
Notes:
blender-bot
2023-02-13 11:51:13 +01:00
Referenced by commit ae49e0e8be
, Cleanup: unused parameter in own recent commit rB92ca920c52b9.
|
@ -58,7 +58,12 @@ class MESH_MT_shape_key_context_menu(Menu):
|
|||
layout.operator("object.join_shapes")
|
||||
layout.operator("object.shape_key_transfer")
|
||||
layout.separator()
|
||||
layout.operator("object.shape_key_remove", icon='X', text="Delete All Shape Keys").all = True
|
||||
op = layout.operator("object.shape_key_remove", icon='X', text="Delete All Shape Keys")
|
||||
op.all = True
|
||||
op.apply_mix = False
|
||||
op = layout.operator("object.shape_key_remove", text="Apply All Shape Keys")
|
||||
op.all = True
|
||||
op.apply_mix = True
|
||||
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'
|
||||
|
|
|
@ -46,8 +46,11 @@ void key_curve_normal_weights(float t, float data[4], int type);
|
|||
|
||||
/**
|
||||
* Returns key coordinates (+ tilt) when key applied, NULL otherwise.
|
||||
*
|
||||
* \param obdata if given, also update that geometry with the result of the shape keys evaluation.
|
||||
*/
|
||||
float *BKE_key_evaluate_object_ex(struct Object *ob, int *r_totelem, float *arr, size_t arr_size);
|
||||
float *BKE_key_evaluate_object_ex(
|
||||
struct Object *ob, int *r_totelem, float *arr, size_t arr_size, struct ID *obdata);
|
||||
float *BKE_key_evaluate_object(struct Object *ob, int *r_totelem);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1501,7 +1501,14 @@ static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
|
|||
}
|
||||
}
|
||||
|
||||
float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t arr_size)
|
||||
static void keyblock_data_convert_to_mesh(const float (*fp)[3], MVert *mvert, const int totvert);
|
||||
static void keyblock_data_convert_to_lattice(const float (*fp)[3],
|
||||
BPoint *bpoint,
|
||||
const int totpoint);
|
||||
static void keyblock_data_convert_to_curve(const float *fp, ListBase *nurb, const int totpoint);
|
||||
|
||||
float *BKE_key_evaluate_object_ex(
|
||||
Object *ob, int *r_totelem, float *arr, size_t arr_size, ID *obdata)
|
||||
{
|
||||
Key *key = BKE_key_from_object(ob);
|
||||
KeyBlock *actkb = BKE_keyblock_from_object(ob);
|
||||
|
@ -1576,7 +1583,6 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
|
|||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
do_mesh_key(ob, key, out, tot);
|
||||
}
|
||||
|
@ -1591,6 +1597,31 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
|
|||
}
|
||||
}
|
||||
|
||||
if (obdata != NULL) {
|
||||
switch (GS(obdata->name)) {
|
||||
case ID_ME: {
|
||||
Mesh *mesh = (Mesh *)obdata;
|
||||
const int totvert = min_ii(tot, mesh->totvert);
|
||||
keyblock_data_convert_to_mesh((const float(*)[3])out, mesh->mvert, totvert);
|
||||
break;
|
||||
}
|
||||
case ID_LT: {
|
||||
Lattice *lattice = (Lattice *)obdata;
|
||||
const int totpoint = min_ii(tot, lattice->pntsu * lattice->pntsv * lattice->pntsw);
|
||||
keyblock_data_convert_to_lattice((const float(*)[3])out, lattice->def, totpoint);
|
||||
break;
|
||||
}
|
||||
case ID_CU_LEGACY: {
|
||||
Curve *curve = (Curve *)obdata;
|
||||
const int totpoint = min_ii(tot, BKE_keyblock_curve_element_count(&curve->nurb));
|
||||
keyblock_data_convert_to_curve((const float *)out, &curve->nurb, totpoint);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
if (r_totelem) {
|
||||
*r_totelem = tot;
|
||||
}
|
||||
|
@ -1599,7 +1630,7 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
|
|||
|
||||
float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
|
||||
{
|
||||
return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
|
||||
return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
int BKE_keyblock_element_count_from_shape(const Key *key, const int shape_index)
|
||||
|
@ -1971,21 +2002,22 @@ void BKE_keyblock_convert_from_lattice(const Lattice *lt, KeyBlock *kb)
|
|||
BKE_keyblock_update_from_lattice(lt, kb);
|
||||
}
|
||||
|
||||
static void keyblock_data_convert_to_lattice(const float (*fp)[3],
|
||||
BPoint *bpoint,
|
||||
const int totpoint)
|
||||
{
|
||||
for (int i = 0; i < totpoint; i++, fp++, bpoint++) {
|
||||
copy_v3_v3(bpoint->vec, *fp);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_keyblock_convert_to_lattice(const KeyBlock *kb, Lattice *lt)
|
||||
{
|
||||
BPoint *bp;
|
||||
const float(*fp)[3];
|
||||
int a, tot;
|
||||
BPoint *bp = lt->def;
|
||||
const float(*fp)[3] = kb->data;
|
||||
const int tot = min_ii(kb->totelem, lt->pntsu * lt->pntsv * lt->pntsw);
|
||||
|
||||
bp = lt->def;
|
||||
fp = kb->data;
|
||||
|
||||
tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
||||
tot = min_ii(kb->totelem, tot);
|
||||
|
||||
for (a = 0; a < tot; a++, fp++, bp++) {
|
||||
copy_v3_v3(bp->vec, *fp);
|
||||
}
|
||||
keyblock_data_convert_to_lattice(fp, bp, tot);
|
||||
}
|
||||
|
||||
/************************* Curve ************************/
|
||||
|
@ -2097,42 +2129,40 @@ void BKE_keyblock_convert_from_curve(const Curve *cu, KeyBlock *kb, const ListBa
|
|||
BKE_keyblock_update_from_curve(cu, kb, nurb);
|
||||
}
|
||||
|
||||
void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
|
||||
static void keyblock_data_convert_to_curve(const float *fp, ListBase *nurb, int totpoint)
|
||||
{
|
||||
Nurb *nu;
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
const float *fp;
|
||||
int a, tot;
|
||||
|
||||
tot = BKE_keyblock_curve_element_count(nurb);
|
||||
tot = min_ii(kb->totelem, tot);
|
||||
|
||||
fp = kb->data;
|
||||
for (nu = nurb->first; nu && tot > 0; nu = nu->next) {
|
||||
if (nu->bezt) {
|
||||
for (a = nu->pntsu, bezt = nu->bezt; a && (tot -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0;
|
||||
a--, bezt++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
copy_v3_v3(bezt->vec[i], &fp[i * 3]);
|
||||
for (Nurb *nu = nurb->first; nu && totpoint > 0; nu = nu->next) {
|
||||
if (nu->bezt != NULL) {
|
||||
BezTriple *bezt = nu->bezt;
|
||||
for (int i = nu->pntsu; i && (totpoint -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0;
|
||||
i--, bezt++, fp += KEYELEM_FLOAT_LEN_BEZTRIPLE) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
copy_v3_v3(bezt->vec[j], &fp[j * 3]);
|
||||
}
|
||||
bezt->tilt = fp[9];
|
||||
bezt->radius = fp[10];
|
||||
fp += KEYELEM_FLOAT_LEN_BEZTRIPLE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a && (tot -= KEYELEM_ELEM_LEN_BPOINT) >= 0;
|
||||
a--, bp++) {
|
||||
BPoint *bp = nu->bp;
|
||||
for (int i = nu->pntsu * nu->pntsv; i && (totpoint -= KEYELEM_ELEM_LEN_BPOINT) >= 0;
|
||||
i--, bp++, fp += KEYELEM_FLOAT_LEN_BPOINT) {
|
||||
copy_v3_v3(bp->vec, fp);
|
||||
bp->tilt = fp[3];
|
||||
bp->radius = fp[4];
|
||||
fp += KEYELEM_FLOAT_LEN_BPOINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
|
||||
{
|
||||
const float *fp = kb->data;
|
||||
const int tot = min_ii(kb->totelem, BKE_keyblock_curve_element_count(nurb));
|
||||
|
||||
keyblock_data_convert_to_curve(fp, nurb, tot);
|
||||
}
|
||||
|
||||
/************************* Mesh ************************/
|
||||
|
||||
void BKE_keyblock_update_from_mesh(const Mesh *me, KeyBlock *kb)
|
||||
|
@ -2171,20 +2201,21 @@ void BKE_keyblock_convert_from_mesh(const Mesh *me, const Key *key, KeyBlock *kb
|
|||
BKE_keyblock_update_from_mesh(me, kb);
|
||||
}
|
||||
|
||||
void BKE_keyblock_convert_to_mesh(const KeyBlock *kb, MVert *mvert, const int totvert)
|
||||
static void keyblock_data_convert_to_mesh(const float (*fp)[3], MVert *mvert, const int totvert)
|
||||
{
|
||||
const float(*fp)[3];
|
||||
int a, tot;
|
||||
|
||||
fp = kb->data;
|
||||
|
||||
tot = min_ii(kb->totelem, totvert);
|
||||
|
||||
for (a = 0; a < tot; a++, fp++, mvert++) {
|
||||
for (int i = 0; i < totvert; i++, fp++, mvert++) {
|
||||
copy_v3_v3(mvert->co, *fp);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_keyblock_convert_to_mesh(const KeyBlock *kb, MVert *mvert, const int totvert)
|
||||
{
|
||||
const float(*fp)[3] = kb->data;
|
||||
const int tot = min_ii(kb->totelem, totvert);
|
||||
|
||||
keyblock_data_convert_to_mesh(fp, mvert, tot);
|
||||
}
|
||||
|
||||
void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
const Mesh *mesh,
|
||||
float (*r_vertnors)[3],
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
@ -299,6 +301,10 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op)
|
|||
bool changed = false;
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "all")) {
|
||||
if (RNA_boolean_get(op->ptr, "apply_mix")) {
|
||||
float *arr = BKE_key_evaluate_object_ex(ob, NULL, NULL, 0, ob->data);
|
||||
MEM_freeN(arr);
|
||||
}
|
||||
changed = BKE_object_shapekey_free(bmain, ob);
|
||||
}
|
||||
else {
|
||||
|
@ -315,6 +321,34 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static bool shape_key_remove_poll_property(const bContext *C,
|
||||
wmOperator *op,
|
||||
const PropertyRNA *prop)
|
||||
{
|
||||
const char *prop_id = RNA_property_identifier(prop);
|
||||
const bool do_all = RNA_enum_get(op->ptr, "all");
|
||||
|
||||
/* Only show seed for randomize action! */
|
||||
if (STREQ(prop_id, "apply_mix") && !do_all) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *shape_key_remove_get_description(bContext *UNUSED(C),
|
||||
wmOperatorType *UNUSED(ot),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
const bool do_apply_mix = RNA_boolean_get(ptr, "apply_mix");
|
||||
|
||||
if (do_apply_mix) {
|
||||
return BLI_strdup(
|
||||
TIP_("Apply current visible shape to the object data, and delete all shape keys"));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -325,12 +359,19 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
|
|||
/* api callbacks */
|
||||
ot->poll = shape_key_mode_exists_poll;
|
||||
ot->exec = shape_key_remove_exec;
|
||||
ot->poll_property = shape_key_remove_poll_property;
|
||||
ot->get_description = shape_key_remove_get_description;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
|
||||
RNA_def_boolean(ot->srna, "all", false, "All", "Remove all shape keys");
|
||||
RNA_def_boolean(ot->srna,
|
||||
"apply_mix",
|
||||
false,
|
||||
"Apply Mix",
|
||||
"Apply current mix of shape keys to the geometry before removing them");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -36,7 +36,7 @@ static void deformVerts(ModifierData *UNUSED(md),
|
|||
if (key && key->block.first) {
|
||||
int deformedVerts_tot;
|
||||
BKE_key_evaluate_object_ex(
|
||||
ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * verts_num);
|
||||
ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * verts_num, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue