/** * Looks to see if the channel with the given name * already exists in this pose - if not a new one is * allocated and initialized. * * \note Use with care, not on Armature poses but for temporal ones. * \note (currently used for action constraints and in rebuild_pose). */ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) { bPoseChannel *chan; if (pose == NULL) return NULL; /* See if this channel exists */ chan = BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name)); if (chan) { return chan; } /* If not, create it and add it */ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); BLI_strncpy(chan->name, name, sizeof(chan->name)); /* init vars to prevent math errors */ unit_qt(chan->quat); unit_axis_angle(chan->rotAxis, &chan->rotAngle); chan->size[0] = chan->size[1] = chan->size[2] = 1.0f; chan->limitmin[0] = chan->limitmin[1] = chan->limitmin[2] = -180.0f; chan->limitmax[0] = chan->limitmax[1] = chan->limitmax[2] = 180.0f; chan->stiffness[0] = chan->stiffness[1] = chan->stiffness[2] = 0.0f; chan->ikrotweight = chan->iklinweight = 0.0f; unit_m4(chan->constinv); chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */ BLI_addtail(&pose->chanbase, chan); BKE_pose_channels_hash_free(pose); return chan; }
/** * Removes and deallocates all channels from a pose. * Does not free the pose itself. */ void BKE_pose_channels_free_ex(bPose *pose, bool do_id_user) { bPoseChannel *pchan; if (pose->chanbase.first) { for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) BKE_pose_channel_free_ex(pchan, do_id_user); BLI_freelistN(&pose->chanbase); } BKE_pose_channels_hash_free(pose); }
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); }
void postEditBoneDuplicate(struct ListBase *editbones, Object *ob) { if (ob->pose == NULL) { return; } BKE_pose_channels_hash_free(ob->pose); BKE_pose_channels_hash_make(ob->pose); GHash *name_map = BLI_ghash_str_new(__func__); for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) { EditBone *ebone_dst = ebone_src->temp.ebone; if (!ebone_dst) { ebone_dst = ED_armature_bone_get_mirrored(editbones, ebone_src); } if (ebone_dst) { BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name); } } for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) { EditBone *ebone_dst = ebone_src->temp.ebone; if (ebone_dst) { bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name); if (pchan_src) { bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name); if (pchan_dst) { if (pchan_src->custom_tx) { pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx); } if (pchan_src->bbone_prev) { pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev); } if (pchan_src->bbone_next) { pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next); } } } } } BLI_ghash_free(name_map, NULL, NULL); }
/* join armature exec is exported for use in object->join objects operator... */ int join_armature_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); bArmature *arm = (ob) ? ob->data : NULL; bPose *pose, *opose; bPoseChannel *pchan, *pchann; EditBone *curbone; float mat[4][4], oimat[4][4]; /* Ensure we're not in editmode and that the active object is an armature*/ if (!ob || ob->type != OB_ARMATURE) return OPERATOR_CANCELLED; if (!arm || arm->edbo) return OPERATOR_CANCELLED; /* Get editbones of active armature to add editbones to */ ED_armature_to_edit(ob); /* get pose of active object and move it out of posemode */ pose = ob->pose; ob->mode &= ~OB_MODE_POSE; CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases) { if ((base->object->type == OB_ARMATURE) && (base->object != ob)) { bArmature *curarm = base->object->data; /* Make a list of editbones in current armature */ ED_armature_to_edit(base->object); /* Get Pose of current armature */ opose = base->object->pose; base->object->mode &= ~OB_MODE_POSE; //BASACT->flag &= ~OB_MODE_POSE; /* Find the difference matrix */ invert_m4_m4(oimat, ob->obmat); mult_m4_m4m4(mat, oimat, base->object->obmat); /* Copy bones and posechannels from the object to the edit armature */ for (pchan = opose->chanbase.first; pchan; pchan = pchann) { pchann = pchan->next; curbone = editbone_name_exists(curarm->edbo, pchan->name); /* Get new name */ unique_editbone_name(arm->edbo, curbone->name, NULL); /* Transform the bone */ { float premat[4][4]; float postmat[4][4]; float difmat[4][4]; float imat[4][4]; float temp[3][3]; float delta[3]; /* Get the premat */ sub_v3_v3v3(delta, curbone->tail, curbone->head); vec_roll_to_mat3(delta, curbone->roll, temp); unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */ mul_m4_m3m4(premat, temp, mat); mul_m4_v3(mat, curbone->head); mul_m4_v3(mat, curbone->tail); /* Get the postmat */ sub_v3_v3v3(delta, curbone->tail, curbone->head); vec_roll_to_mat3(delta, curbone->roll, temp); copy_m4_m3(postmat, temp); /* Find the roll */ invert_m4_m4(imat, premat); mult_m4_m4m4(difmat, imat, postmat); curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]); } /* Fix Constraints and Other Links to this Bone and Armature */ joined_armature_fix_links(ob, base->object, pchan, curbone); /* Rename pchan */ BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name)); /* Jump Ship! */ BLI_remlink(curarm->edbo, curbone); BLI_addtail(arm->edbo, curbone); BLI_remlink(&opose->chanbase, pchan); BLI_addtail(&pose->chanbase, pchan); BKE_pose_channels_hash_free(opose); BKE_pose_channels_hash_free(pose); } ED_base_object_free_and_unlink(bmain, scene, base); } } CTX_DATA_END; DAG_relations_tag_update(bmain); /* because we removed object(s) */ ED_armature_from_edit(ob); ED_armature_edit_free(ob); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; }