/* put EditMode back in Object */ void ED_armature_from_edit(bArmature *arm) { EditBone *eBone, *neBone; Bone *newBone; Object *obt; /* armature bones */ BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; /* remove zero sized bones, this gives unstable restposes */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len_sq = len_squared_v3v3(eBone->head, eBone->tail); neBone = eBone->next; if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */ EditBone *fBone; /* Find any bones that refer to this bone */ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) { if (fBone->parent == eBone) fBone->parent = eBone->parent; } if (G.debug & G_DEBUG) printf("Warning: removed zero sized bone: %s\n", eBone->name); bone_free(arm, eBone); } } /* Copy the bones from the editData into the armature */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name)); copy_v3_v3(newBone->arm_head, eBone->head); copy_v3_v3(newBone->arm_tail, eBone->tail); newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses * editmode toggle and can separate active bone which is de-selected originally */ /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */ arm->act_bone = newBone; } newBone->roll = 0.0f; newBone->weight = eBone->weight; newBone->dist = eBone->dist; newBone->xwidth = eBone->xwidth; newBone->zwidth = eBone->zwidth; newBone->rad_head = eBone->rad_head; newBone->rad_tail = eBone->rad_tail; newBone->segments = eBone->segments; newBone->layer = eBone->layer; /* Bendy-Bone parameters */ newBone->roll1 = eBone->roll1; newBone->roll2 = eBone->roll2; newBone->curveInX = eBone->curveInX; newBone->curveInY = eBone->curveInY; newBone->curveOutX = eBone->curveOutX; newBone->curveOutY = eBone->curveOutY; newBone->ease1 = eBone->ease1; newBone->ease2 = eBone->ease2; newBone->scaleIn = eBone->scaleIn; newBone->scaleOut = eBone->scaleOut; if (eBone->prop) newBone->prop = IDP_CopyProperty(eBone->prop); } /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point. * Do not set bone->head/tail here anymore, using EditBone data for that is not OK since our later fiddling * with parent's arm_mat (for roll conversion) may have some small but visible impact on locations (T46010). */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = eBone->temp.bone; if (eBone->parent) { newBone->parent = eBone->parent->temp.bone; BLI_addtail(&newBone->parent->childbase, newBone); } /* ...otherwise add this bone to the armature's bonebase */ else { BLI_addtail(&arm->bonebase, newBone); } } /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */ armature_finalize_restpose(&arm->bonebase, arm->edbo); /* so all users of this armature should get rebuilt */ for (obt = G.main->object.first; obt; obt = obt->id.next) { if (obt->data == arm) { BKE_pose_rebuild(obt, arm); } } DAG_id_tag_update(&arm->id, 0); }
/* put EditMode back in Object */ void ED_armature_from_edit(bArmature *arm) { EditBone *eBone, *neBone; Bone *newBone; Object *obt; /* armature bones */ BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; /* remove zero sized bones, this gives unstable restposes */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len = len_v3v3(eBone->head, eBone->tail); neBone = eBone->next; if (len <= 0.000001f) { /* FLT_EPSILON is too large? */ EditBone *fBone; /* Find any bones that refer to this bone */ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) { if (fBone->parent == eBone) fBone->parent = eBone->parent; } if (G.debug & G_DEBUG) printf("Warning: removed zero sized bone: %s\n", eBone->name); bone_free(arm, eBone); } } /* Copy the bones from the editData into the armature */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name)); copy_v3_v3(newBone->arm_head, eBone->head); copy_v3_v3(newBone->arm_tail, eBone->tail); newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses * editmode toggle and can separate active bone which is de-selected originally */ /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */ arm->act_bone = newBone; } newBone->roll = 0.0f; newBone->weight = eBone->weight; newBone->dist = eBone->dist; newBone->xwidth = eBone->xwidth; newBone->zwidth = eBone->zwidth; newBone->ease1 = eBone->ease1; newBone->ease2 = eBone->ease2; newBone->rad_head = eBone->rad_head; newBone->rad_tail = eBone->rad_tail; newBone->segments = eBone->segments; newBone->layer = eBone->layer; if (eBone->prop) newBone->prop = IDP_CopyProperty(eBone->prop); } /* Fix parenting in a separate pass to ensure ebone->bone connections * are valid at this point */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = eBone->temp.bone; if (eBone->parent) { newBone->parent = eBone->parent->temp.bone; BLI_addtail(&newBone->parent->childbase, newBone); { float M_parentRest[3][3]; float iM_parentRest[3][3]; /* Get the parent's matrix (rotation only) */ ED_armature_ebone_to_mat3(eBone->parent, M_parentRest); /* Invert the parent matrix */ invert_m3_m3(iM_parentRest, M_parentRest); /* Get the new head and tail */ sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail); sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail); mul_m3_v3(iM_parentRest, newBone->head); mul_m3_v3(iM_parentRest, newBone->tail); } } /* ...otherwise add this bone to the armature's bonebase */ else { copy_v3_v3(newBone->head, eBone->head); copy_v3_v3(newBone->tail, eBone->tail); BLI_addtail(&arm->bonebase, newBone); } } /* Make a pass through the new armature to fix rolling */ /* also builds restposition again (like BKE_armature_where_is) */ fix_bonelist_roll(&arm->bonebase, arm->edbo); /* so all users of this armature should get rebuilt */ for (obt = G.main->object.first; obt; obt = obt->id.next) { if (obt->data == arm) BKE_pose_rebuild(obt, arm); } DAG_id_tag_update(&arm->id, 0); }