void BKE_pose_channels_free(bPose *pose) { bPoseChannel *pchan; if (pose->chanbase.first) { for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) BKE_pose_channel_free(pchan); BLI_freelistN(&pose->chanbase); } BKE_pose_channels_hash_free(pose); }
/* Helper function for armature separating - remove certain bones from the given armature * sel: remove selected bones from the armature, otherwise the unselected bones are removed * (ob is not in editmode) */ static void separate_armature_bones(Object *ob, short sel) { bArmature *arm = (bArmature *)ob->data; bPoseChannel *pchan, *pchann; EditBone *curbone; /* make local set of editbones to manipulate here */ ED_armature_to_edit(ob); /* go through pose-channels, checking if a bone should be removed */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) { pchann = pchan->next; curbone = editbone_name_exists(arm->edbo, pchan->name); /* check if bone needs to be removed */ if ( (sel && (curbone->flag & BONE_SELECTED)) || (!sel && !(curbone->flag & BONE_SELECTED)) ) { EditBone *ebo; bPoseChannel *pchn; /* clear the bone->parent var of any bone that had this as its parent */ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { if (ebo->parent == curbone) { ebo->parent = NULL; ebo->temp = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */ ebo->flag &= ~BONE_CONNECTED; } } /* clear the pchan->parent var of any pchan that had this as its parent */ for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) { if (pchn->parent == pchan) pchn->parent = NULL; } /* free any of the extra-data this pchan might have */ BKE_pose_channel_free(pchan); BKE_pose_channels_hash_free(ob->pose); /* get rid of unneeded bone */ bone_free(arm, curbone); BLI_freelinkN(&ob->pose->chanbase, pchan); } } /* exit editmode (recalculates pchans too) */ ED_armature_from_edit(ob); ED_armature_edit_free(ob); }
/** * Selectively remove pose channels. */ void BKE_pose_channels_remove( Object *ob, bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data) { /* Erase any associated pose channel, along with any references to them */ if (ob->pose) { bPoseChannel *pchan, *pchan_next; bConstraint *con; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan_next) { pchan_next = pchan->next; if (filter_fn(pchan->name, user_data)) { /* Bone itself is being removed */ BKE_pose_channel_free(pchan); if (ob->pose->chanhash) { BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL); } BLI_freelinkN(&ob->pose->chanbase, pchan); } else { /* Maybe something the bone references is being removed instead? */ for (con = pchan->constraints.first; con; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == ob) { if (ct->subtarget[0]) { if (filter_fn(ct->subtarget, user_data)) { con->flag |= CONSTRAINT_DISABLE; ct->subtarget[0] = 0; } } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 0); } } if (pchan->bbone_prev) { if (filter_fn(pchan->bbone_prev->name, user_data)) pchan->bbone_prev = NULL; } if (pchan->bbone_next) { if (filter_fn(pchan->bbone_next->name, user_data)) pchan->bbone_next = NULL; } if (pchan->custom_tx) { if (filter_fn(pchan->custom_tx->name, user_data)) pchan->custom_tx = NULL; } } } } }