From 87629b2a7443f1b2bf41062aec5054ab1123ca83 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Jun 2015 19:49:01 +1000 Subject: RNA: Object.shape_key_remove method Python had no ability to remove shape keys Original D1169 from @lichtwerk, with edits --- source/blender/blenkernel/BKE_key.h | 1 + source/blender/blenkernel/BKE_object.h | 4 +- source/blender/blenkernel/intern/key.c | 24 +++++-- source/blender/blenkernel/intern/object.c | 81 ++++++++++++++++++++++- source/blender/editors/object/object_shapekey.c | 86 +++---------------------- source/blender/makesrna/intern/rna_object_api.c | 34 +++++++++- 6 files changed, 143 insertions(+), 87 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 08fa096ab53..abe12282a1b 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -65,6 +65,7 @@ float *BKE_key_evaluate_object_ex( float *BKE_key_evaluate_object( struct Object *ob, int *r_totelem); +struct Key **BKE_key_from_object_p(struct Object *ob); struct Key *BKE_key_from_object(struct Object *ob); struct KeyBlock *BKE_keyblock_from_object(struct Object *ob); struct KeyBlock *BKE_keyblock_from_object_reference(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0465a354f9f..9482ec778d3 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -217,7 +217,9 @@ int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float * int BKE_object_insert_ptcache(struct Object *ob); void BKE_object_delete_ptcache(struct Object *ob, int index); -struct KeyBlock *BKE_object_insert_shape_key(struct Object *ob, const char *name, const bool from_mix); +struct KeyBlock *BKE_object_shapekey_insert(struct Object *ob, const char *name, const bool from_mix); +bool BKE_object_shapekey_remove(struct Main *bmain, struct Object *ob, struct KeyBlock *kb); +bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob); bool BKE_object_flag_test_recursive(const struct Object *ob, short flag); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 4f4c5bf8643..8427b17c01a 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1392,25 +1392,37 @@ float *BKE_key_evaluate_object(Object *ob, int *r_totelem) return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0); } -Key *BKE_key_from_object(Object *ob) +Key **BKE_key_from_object_p(Object *ob) { - if (ob == NULL) return NULL; - + if (ob == NULL) + return NULL; + if (ob->type == OB_MESH) { Mesh *me = ob->data; - return me->key; + return &me->key; } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - return cu->key; + return &cu->key; } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; - return lt->key; + return <->key; } return NULL; } +Key *BKE_key_from_object(Object *ob) +{ + Key **key_p; + key_p = BKE_key_from_object_p(ob); + if (key_p) { + return *key_p; + } + + return NULL; +} + KeyBlock *BKE_keyblock_add(Key *key, const char *name) { KeyBlock *kb; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 03bf7ddef4d..f8fe53063bc 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3358,7 +3358,7 @@ static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_m return kb; } -KeyBlock *BKE_object_insert_shape_key(Object *ob, const char *name, const bool from_mix) +KeyBlock *BKE_object_shapekey_insert(Object *ob, const char *name, const bool from_mix) { switch (ob->type) { case OB_MESH: @@ -3374,6 +3374,85 @@ KeyBlock *BKE_object_insert_shape_key(Object *ob, const char *name, const bool f } +bool BKE_object_shapekey_free(Main *bmain, Object *ob) +{ + Key **key_p, *key; + + key_p = BKE_key_from_object_p(ob); + if (ELEM(NULL, key_p, *key_p)) { + return false; + } + + key = *key_p; + *key_p = NULL; + + BKE_libblock_free_us(bmain, key); + + return false; +} + +bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb) +{ + KeyBlock *rkb; + Key *key = BKE_key_from_object(ob); + short kb_index; + + if (key == NULL) { + return false; + } + + kb_index = BLI_findindex(&key->block, kb); + BLI_assert(kb_index != -1); + + for (rkb = key->block.first; rkb; rkb = rkb->next) { + if (rkb->relative == kb_index) { + /* remap to the 'Basis' */ + rkb->relative = 0; + } + else if (rkb->relative >= kb_index) { + /* Fix positional shift of the keys when kb is deleted from the list */ + rkb->relative -= 1; + } + } + + BLI_remlink(&key->block, kb); + key->totkey--; + if (key->refkey == kb) { + key->refkey = key->block.first; + + if (key->refkey) { + /* apply new basis key on original data */ + switch (ob->type) { + case OB_MESH: + BKE_keyblock_convert_to_mesh(key->refkey, ob->data); + break; + case OB_CURVE: + case OB_SURF: + BKE_keyblock_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data)); + break; + case OB_LATTICE: + BKE_keyblock_convert_to_lattice(key->refkey, ob->data); + break; + } + } + } + + if (kb->data) { + MEM_freeN(kb->data); + } + MEM_freeN(kb); + + if (ob->shapenr > 1) { + ob->shapenr--; + } + + if (key->totkey == 0) { + BKE_object_shapekey_free(bmain, ob); + } + + return true; +} + bool BKE_object_flag_test_recursive(const Object *ob, short flag) { if (ob->flag & flag) { diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 8f8bfc47b10..8a98d0d8a1a 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -77,7 +77,7 @@ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix) { KeyBlock *kb; - if ((kb = BKE_object_insert_shape_key(ob, NULL, from_mix))) { + if ((kb = BKE_object_shapekey_insert(ob, NULL, from_mix))) { Key *key = BKE_key_from_object(ob); /* for absolute shape keys, new keys may not be added last */ ob->shapenr = BLI_findindex(&key->block, kb) + 1; @@ -88,89 +88,21 @@ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix /*********************** remove shape key ***********************/ -static bool ED_object_shape_key_remove_all(Main *bmain, Object *ob) +static bool object_shapekey_remove(Main *bmain, Object *ob) { - Key *key; + KeyBlock *kb; + Key *key = BKE_key_from_object(ob); - key = BKE_key_from_object(ob); - if (key == NULL) + if (key == NULL) { return false; - - switch (GS(key->from->name)) { - case ID_ME: ((Mesh *)key->from)->key = NULL; break; - case ID_CU: ((Curve *)key->from)->key = NULL; break; - case ID_LT: ((Lattice *)key->from)->key = NULL; break; } - BKE_libblock_free_us(bmain, key); - - return true; -} - -static bool ED_object_shape_key_remove(Main *bmain, Object *ob) -{ - KeyBlock *kb, *rkb; - Key *key; - - key = BKE_key_from_object(ob); - if (key == NULL) - return false; - kb = BLI_findlink(&key->block, ob->shapenr - 1); - if (kb) { - for (rkb = key->block.first; rkb; rkb = rkb->next) { - if (rkb->relative == ob->shapenr - 1) { - /* remap to the 'Basis' */ - rkb->relative = 0; - } - else if (rkb->relative >= ob->shapenr) { - /* Fix positional shift of the keys when kb is deleted from the list */ - rkb->relative -= 1; - } - } - - BLI_remlink(&key->block, kb); - key->totkey--; - if (key->refkey == kb) { - key->refkey = key->block.first; - - if (key->refkey) { - /* apply new basis key on original data */ - switch (ob->type) { - case OB_MESH: - BKE_keyblock_convert_to_mesh(key->refkey, ob->data); - break; - case OB_CURVE: - case OB_SURF: - BKE_keyblock_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data)); - break; - case OB_LATTICE: - BKE_keyblock_convert_to_lattice(key->refkey, ob->data); - break; - } - } - } - - if (kb->data) MEM_freeN(kb->data); - MEM_freeN(kb); - - if (ob->shapenr > 1) { - ob->shapenr--; - } - } - - if (key->totkey == 0) { - switch (GS(key->from->name)) { - case ID_ME: ((Mesh *)key->from)->key = NULL; break; - case ID_CU: ((Curve *)key->from)->key = NULL; break; - case ID_LT: ((Lattice *)key->from)->key = NULL; break; - } - - BKE_libblock_free_us(bmain, key); + return BKE_object_shapekey_remove(bmain, ob, kb); } - return true; + return false; } static bool object_shape_key_mirror(bContext *C, Object *ob, @@ -361,10 +293,10 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op) bool changed = false; if (RNA_boolean_get(op->ptr, "all")) { - changed = ED_object_shape_key_remove_all(bmain, ob); + changed = BKE_object_shapekey_free(bmain, ob); } else { - changed = ED_object_shape_key_remove(bmain, ob); + changed = object_shapekey_remove(bmain, ob); } if (changed) { diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 2a3688c49f2..4b3f34f46c0 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -229,7 +229,7 @@ static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList * { KeyBlock *kb = NULL; - if ((kb = BKE_object_insert_shape_key(ob, name, from_mix))) { + if ((kb = BKE_object_shapekey_insert(ob, name, from_mix))) { PointerRNA keyptr; RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr); @@ -243,6 +243,29 @@ static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList * } } +static void rna_Object_shape_key_remove( + Object *ob, Main *bmain, ReportList *reports, + PointerRNA *kb_ptr) +{ + KeyBlock *kb = kb_ptr->data; + Key *key = BKE_key_from_object(ob); + + if ((key == NULL) || BLI_findindex(&key->block, kb) == -1) { + BKE_reportf(reports, RPT_ERROR, "ShapeKey not found"); + return; + } + + if (!BKE_object_shapekey_remove(bmain, ob, kb)) { + BKE_reportf(reports, RPT_ERROR, "Could not remove ShapeKey"); + return; + } + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); + + RNA_POINTER_INVALIDATE(kb_ptr); +} + static int rna_Object_is_visible(Object *ob, Scene *sce) { return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay); @@ -557,7 +580,7 @@ void RNA_api_object(StructRNA *srna) /* Shape key */ func = RNA_def_function(srna, "shape_key_add", "rna_Object_shape_key_add"); - RNA_def_function_ui_description(func, "Add shape key to an object"); + RNA_def_function_ui_description(func, "Add shape key to this object"); RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); RNA_def_string(func, "name", "Key", 0, "", "Unique name for the new keyblock"); /* optional */ RNA_def_boolean(func, "from_mix", 1, "", "Create new shape from existing mix of shapes"); @@ -565,6 +588,13 @@ void RNA_api_object(StructRNA *srna) RNA_def_property_flag(parm, PROP_RNAPTR); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "shape_key_remove", "rna_Object_shape_key_remove"); + RNA_def_function_ui_description(func, "Remove a Shape Key from this object"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "key", "ShapeKey", "", "Keyblock to be removed"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); + /* Ray Cast */ func = RNA_def_function(srna, "ray_cast", "rna_Object_ray_cast"); RNA_def_function_ui_description(func, "Cast a ray onto in object space"); -- cgit v1.2.3