diff options
Diffstat (limited to 'source/blender/editors/armature/armature_utils.c')
-rw-r--r-- | source/blender/editors/armature/armature_utils.c | 1187 |
1 files changed, 594 insertions, 593 deletions
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 465209eb9c5..50289197ed4 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -50,34 +50,34 @@ /* Sync selection to parent for connected children */ void ED_armature_edit_sync_selection(ListBase *edbo) { - EditBone *ebo; - - for (ebo = edbo->first; ebo; ebo = ebo->next) { - /* if bone is not selectable, we shouldn't alter this setting... */ - if ((ebo->flag & BONE_UNSELECTABLE) == 0) { - if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) { - if (ebo->parent->flag & BONE_TIPSEL) - ebo->flag |= BONE_ROOTSEL; - else - ebo->flag &= ~BONE_ROOTSEL; - } - - if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) - ebo->flag |= BONE_SELECTED; - else - ebo->flag &= ~BONE_SELECTED; - } - } + EditBone *ebo; + + for (ebo = edbo->first; ebo; ebo = ebo->next) { + /* if bone is not selectable, we shouldn't alter this setting... */ + if ((ebo->flag & BONE_UNSELECTABLE) == 0) { + if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) { + if (ebo->parent->flag & BONE_TIPSEL) + ebo->flag |= BONE_ROOTSEL; + else + ebo->flag &= ~BONE_ROOTSEL; + } + + if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) + ebo->flag |= BONE_SELECTED; + else + ebo->flag &= ~BONE_SELECTED; + } + } } void ED_armature_edit_validate_active(struct bArmature *arm) { - EditBone *ebone = arm->act_edbone; + EditBone *ebone = arm->act_edbone; - if (ebone) { - if (ebone->flag & BONE_HIDDEN_A) - arm->act_edbone = NULL; - } + if (ebone) { + if (ebone->flag & BONE_HIDDEN_A) + arm->act_edbone = NULL; + } } /* *************************************************************** */ @@ -85,31 +85,30 @@ void ED_armature_edit_validate_active(struct bArmature *arm) /* XXX bone_looper is only to be used when we want to access settings * (i.e. editability/visibility/selected) that context doesn't offer */ -int bone_looper(Object *ob, Bone *bone, void *data, - int (*bone_func)(Object *, Bone *, void *)) +int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *)) { - /* We want to apply the function bone_func to every bone - * in an armature -- feed bone_looper the first bone and - * a pointer to the bone_func and watch it go!. The int count - * can be useful for counting bones with a certain property - * (e.g. skinnable) - */ - int count = 0; + /* We want to apply the function bone_func to every bone + * in an armature -- feed bone_looper the first bone and + * a pointer to the bone_func and watch it go!. The int count + * can be useful for counting bones with a certain property + * (e.g. skinnable) + */ + int count = 0; - if (bone) { - /* only do bone_func if the bone is non null */ - count += bone_func(ob, bone, data); + if (bone) { + /* only do bone_func if the bone is non null */ + count += bone_func(ob, bone, data); - /* try to execute bone_func for the first child */ - count += bone_looper(ob, bone->childbase.first, data, bone_func); + /* try to execute bone_func for the first child */ + count += bone_looper(ob, bone->childbase.first, data, bone_func); - /* try to execute bone_func for the next bone at this - * depth of the recursion. - */ - count += bone_looper(ob, bone->next, data, bone_func); - } + /* try to execute bone_func for the next bone at this + * depth of the recursion. + */ + count += bone_looper(ob, bone->next, data, bone_func); + } - return count; + return count; } /* *************************************************************** */ @@ -117,25 +116,25 @@ int bone_looper(Object *ob, Bone *bone, void *data, void bone_free(bArmature *arm, EditBone *bone) { - if (arm->act_edbone == bone) - arm->act_edbone = NULL; + if (arm->act_edbone == bone) + arm->act_edbone = NULL; - if (bone->prop) { - IDP_FreeProperty(bone->prop); - MEM_freeN(bone->prop); - } + if (bone->prop) { + IDP_FreeProperty(bone->prop); + MEM_freeN(bone->prop); + } - /* Clear references from other edit bones. */ - for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (ebone->bbone_next == bone) { - ebone->bbone_next = NULL; - } - if (ebone->bbone_prev == bone) { - ebone->bbone_prev = NULL; - } - } + /* Clear references from other edit bones. */ + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (ebone->bbone_next == bone) { + ebone->bbone_next = NULL; + } + if (ebone->bbone_prev == bone) { + ebone->bbone_prev = NULL; + } + } - BLI_freelinkN(arm->edbo, bone); + BLI_freelinkN(arm->edbo, bone); } /** @@ -143,33 +142,33 @@ void bone_free(bArmature *arm, EditBone *bone) */ void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected) { - EditBone *curBone; + EditBone *curBone; - /* Find any bones that refer to this bone */ - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (curBone->parent == exBone) { - curBone->parent = exBone->parent; - if (clear_connected) { - curBone->flag &= ~BONE_CONNECTED; - } - } - } + /* Find any bones that refer to this bone */ + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + if (curBone->parent == exBone) { + curBone->parent = exBone->parent; + if (clear_connected) { + curBone->flag &= ~BONE_CONNECTED; + } + } + } - bone_free(arm, exBone); + bone_free(arm, exBone); } void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone) { - ED_armature_ebone_remove_ex(arm, exBone, true); + ED_armature_ebone_remove_ex(arm, exBone, true); } bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child) { - for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) { - if (ebone_child == ebone_parent) - return true; - } - return false; + for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) { + if (ebone_child == ebone_parent) + return true; + } + return false; } /** @@ -179,81 +178,82 @@ bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebon * \param ebone_child_tot: Size of the ebone_child array * \return The shared parent or NULL. */ -EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const unsigned int ebone_child_tot) +EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], + const unsigned int ebone_child_tot) { - unsigned int i; - EditBone *ebone_iter; + unsigned int i; + EditBone *ebone_iter; #define EBONE_TEMP_UINT(ebone) (*((unsigned int *)(&((ebone)->temp)))) - /* clear all */ - for (i = 0; i < ebone_child_tot; i++) { - for (ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) { - EBONE_TEMP_UINT(ebone_iter) = 0; - } - } - - /* accumulate */ - for (i = 0; i < ebone_child_tot; i++) { - for (ebone_iter = ebone_child[i]->parent; ebone_iter; ebone_iter = ebone_iter->parent) { - EBONE_TEMP_UINT(ebone_iter) += 1; - } - } - - /* only need search the first chain */ - for (ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent) { - if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) { - return ebone_iter; - } - } + /* clear all */ + for (i = 0; i < ebone_child_tot; i++) { + for (ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) { + EBONE_TEMP_UINT(ebone_iter) = 0; + } + } + + /* accumulate */ + for (i = 0; i < ebone_child_tot; i++) { + for (ebone_iter = ebone_child[i]->parent; ebone_iter; ebone_iter = ebone_iter->parent) { + EBONE_TEMP_UINT(ebone_iter) += 1; + } + } + + /* only need search the first chain */ + for (ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent) { + if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) { + return ebone_iter; + } + } #undef EBONE_TEMP_UINT - return NULL; + return NULL; } void ED_armature_ebone_to_mat3(EditBone *ebone, float mat[3][3]) { - float delta[3]; + float delta[3]; - /* Find the current bone matrix */ - sub_v3_v3v3(delta, ebone->tail, ebone->head); - vec_roll_to_mat3(delta, ebone->roll, mat); + /* Find the current bone matrix */ + sub_v3_v3v3(delta, ebone->tail, ebone->head); + vec_roll_to_mat3(delta, ebone->roll, mat); } void ED_armature_ebone_to_mat4(EditBone *ebone, float mat[4][4]) { - float m3[3][3]; + float m3[3][3]; - ED_armature_ebone_to_mat3(ebone, m3); + ED_armature_ebone_to_mat3(ebone, m3); - copy_m4_m3(mat, m3); - copy_v3_v3(mat[3], ebone->head); + copy_m4_m3(mat, m3); + copy_v3_v3(mat[3], ebone->head); } void ED_armature_ebone_from_mat3(EditBone *ebone, float mat[3][3]) { - float vec[3], roll; - const float len = len_v3v3(ebone->head, ebone->tail); + float vec[3], roll; + const float len = len_v3v3(ebone->head, ebone->tail); - mat3_to_vec_roll(mat, vec, &roll); + mat3_to_vec_roll(mat, vec, &roll); - madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len); - ebone->roll = roll; + madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len); + ebone->roll = roll; } void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]) { - float mat3[3][3]; + float mat3[3][3]; - copy_m3_m4(mat3, mat); - /* We want normalized matrix here, to be consistent with ebone_to_mat. */ - BLI_ASSERT_UNIT_M3(mat3); + copy_m3_m4(mat3, mat); + /* We want normalized matrix here, to be consistent with ebone_to_mat. */ + BLI_ASSERT_UNIT_M3(mat3); - sub_v3_v3(ebone->tail, ebone->head); - copy_v3_v3(ebone->head, mat[3]); - add_v3_v3(ebone->tail, mat[3]); - ED_armature_ebone_from_mat3(ebone, mat3); + sub_v3_v3(ebone->tail, ebone->head); + copy_v3_v3(ebone->head, mat[3]); + add_v3_v3(ebone->tail, mat[3]); + ED_armature_ebone_from_mat3(ebone, mat3); } /** @@ -261,10 +261,9 @@ void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]) */ EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name) { - return BLI_findstring(edbo, name, offsetof(EditBone, name)); + return BLI_findstring(edbo, name, offsetof(EditBone, name)); } - /* *************************************************************** */ /* Mirroring */ @@ -273,18 +272,18 @@ EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name) */ EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo) { - char name_flip[MAXBONENAME]; + char name_flip[MAXBONENAME]; - if (ebo == NULL) - return NULL; + if (ebo == NULL) + return NULL; - BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip)); + BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip)); - if (!STREQ(name_flip, ebo->name)) { - return ED_armature_ebone_find_name(edbo, name_flip); - } + if (!STREQ(name_flip, ebo->name)) { + return ED_armature_ebone_find_name(edbo, name_flip); + } - return NULL; + return NULL; } /* ------------------------------------- */ @@ -293,70 +292,69 @@ EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo) * it leaves mirrored bones selected then too, which is a good indication of what happened */ void armature_select_mirrored_ex(bArmature *arm, const int flag) { - BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0); - /* Select mirrored bones */ - if (arm->flag & ARM_MIRROR_EDIT) { - EditBone *curBone, *ebone_mirr; - - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (arm->layer & curBone->layer) { - if (curBone->flag & flag) { - ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); - if (ebone_mirr) - ebone_mirr->flag |= (curBone->flag & flag); - } - } - } - } + BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0); + /* Select mirrored bones */ + if (arm->flag & ARM_MIRROR_EDIT) { + EditBone *curBone, *ebone_mirr; + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + if (arm->layer & curBone->layer) { + if (curBone->flag & flag) { + ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); + if (ebone_mirr) + ebone_mirr->flag |= (curBone->flag & flag); + } + } + } + } } void armature_select_mirrored(bArmature *arm) { - armature_select_mirrored_ex(arm, BONE_SELECTED); + armature_select_mirrored_ex(arm, BONE_SELECTED); } void armature_tag_select_mirrored(bArmature *arm) { - EditBone *curBone; - - /* always untag */ - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - curBone->flag &= ~BONE_DONE; - } - - /* Select mirrored bones */ - if (arm->flag & ARM_MIRROR_EDIT) { - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (arm->layer & curBone->layer) { - if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) { - EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); - if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) { - ebone_mirr->flag |= BONE_DONE; - } - } - } - } - - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (curBone->flag & BONE_DONE) { - EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); - curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); - } - } - } + EditBone *curBone; + + /* always untag */ + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + curBone->flag &= ~BONE_DONE; + } + + /* Select mirrored bones */ + if (arm->flag & ARM_MIRROR_EDIT) { + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + if (arm->layer & curBone->layer) { + if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) { + EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); + if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) { + ebone_mirr->flag |= BONE_DONE; + } + } + } + } + + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + if (curBone->flag & BONE_DONE) { + EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone); + curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); + } + } + } } /* only works when tagged */ void armature_tag_unselect(bArmature *arm) { - EditBone *curBone; + EditBone *curBone; - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (curBone->flag & BONE_DONE) { - curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE); - } - } + for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { + if (curBone->flag & BONE_DONE) { + curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE); + } + } } /* ------------------------------------- */ @@ -365,186 +363,189 @@ void armature_tag_unselect(bArmature *arm) /* context; editmode armature, with mirror editing enabled */ void ED_armature_edit_transform_mirror_update(Object *obedit) { - bArmature *arm = obedit->data; - EditBone *ebo, *eboflip; - - for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { - /* no layer check, correct mirror is more important */ - if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) { - eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo); - - if (eboflip) { - /* we assume X-axis flipping for now */ - if (ebo->flag & BONE_TIPSEL) { - EditBone *children; - - eboflip->tail[0] = -ebo->tail[0]; - eboflip->tail[1] = ebo->tail[1]; - eboflip->tail[2] = ebo->tail[2]; - eboflip->rad_tail = ebo->rad_tail; - eboflip->roll = -ebo->roll; - eboflip->curveOutX = -ebo->curveOutX; - eboflip->roll2 = -ebo->roll2; - - /* Also move connected children, in case children's name aren't mirrored properly */ - for (children = arm->edbo->first; children; children = children->next) { - if (children->parent == eboflip && children->flag & BONE_CONNECTED) { - copy_v3_v3(children->head, eboflip->tail); - children->rad_head = ebo->rad_tail; - } - } - } - if (ebo->flag & BONE_ROOTSEL) { - eboflip->head[0] = -ebo->head[0]; - eboflip->head[1] = ebo->head[1]; - eboflip->head[2] = ebo->head[2]; - eboflip->rad_head = ebo->rad_head; - eboflip->roll = -ebo->roll; - eboflip->curveInX = -ebo->curveInX; - eboflip->roll1 = -ebo->roll1; - - /* Also move connected parent, in case parent's name isn't mirrored properly */ - if (eboflip->parent && eboflip->flag & BONE_CONNECTED) { - EditBone *parent = eboflip->parent; - copy_v3_v3(parent->tail, eboflip->head); - parent->rad_tail = ebo->rad_head; - } - } - if (ebo->flag & BONE_SELECTED) { - eboflip->dist = ebo->dist; - eboflip->roll = -ebo->roll; - eboflip->xwidth = ebo->xwidth; - eboflip->zwidth = ebo->zwidth; - - eboflip->curveInX = -ebo->curveInX; - eboflip->curveOutX = -ebo->curveOutX; - eboflip->roll1 = -ebo->roll1; - eboflip->roll2 = -ebo->roll2; - } - } - } - } + bArmature *arm = obedit->data; + EditBone *ebo, *eboflip; + + for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { + /* no layer check, correct mirror is more important */ + if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) { + eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo); + + if (eboflip) { + /* we assume X-axis flipping for now */ + if (ebo->flag & BONE_TIPSEL) { + EditBone *children; + + eboflip->tail[0] = -ebo->tail[0]; + eboflip->tail[1] = ebo->tail[1]; + eboflip->tail[2] = ebo->tail[2]; + eboflip->rad_tail = ebo->rad_tail; + eboflip->roll = -ebo->roll; + eboflip->curveOutX = -ebo->curveOutX; + eboflip->roll2 = -ebo->roll2; + + /* Also move connected children, in case children's name aren't mirrored properly */ + for (children = arm->edbo->first; children; children = children->next) { + if (children->parent == eboflip && children->flag & BONE_CONNECTED) { + copy_v3_v3(children->head, eboflip->tail); + children->rad_head = ebo->rad_tail; + } + } + } + if (ebo->flag & BONE_ROOTSEL) { + eboflip->head[0] = -ebo->head[0]; + eboflip->head[1] = ebo->head[1]; + eboflip->head[2] = ebo->head[2]; + eboflip->rad_head = ebo->rad_head; + eboflip->roll = -ebo->roll; + eboflip->curveInX = -ebo->curveInX; + eboflip->roll1 = -ebo->roll1; + + /* Also move connected parent, in case parent's name isn't mirrored properly */ + if (eboflip->parent && eboflip->flag & BONE_CONNECTED) { + EditBone *parent = eboflip->parent; + copy_v3_v3(parent->tail, eboflip->head); + parent->rad_tail = ebo->rad_head; + } + } + if (ebo->flag & BONE_SELECTED) { + eboflip->dist = ebo->dist; + eboflip->roll = -ebo->roll; + eboflip->xwidth = ebo->xwidth; + eboflip->zwidth = ebo->zwidth; + + eboflip->curveInX = -ebo->curveInX; + eboflip->curveOutX = -ebo->curveOutX; + eboflip->roll1 = -ebo->roll1; + eboflip->roll2 = -ebo->roll2; + } + } + } + } } /* *************************************************************** */ /* Armature EditMode Conversions */ /* converts Bones to EditBone list, used for tools as well */ -static EditBone *make_boneList_rec(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone) -{ - EditBone *eBone; - EditBone *eBoneAct = NULL; - EditBone *eBoneTest = NULL; - Bone *curBone; - - for (curBone = bones->first; curBone; curBone = curBone->next) { - eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); - eBone->temp.bone = curBone; - - /* Copy relevant data from bone to eBone - * Keep selection logic in sync with ED_armature_edit_sync_selection. - */ - eBone->parent = parent; - BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); - eBone->flag = curBone->flag; - - /* fix selection flags */ - if (eBone->flag & BONE_SELECTED) { - /* if the bone is selected the copy its root selection to the parents tip */ - eBone->flag |= BONE_TIPSEL; - if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { - eBone->parent->flag |= BONE_TIPSEL; - } - - /* For connected bones, take care when changing the selection when we have a connected parent, - * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */ - eBone->flag |= BONE_ROOTSEL; - } - else { - /* if the bone is not selected, but connected to its parent - * always use the parents tip selection state */ - if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { - eBone->flag &= ~BONE_ROOTSEL; - } - } - - copy_v3_v3(eBone->head, curBone->arm_head); - copy_v3_v3(eBone->tail, curBone->arm_tail); - eBone->roll = curBone->arm_roll; - - /* rest of stuff copy */ - eBone->length = curBone->length; - eBone->dist = curBone->dist; - eBone->weight = curBone->weight; - eBone->xwidth = curBone->xwidth; - eBone->zwidth = curBone->zwidth; - eBone->rad_head = curBone->rad_head; - eBone->rad_tail = curBone->rad_tail; - eBone->segments = curBone->segments; - eBone->layer = curBone->layer; - - /* Bendy-Bone parameters */ - eBone->roll1 = curBone->roll1; - eBone->roll2 = curBone->roll2; - eBone->curveInX = curBone->curveInX; - eBone->curveInY = curBone->curveInY; - eBone->curveOutX = curBone->curveOutX; - eBone->curveOutY = curBone->curveOutY; - eBone->ease1 = curBone->ease1; - eBone->ease2 = curBone->ease2; - eBone->scaleIn = curBone->scaleIn; - eBone->scaleOut = curBone->scaleOut; - - eBone->bbone_prev_type = curBone->bbone_prev_type; - eBone->bbone_next_type = curBone->bbone_next_type; - - if (curBone->prop) - eBone->prop = IDP_CopyProperty(curBone->prop); - - BLI_addtail(edbo, eBone); - - /* Add children if necessary */ - if (curBone->childbase.first) { - eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone); - if (eBoneTest) - eBoneAct = eBoneTest; - } - - if (curBone == actBone) - eBoneAct = eBone; - } - - return eBoneAct; +static EditBone *make_boneList_rec(ListBase *edbo, + ListBase *bones, + EditBone *parent, + Bone *actBone) +{ + EditBone *eBone; + EditBone *eBoneAct = NULL; + EditBone *eBoneTest = NULL; + Bone *curBone; + + for (curBone = bones->first; curBone; curBone = curBone->next) { + eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); + eBone->temp.bone = curBone; + + /* Copy relevant data from bone to eBone + * Keep selection logic in sync with ED_armature_edit_sync_selection. + */ + eBone->parent = parent; + BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); + eBone->flag = curBone->flag; + + /* fix selection flags */ + if (eBone->flag & BONE_SELECTED) { + /* if the bone is selected the copy its root selection to the parents tip */ + eBone->flag |= BONE_TIPSEL; + if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { + eBone->parent->flag |= BONE_TIPSEL; + } + + /* For connected bones, take care when changing the selection when we have a connected parent, + * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */ + eBone->flag |= BONE_ROOTSEL; + } + else { + /* if the bone is not selected, but connected to its parent + * always use the parents tip selection state */ + if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { + eBone->flag &= ~BONE_ROOTSEL; + } + } + + copy_v3_v3(eBone->head, curBone->arm_head); + copy_v3_v3(eBone->tail, curBone->arm_tail); + eBone->roll = curBone->arm_roll; + + /* rest of stuff copy */ + eBone->length = curBone->length; + eBone->dist = curBone->dist; + eBone->weight = curBone->weight; + eBone->xwidth = curBone->xwidth; + eBone->zwidth = curBone->zwidth; + eBone->rad_head = curBone->rad_head; + eBone->rad_tail = curBone->rad_tail; + eBone->segments = curBone->segments; + eBone->layer = curBone->layer; + + /* Bendy-Bone parameters */ + eBone->roll1 = curBone->roll1; + eBone->roll2 = curBone->roll2; + eBone->curveInX = curBone->curveInX; + eBone->curveInY = curBone->curveInY; + eBone->curveOutX = curBone->curveOutX; + eBone->curveOutY = curBone->curveOutY; + eBone->ease1 = curBone->ease1; + eBone->ease2 = curBone->ease2; + eBone->scaleIn = curBone->scaleIn; + eBone->scaleOut = curBone->scaleOut; + + eBone->bbone_prev_type = curBone->bbone_prev_type; + eBone->bbone_next_type = curBone->bbone_next_type; + + if (curBone->prop) + eBone->prop = IDP_CopyProperty(curBone->prop); + + BLI_addtail(edbo, eBone); + + /* Add children if necessary */ + if (curBone->childbase.first) { + eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone); + if (eBoneTest) + eBoneAct = eBoneTest; + } + + if (curBone == actBone) + eBoneAct = eBone; + } + + return eBoneAct; } static EditBone *find_ebone_link(ListBase *edbo, Bone *link) { - if (link != NULL) { - for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) { - if (ebone->temp.bone == link) { - return ebone; - } - } - } + if (link != NULL) { + for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) { + if (ebone->temp.bone == link) { + return ebone; + } + } + } - return NULL; + return NULL; } EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone) { - BLI_assert(!edbo->first && !edbo->last); + BLI_assert(!edbo->first && !edbo->last); - EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone); + EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone); - for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) { - Bone *bone = ebone->temp.bone; + for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) { + Bone *bone = ebone->temp.bone; - /* Convert custom B-Bone handle links. */ - ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev); - ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next); - } + /* Convert custom B-Bone handle links. */ + ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev); + ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next); + } - return active; + return active; } /** @@ -559,217 +560,217 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone) */ static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist) { - Bone *curBone; - EditBone *ebone; + Bone *curBone; + EditBone *ebone; - for (curBone = bonelist->first; curBone; curBone = curBone->next) { - /* Set bone's local head/tail. - * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values - * from editbone's matrix (see T46010). */ - if (curBone->parent) { - float parmat_inv[4][4]; + for (curBone = bonelist->first; curBone; curBone = curBone->next) { + /* Set bone's local head/tail. + * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values + * from editbone's matrix (see T46010). */ + if (curBone->parent) { + float parmat_inv[4][4]; - invert_m4_m4(parmat_inv, curBone->parent->arm_mat); + invert_m4_m4(parmat_inv, curBone->parent->arm_mat); - /* Get the new head and tail */ - sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail); - sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail); + /* Get the new head and tail */ + sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail); + sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail); - mul_mat3_m4_v3(parmat_inv, curBone->head); - mul_mat3_m4_v3(parmat_inv, curBone->tail); - } - else { - copy_v3_v3(curBone->head, curBone->arm_head); - copy_v3_v3(curBone->tail, curBone->arm_tail); - } + mul_mat3_m4_v3(parmat_inv, curBone->head); + mul_mat3_m4_v3(parmat_inv, curBone->tail); + } + else { + copy_v3_v3(curBone->head, curBone->arm_head); + copy_v3_v3(curBone->tail, curBone->arm_tail); + } - /* Set local matrix and arm_mat (restpose). - * Do not recurse into children here, armature_finalize_restpose() is already recursive. */ - BKE_armature_where_is_bone(curBone, curBone->parent, false); + /* Set local matrix and arm_mat (restpose). + * Do not recurse into children here, armature_finalize_restpose() is already recursive. */ + BKE_armature_where_is_bone(curBone, curBone->parent, false); - /* Find the associated editbone */ - for (ebone = editbonelist->first; ebone; ebone = ebone->next) { - if (ebone->temp.bone == curBone) { - float premat[3][3]; - float postmat[3][3]; - float difmat[3][3]; - float imat[3][3]; + /* Find the associated editbone */ + for (ebone = editbonelist->first; ebone; ebone = ebone->next) { + if (ebone->temp.bone == curBone) { + float premat[3][3]; + float postmat[3][3]; + float difmat[3][3]; + float imat[3][3]; - /* Get the ebone premat and its inverse. */ - ED_armature_ebone_to_mat3(ebone, premat); - invert_m3_m3(imat, premat); + /* Get the ebone premat and its inverse. */ + ED_armature_ebone_to_mat3(ebone, premat); + invert_m3_m3(imat, premat); - /* Get the bone postmat. */ - copy_m3_m4(postmat, curBone->arm_mat); + /* Get the bone postmat. */ + copy_m3_m4(postmat, curBone->arm_mat); - mul_m3_m3m3(difmat, imat, postmat); + mul_m3_m3m3(difmat, imat, postmat); #if 0 - printf("Bone %s\n", curBone->name); - print_m4("premat", premat); - print_m4("postmat", postmat); - print_m4("difmat", difmat); - printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2]))); + printf("Bone %s\n", curBone->name); + print_m4("premat", premat); + print_m4("postmat", postmat); + print_m4("difmat", difmat); + printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2]))); #endif - curBone->roll = -atan2f(difmat[2][0], difmat[2][2]); + curBone->roll = -atan2f(difmat[2][0], difmat[2][2]); - /* and set restposition again */ - BKE_armature_where_is_bone(curBone, curBone->parent, false); - break; - } - } + /* and set restposition again */ + BKE_armature_where_is_bone(curBone, curBone->parent, false); + break; + } + } - /* Recurse into children... */ - armature_finalize_restpose(&curBone->childbase, editbonelist); - } + /* Recurse into children... */ + armature_finalize_restpose(&curBone->childbase, editbonelist); + } } /* put EditMode back in Object */ void ED_armature_from_edit(Main *bmain, 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 */ - - /* important, editbones can be active with only 1 point selected */ - /* newBone->flag |= BONE_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; - - newBone->bbone_prev_type = eBone->bbone_prev_type; - newBone->bbone_next_type = eBone->bbone_next_type; - - 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); - } - - /* Also transfer B-Bone custom handles. */ - if (eBone->bbone_prev) { - newBone->bbone_prev = eBone->bbone_prev->temp.bone; - } - if (eBone->bbone_next) { - newBone->bbone_next = eBone->bbone_next->temp.bone; - } - } - - /* 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 = bmain->objects.first; obt; obt = obt->id.next) { - if (obt->data == arm) { - BKE_pose_rebuild(bmain, obt, arm, true); - } - } - - DEG_id_tag_update(&arm->id, 0); + 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 */ + + /* important, editbones can be active with only 1 point selected */ + /* newBone->flag |= BONE_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; + + newBone->bbone_prev_type = eBone->bbone_prev_type; + newBone->bbone_next_type = eBone->bbone_next_type; + + 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); + } + + /* Also transfer B-Bone custom handles. */ + if (eBone->bbone_prev) { + newBone->bbone_prev = eBone->bbone_prev->temp.bone; + } + if (eBone->bbone_next) { + newBone->bbone_next = eBone->bbone_next->temp.bone; + } + } + + /* 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 = bmain->objects.first; obt; obt = obt->id.next) { + if (obt->data == arm) { + BKE_pose_rebuild(bmain, obt, arm, true); + } + } + + DEG_id_tag_update(&arm->id, 0); } void ED_armature_edit_free(struct bArmature *arm) { - EditBone *eBone; + EditBone *eBone; - /* Clear the editbones list */ - if (arm->edbo) { - if (arm->edbo->first) { - for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { - if (eBone->prop) { - IDP_FreeProperty(eBone->prop); - MEM_freeN(eBone->prop); - } - } + /* Clear the editbones list */ + if (arm->edbo) { + if (arm->edbo->first) { + for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { + if (eBone->prop) { + IDP_FreeProperty(eBone->prop); + MEM_freeN(eBone->prop); + } + } - BLI_freelistN(arm->edbo); - } - MEM_freeN(arm->edbo); - arm->edbo = NULL; - arm->act_edbone = NULL; - } + BLI_freelistN(arm->edbo); + } + MEM_freeN(arm->edbo); + arm->edbo = NULL; + arm->act_edbone = NULL; + } } /* Put armature in EditMode */ void ED_armature_to_edit(bArmature *arm) { - ED_armature_edit_free(arm); - arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); - arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone); + ED_armature_edit_free(arm); + arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); + arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone); } /* *************************************************************** */ @@ -779,59 +780,59 @@ void ED_armature_to_edit(bArmature *arm) void ED_armature_ebone_listbase_free(ListBase *lb) { - EditBone *ebone, *ebone_next; + EditBone *ebone, *ebone_next; - for (ebone = lb->first; ebone; ebone = ebone_next) { - ebone_next = ebone->next; + for (ebone = lb->first; ebone; ebone = ebone_next) { + ebone_next = ebone->next; - if (ebone->prop) { - IDP_FreeProperty(ebone->prop); - MEM_freeN(ebone->prop); - } + if (ebone->prop) { + IDP_FreeProperty(ebone->prop); + MEM_freeN(ebone->prop); + } - MEM_freeN(ebone); - } + MEM_freeN(ebone); + } - BLI_listbase_clear(lb); + BLI_listbase_clear(lb); } void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src) { - EditBone *ebone_src; - EditBone *ebone_dst; - - BLI_assert(BLI_listbase_is_empty(lb_dst)); - - for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) { - ebone_dst = MEM_dupallocN(ebone_src); - if (ebone_dst->prop) { - ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop); - } - ebone_src->temp.ebone = ebone_dst; - BLI_addtail(lb_dst, ebone_dst); - } - - /* set pointers */ - for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) { - if (ebone_dst->parent) { - ebone_dst->parent = ebone_dst->parent->temp.ebone; - } - if (ebone_dst->bbone_next) { - ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone; - } - if (ebone_dst->bbone_prev) { - ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone; - } - } + EditBone *ebone_src; + EditBone *ebone_dst; + + BLI_assert(BLI_listbase_is_empty(lb_dst)); + + for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) { + ebone_dst = MEM_dupallocN(ebone_src); + if (ebone_dst->prop) { + ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop); + } + ebone_src->temp.ebone = ebone_dst; + BLI_addtail(lb_dst, ebone_dst); + } + + /* set pointers */ + for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) { + if (ebone_dst->parent) { + ebone_dst->parent = ebone_dst->parent->temp.ebone; + } + if (ebone_dst->bbone_next) { + ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone; + } + if (ebone_dst->bbone_prev) { + ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone; + } + } } void ED_armature_ebone_listbase_temp_clear(ListBase *lb) { - EditBone *ebone; - /* be sure they don't hang ever */ - for (ebone = lb->first; ebone; ebone = ebone->next) { - ebone->temp.p = NULL; - } + EditBone *ebone; + /* be sure they don't hang ever */ + for (ebone = lb->first; ebone; ebone = ebone->next) { + ebone->temp.p = NULL; + } } /* *************************************************************** */ @@ -841,54 +842,54 @@ void ED_armature_ebone_listbase_temp_clear(ListBase *lb) int ED_armature_ebone_selectflag_get(const EditBone *ebone) { - if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { - return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) | - ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0)); - } - else { - return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)); - } + if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { + return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) | + ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0)); + } + else { + return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)); + } } void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag) { - flag = flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); + flag = flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); - if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { - ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); - ebone->parent->flag &= ~BONE_TIPSEL; + if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { + ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); + ebone->parent->flag &= ~BONE_TIPSEL; - ebone->flag |= flag; - ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0; - } - else { - ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); - ebone->flag |= flag; - } + ebone->flag |= flag; + ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0; + } + else { + ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); + ebone->flag |= flag; + } } void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag) { - BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0); - ED_armature_ebone_selectflag_set(ebone, ebone->flag | flag); + BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0); + ED_armature_ebone_selectflag_set(ebone, ebone->flag | flag); } void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag) { - BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0); - ED_armature_ebone_selectflag_set(ebone, ebone->flag & ~flag); + BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0); + ED_armature_ebone_selectflag_set(ebone, ebone->flag & ~flag); } /* could be used in more places */ void ED_armature_ebone_select_set(EditBone *ebone, bool select) { - int flag; - if (select) { - BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0); - flag = (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - flag = 0; - } - ED_armature_ebone_selectflag_set(ebone, flag); + int flag; + if (select) { + BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0); + flag = (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else { + flag = 0; + } + ED_armature_ebone_selectflag_set(ebone, flag); } |