RNA: Object.shape_key_remove method
authorCampbell Barton <ideasman42@gmail.com>
Mon, 8 Jun 2015 09:49:01 +0000 (19:49 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 8 Jun 2015 09:52:04 +0000 (19:52 +1000)
Python had no ability to remove shape keys
Original D1169 from @lichtwerk, with edits

source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/object.c
source/blender/editors/object/object_shapekey.c
source/blender/makesrna/intern/rna_object_api.c

index 08fa096ab53fff9689352cbfdfd9a8b61e6c3a4f..abe12282a1b976fc30f0caa0dfcb2b67db18c8ae 100644 (file)
@@ -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);
index 0465a354f9f3cb8e8bc69da19d26b527dd4dcdef..9482ec778d34d27c8a71c846bf02d890c552eb5f 100644 (file)
@@ -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);
 
index 4f4c5bf864345c505b65368762f6387c8da7e791..8427b17c01a9d9381ee79e3cd358313a271fc9a1 100644 (file)
@@ -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 &lt->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;
index 03bf7ddef4d26648a8b55ef0a1b71d32b2764308..f8fe53063bcadd81ab25a81520cbfd18dac9ebee 100644 (file)
@@ -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) {
index 8f8bfc47b10feb48f85d591fd42df9f639065e0a..8a98d0d8a1a873b45c07d88a26466637f2318bbc 100644 (file)
@@ -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) {
index 2a3688c49f205fd0cfe9b32d6a3918982360ce2c..4b3f34f46c0b13bcf61d9830cbab8ec901c84c78 100644 (file)
@@ -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");