diff options
23 files changed, 392 insertions, 290 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 2dec76d1b6b..2505a3a70ac 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -471,7 +471,7 @@ bPoseChannel *get_active_posechannel (Object *ob) /* find active */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if ((pchan->bone) && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) + if ((pchan->bone) && (pchan->bone == arm->act_bone) && (pchan->bone->layer & arm->layer)) return pchan; } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f178553d796..b0153a1fca3 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -169,10 +169,13 @@ void make_local_armature(bArmature *arm) } } -static void copy_bonechildren (Bone* newBone, Bone* oldBone) +static void copy_bonechildren (Bone* newBone, Bone* oldBone, Bone* actBone, Bone **newActBone) { Bone *curBone, *newChildBone; + if(oldBone == actBone) + *newActBone= newBone; + /* Copy this bone's list*/ BLI_duplicatelist(&newBone->childbase, &oldBone->childbase); @@ -180,7 +183,7 @@ static void copy_bonechildren (Bone* newBone, Bone* oldBone) newChildBone=newBone->childbase.first; for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){ newChildBone->parent=newBone; - copy_bonechildren(newChildBone,curBone); + copy_bonechildren(newChildBone, curBone, actBone, newActBone); newChildBone=newChildBone->next; } } @@ -189,6 +192,7 @@ bArmature *copy_armature(bArmature *arm) { bArmature *newArm; Bone *oldBone, *newBone; + Bone *newActBone= NULL; newArm= copy_libblock (arm); BLI_duplicatelist(&newArm->bonebase, &arm->bonebase); @@ -197,10 +201,11 @@ bArmature *copy_armature(bArmature *arm) newBone=newArm->bonebase.first; for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){ newBone->parent=NULL; - copy_bonechildren (newBone, oldBone); + copy_bonechildren (newBone, oldBone, arm->act_bone, &newActBone); newBone=newBone->next; }; + newArm->act_bone= newActBone; return newArm; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 00f7cbd9eeb..e1a13b65efa 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2333,7 +2333,7 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose) rebuild= 1; else if(ob->id.lib==NULL && arm->id.lib) { /* local pose selection copied to armature, bit hackish */ - pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); + pchan->bone->flag &= ~BONE_SELECTED; pchan->bone->flag |= pchan->selectflag; } } @@ -2388,6 +2388,9 @@ static void direct_link_armature(FileData *fd, bArmature *arm) direct_link_bones(fd, bone); bone=bone->next; } + + arm->act_bone= newdataadr(fd, arm->act_bone); + arm->act_edbone= NULL; } /* ************ READ CAMERA ***************** */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 8ec12496e59..b2147221f9f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1114,7 +1114,7 @@ static void write_pose(WriteData *wd, bPose *pose) /* prevent crashes with autosave, when a bone duplicated in editmode has not yet been assigned to its posechannel */ if (chan->bone) - chan->selectflag= chan->bone->flag & (BONE_SELECTED|BONE_ACTIVE); /* gets restored on read, for library armatures */ + chan->selectflag= chan->bone->flag & BONE_SELECTED; /* gets restored on read, for library armatures */ writestruct(wd, DATA, "bPoseChannel", 1, chan); } diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index d31a3bda332..012610bfd25 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -136,7 +136,7 @@ struct bArmature; struct EditBone; struct ListBase; -void make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent); +EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent, struct Bone *actBone); struct EditBone *addEditBone(struct bArmature *arm, char *name); void BIF_sk_selectStroke(struct bContext *C, short mval[2], short extend); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index c5b01f1cab0..6dad0b6e90f 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -129,10 +129,30 @@ void ED_armature_sync_selection(ListBase *edbo) } } +void ED_armature_validate_active(struct bArmature *arm) +{ + EditBone *ebone= arm->act_edbone; + + if(ebone) { + if(ebone->flag & BONE_HIDDEN_A || (ebone->flag & BONE_SELECTED)==0) + arm->act_edbone= NULL; + } +} + +void free_edit_bone(bArmature *arm, EditBone *bone) +{ + if(arm->act_edbone==bone) + arm->act_edbone= NULL; + + BLI_freelinkN(arm->edbo, bone); +} + /* converts Bones to EditBone list, used for tools as well */ -void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent) +EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone) { EditBone *eBone; + EditBone *eBoneAct= NULL; + EditBone *eBoneTest= NULL; Bone *curBone; float delta[3]; float premat[3][3]; @@ -194,9 +214,17 @@ void make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent) BLI_addtail(edbo, eBone); /* Add children if necessary */ - if (curBone->childbase.first) - make_boneList(edbo, &curBone->childbase, eBone); + if (curBone->childbase.first) { + eBoneTest= make_boneList(edbo, &curBone->childbase, eBone, actBone); + if(eBoneTest) + eBoneAct= eBoneTest; + } + + if(curBone==actBone) + eBoneAct= eBone; } + + return eBoneAct; } /* nasty stuff for converting roll in editbones into bones */ @@ -270,7 +298,7 @@ void ED_armature_from_edit(Object *obedit) fBone->parent= eBone->parent; } printf("Warning: removed zero sized bone: %s\n", eBone->name); - BLI_freelinkN(arm->edbo, eBone); + free_edit_bone(arm, eBone); } } @@ -283,8 +311,12 @@ void ED_armature_from_edit(Object *obedit) memcpy(newBone->head, eBone->head, sizeof(float)*3); memcpy(newBone->tail, eBone->tail, sizeof(float)*3); newBone->flag= eBone->flag; - if (eBone->flag & BONE_ACTIVE) + + if (eBone == arm->act_edbone) { newBone->flag |= BONE_SELECTED; /* important, editbones can be active with only 1 point selected */ + arm->act_edbone= NULL; + arm->act_bone= newBone; + } newBone->roll = 0.0f; newBone->weight = eBone->weight; @@ -997,7 +1029,7 @@ static void separate_armature_bones (Scene *scene, Object *ob, short sel) free_constraints(&pchan->constraints); /* get rid of unneeded bone */ - BLI_freelinkN(arm->edbo, curbone); + free_edit_bone(arm, curbone); BLI_freelinkN(&ob->pose->chanbase, pchan); } } @@ -1633,19 +1665,20 @@ static EditBone *get_nearest_editbonepoint (ViewContext *vc, short mval[2], List return NULL; } -static void delete_bone(ListBase *edbo, EditBone* exBone) +/* warning, wont clear the active bone */ +static void delete_bone(bArmature *arm, EditBone* exBone) { EditBone *curBone; /* Find any bones that refer to this bone */ - for (curBone=edbo->first;curBone;curBone=curBone->next) { + for (curBone=arm->edbo->first; curBone; curBone=curBone->next) { if (curBone->parent==exBone) { curBone->parent=exBone->parent; curBone->flag &= ~BONE_CONNECTED; } } - - BLI_freelinkN(edbo, exBone); + + free_edit_bone(arm, exBone); } /* context: editmode armature */ @@ -1742,8 +1775,10 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op) for (curBone=arm->edbo->first;curBone;curBone=next) { next=curBone->next; if (arm->layer & curBone->layer) { - if (curBone->flag & BONE_SELECTED) - delete_bone(arm->edbo, curBone); + if (curBone->flag & BONE_SELECTED) { + if(curBone==arm->act_edbone) arm->act_edbone= NULL; + delete_bone(arm, curBone); + } } } @@ -1795,30 +1830,33 @@ void ED_armature_deselectall(Object *obedit, int toggle, int doundo) } else sel= toggle; - /* Set the flags */ - for (eBone=arm->edbo->first;eBone;eBone=eBone->next) { - if (sel==3) { - /* invert selection of bone */ - if ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) { - eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - eBone->flag &= ~BONE_ACTIVE; + if(sel==2) { + arm->act_edbone= NULL; + } else { + /* Set the flags */ + for (eBone=arm->edbo->first;eBone;eBone=eBone->next) { + if (sel==3) { + /* invert selection of bone */ + if ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) { + eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + if(arm->act_edbone==eBone) + arm->act_edbone= NULL; + } } - } - else if (sel==1) { - /* select bone */ - if(arm->layer & eBone->layer && (eBone->flag & BONE_HIDDEN_A)==0) { - eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if(eBone->parent) - eBone->parent->flag |= (BONE_TIPSEL); + else if (sel==1) { + /* select bone */ + if(arm->layer & eBone->layer && (eBone->flag & BONE_HIDDEN_A)==0) { + eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + if(eBone->parent) + eBone->parent->flag |= (BONE_TIPSEL); + } + } + else { + /* deselect bone */ + eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + if(arm->act_edbone==eBone) + arm->act_edbone= NULL; } - } - else if (sel==2) { - /* clear active flag */ - eBone->flag &= ~(BONE_ACTIVE); - } - else { - /* deselect bone */ - eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); } } @@ -1836,7 +1874,7 @@ void mouse_armature(bContext *C, short mval[2], int extend) Object *obedit= CTX_data_edit_object(C); bArmature *arm= obedit->data; ViewContext vc; - EditBone *nearBone = NULL, *ebone; + EditBone *nearBone = NULL; int selmask; view3d_set_viewcontext(C, &vc); @@ -1898,8 +1936,7 @@ void mouse_armature(bContext *C, short mval[2], int extend) if(nearBone) { /* then now check for active status */ - for (ebone=arm->edbo->first;ebone;ebone=ebone->next) ebone->flag &= ~BONE_ACTIVE; - if(nearBone->flag & BONE_SELECTED) nearBone->flag |= BONE_ACTIVE; + if(nearBone->flag & BONE_SELECTED) arm->act_edbone= nearBone; } WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit); @@ -1945,7 +1982,8 @@ void ED_armature_to_edit(Object *ob) ED_armature_edit_free(ob); arm->edbo= MEM_callocN(sizeof(ListBase), "edbo armature"); - make_boneList(arm->edbo, &arm->bonebase,NULL); + arm->act_edbone= make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone); + arm->act_bone= NULL; // BIF_freeTemplates(); /* force template update when entering editmode */ } @@ -2103,68 +2141,84 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot) /* **************** undo for armatures ************** */ -static void undoBones_to_editBones(void *lbuv, void *lbev) +typedef struct UndoArmature { + EditBone *act_edbone; + ListBase lb; +} UndoArmature; + +static void undoBones_to_editBones(void *uarmv, void *armv) { - ListBase *lbu= lbuv; - ListBase *edbo= lbev; + UndoArmature *uarm= uarmv; + bArmature *arm= armv; EditBone *ebo, *newebo; - BLI_freelistN(edbo); + BLI_freelistN(arm->edbo); /* copy */ - for(ebo= lbu->first; ebo; ebo= ebo->next) { + for(ebo= uarm->lb.first; ebo; ebo= ebo->next) { newebo= MEM_dupallocN(ebo); ebo->temp= newebo; - BLI_addtail(edbo, newebo); + BLI_addtail(arm->edbo, newebo); } + /* active bone */ + if(uarm->act_edbone) { + ebo= uarm->act_edbone; + arm->act_edbone= ebo->temp; + } + /* set pointers */ - for(newebo= edbo->first; newebo; newebo= newebo->next) { + for(newebo= arm->edbo->first; newebo; newebo= newebo->next) { if(newebo->parent) newebo->parent= newebo->parent->temp; } /* be sure they dont hang ever */ - for(newebo= edbo->first; newebo; newebo= newebo->next) { + for(newebo= arm->edbo->first; newebo; newebo= newebo->next) { newebo->temp= NULL; } } -static void *editBones_to_undoBones(void *lbev) +static void *editBones_to_undoBones(void *armv) { - ListBase *edbo= lbev; - ListBase *lb; + bArmature *arm= armv; + UndoArmature *uarm; EditBone *ebo, *newebo; - lb= MEM_callocN(sizeof(ListBase), "listbase undo"); + uarm= MEM_callocN(sizeof(UndoArmature), "listbase undo"); /* copy */ - for(ebo= edbo->first; ebo; ebo= ebo->next) { + for(ebo= arm->edbo->first; ebo; ebo= ebo->next) { newebo= MEM_dupallocN(ebo); ebo->temp= newebo; - BLI_addtail(lb, newebo); + BLI_addtail(&uarm->lb, newebo); } + /* active bone */ + if(arm->act_edbone) { + ebo= arm->act_edbone; + uarm->act_edbone= ebo->temp; + } + /* set pointers */ - for(newebo= lb->first; newebo; newebo= newebo->next) { + for(newebo= uarm->lb.first; newebo; newebo= newebo->next) { if(newebo->parent) newebo->parent= newebo->parent->temp; } - return lb; + return uarm; } -static void free_undoBones(void *lbv) +static void free_undoBones(void *uarmv) { - ListBase *lb= lbv; + UndoArmature *uarm= uarmv; - BLI_freelistN(lb); - MEM_freeN(lb); + BLI_freelistN(&uarm->lb); + MEM_freeN(uarm); } static void *get_armature_edit(bContext *C) { Object *obedit= CTX_data_edit_object(C); if(obedit && obedit->type==OB_ARMATURE) { - bArmature *arm= obedit->data; - return arm->edbo; + return obedit->data; } return NULL; } @@ -2270,7 +2324,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op) /* find the active or selected bone */ for (ebone = arm->edbo->first; ebone; ebone=ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { - if (ebone->flag & (BONE_ACTIVE|BONE_TIPSEL)) + if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone) break; } } @@ -2278,7 +2332,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op) if (ebone==NULL) { for (ebone = arm->edbo->first; ebone; ebone=ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { - if (ebone->flag & (BONE_ACTIVE|BONE_ROOTSEL)) + if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone) break; } } @@ -2305,7 +2359,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *op) } newbone= add_editbone(obedit, ebone->name); - newbone->flag |= BONE_ACTIVE; + arm->act_edbone= newbone; if (to_root) { VECCOPY(newbone->head, ebone->head); @@ -2635,7 +2689,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) BLI_addtail(arm->edbo, eBone); if (!firstDup) firstDup=eBone; - + /* Lets duplicate the list of constraints that the * current bone has. */ @@ -2719,12 +2773,21 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) } } + /* correct the active bone */ + if(arm->act_edbone) { + eBone= arm->act_edbone; + if(eBone->temp) + arm->act_edbone= eBone->temp; + } + /* Deselect the old bones and select the new ones */ for (curBone=arm->edbo->first; curBone && curBone!=firstDup; curBone=curBone->next) { if (EBONE_VISIBLE(arm, curBone)) - curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); + curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } + ED_armature_validate_active(arm); + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit); return OPERATOR_FINISHED; @@ -3046,13 +3109,13 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone * - tail = head/tail of end (default tail) * - parent = parent of start */ - if ((start->flag & BONE_TIPSEL) && !(start->flag & (BONE_SELECTED|BONE_ACTIVE))) { + if ((start->flag & BONE_TIPSEL) && ((start->flag & BONE_SELECTED) || start==arm->act_edbone)==0) { VECCOPY(head, start->tail); } else { VECCOPY(head, start->head); } - if ((end->flag & BONE_ROOTSEL) && !(end->flag & (BONE_SELECTED|BONE_ACTIVE))) { + if ((end->flag & BONE_ROOTSEL) && ((end->flag & BONE_SELECTED) || end==arm->act_edbone)==0) { VECCOPY(tail, end->head); } else { @@ -3090,7 +3153,7 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone /* step 3: delete all bones between and including start and end */ for (ebo= end; ebo; ebo= ebone) { ebone= (ebo == start) ? (NULL) : (ebo->parent); - BLI_freelinkN(arm->edbo, ebo); + free_edit_bone(arm, ebo); } } @@ -3130,7 +3193,7 @@ static int armature_merge_exec (bContext *C, wmOperator *op) /* check if visible + selected */ if ( EBONE_VISIBLE(arm, ebo) && ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) && - (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) ) + ((ebo->flag & BONE_SELECTED) || (ebo==arm->act_edbone)) ) { /* set either end or start (end gets priority, unless it is already set) */ if (bend == NULL) { @@ -3205,17 +3268,20 @@ void hide_selected_armature_bones(Scene *scene) for (ebone = arm->edbo->first; ebone; ebone=ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { - if (ebone->flag & (BONE_SELECTED)) { - ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + if (ebone->flag & BONE_SELECTED) { + ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); ebone->flag |= BONE_HIDDEN_A; } } } + ED_armature_validate_active(arm); ED_armature_sync_selection(arm->edbo); BIF_undo_push("Hide Bones"); } -void hide_unselected_armature_bones(Scene *scene) + +#if 0 // remove this? +static void hide_unselected_armature_bones(Scene *scene) { Object *obedit= scene->obedit; // XXX get from context bArmature *arm= obedit->data; @@ -3226,15 +3292,18 @@ void hide_unselected_armature_bones(Scene *scene) if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL)); else { - ebone->flag &= ~BONE_ACTIVE; ebone->flag |= BONE_HIDDEN_A; } } } + + ED_armature_validate_active(arm); ED_armature_sync_selection(arm->edbo); BIF_undo_push("Hide Unselected Bones"); } +#endif +#if 0 // remove this? void show_all_armature_bones(Scene *scene) { Object *obedit= scene->obedit; // XXX get from context @@ -3249,9 +3318,11 @@ void show_all_armature_bones(Scene *scene) } } } + ED_armature_validate_active(arm); ED_armature_sync_selection(arm->edbo); BIF_undo_push("Reveal Bones"); } +#endif /* previously extrude_armature */ /* context; editmode armature */ @@ -3301,7 +3372,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) forked= 0; // we extrude 2 different bones if (flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED)) /* don't want this bone to be selected... */ - flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); } if ((flipbone==NULL) && (forked)) flipbone= ebone; @@ -3373,14 +3444,17 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) } /* Deselect the old bone */ - ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); } } /* if only one bone, make this one active */ - if (totbone==1 && first) first->flag |= BONE_ACTIVE; + if (totbone==1 && first) arm->act_edbone= first; if (totbone==0) return OPERATOR_CANCELLED; + if(arm->act_edbone && (((EditBone *)arm->act_edbone)->flag & BONE_SELECTED)==0) + arm->act_edbone= NULL; + /* Transform the endpoints */ ED_armature_sync_selection(arm->edbo); @@ -3965,7 +4039,6 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op) if ((ebone->flag & BONE_UNSELECTABLE) == 0) { /* select bone */ ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - ebone->flag &= ~BONE_ACTIVE; } } CTX_DATA_END; @@ -4009,7 +4082,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) } else { /* deselect bone */ - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } } } @@ -4053,17 +4126,17 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) for (curbone= arm->edbo->first; curbone; curbone= curbone->next) { /* only work on bone if it is visible and its selection can change */ if (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_UNSELECTABLE)==0) { - if (curbone->flag & (BONE_ACTIVE)) { + if (curbone == arm->act_edbone) { if (direction == BONE_SELECT_PARENT) { if (curbone->parent == NULL) continue; else pabone = curbone->parent; if (EBONE_VISIBLE(arm, pabone)) { - pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + pabone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + arm->act_edbone= pabone; if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL; if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - curbone->flag &= ~BONE_ACTIVE; break; } @@ -4073,13 +4146,13 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) if (chbone == NULL) continue; if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE)==0) { - chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + chbone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + arm->act_edbone= chbone; if (!add_to_sel) { curbone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL); if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL; } - curbone->flag &= ~BONE_ACTIVE; break; } } @@ -4256,14 +4329,6 @@ void ARMATURE_OT_align(wmOperatorType *ot) /* ***************** Pose tools ********************* */ -/* helper for function below */ -static int clear_active_flag(Object *ob, Bone *bone, void *data) -{ - bone->flag &= ~BONE_ACTIVE; - return 0; -} - - // XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer static int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *)) @@ -4310,7 +4375,8 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */ if (!(extend) || (base != scene->basact)) { ED_pose_deselectall(ob, 0, 0); - nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + arm->act_bone= nearBone; // XXX old cruft! use notifiers instead //select_actionchannel_by_name(ob->action, nearBone->name, 1); @@ -4318,21 +4384,19 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor else { if (nearBone->flag & BONE_SELECTED) { /* if not active, we make it active */ - if((nearBone->flag & BONE_ACTIVE)==0) { - bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag); - nearBone->flag |= BONE_ACTIVE; + if(nearBone != arm->act_bone) { + arm->act_bone= nearBone; } else { - nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); // XXX old cruft! use notifiers instead //select_actionchannel_by_name(ob->action, nearBone->name, 0); } } else { - bone_looper(ob, arm->bonebase.first, NULL, clear_active_flag); - - nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + arm->act_bone= nearBone; // XXX old cruft! use notifiers instead //select_actionchannel_by_name(ob->action, nearBone->name, 1); @@ -4341,7 +4405,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor /* in weightpaint we select the associated vertex group too */ if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) { - if (nearBone->flag & BONE_ACTIVE) { + if (nearBone == arm->act_bone) { ED_vgroup_select_by_name(OBACT, nearBone->name); DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA); } @@ -4387,16 +4451,17 @@ void ED_pose_deselectall (Object *ob, int test, int doundo) if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) { if (test==3) { pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - pchan->bone->flag &= ~BONE_ACTIVE; } else { - if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED; - else pchan->bone->flag &= ~BONE_ACTIVE; } } } + if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0) + arm->act_bone= NULL; + //countall(); // XXX need an equivalent to this... if (doundo) { @@ -4990,7 +5055,6 @@ static int pose_select_inverse_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) { pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - pchan->bone->flag &= ~BONE_ACTIVE; } } CTX_DATA_END; @@ -5026,12 +5090,13 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { /* select pchan only if selectable, but deselect works always */ - if (sel==0) - pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + if (sel==0) { + pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + } else if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) pchan->bone->flag |= BONE_SELECTED; } - CTX_DATA_END; + CTX_DATA_END; WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL); @@ -5062,11 +5127,11 @@ static int pose_select_parent_exec(bContext *C, wmOperator *op) /* Determine if there is an active bone */ pchan=CTX_data_active_pchan(C); if (pchan) { + bArmature *arm= ob->data; parent=pchan->parent; if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) { parent->bone->flag |= BONE_SELECTED; - parent->bone->flag |= BONE_ACTIVE; - pchan->bone->flag &= ~BONE_ACTIVE; + arm->act_bone= parent->bone; } else { return OPERATOR_CANCELLED; @@ -5105,7 +5170,8 @@ static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr) if (arm->layer & bone->layer) { if (bone->flag & BONE_SELECTED) { bone->flag |= BONE_HIDDEN_P; - bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); + if(arm->act_bone==bone) + arm->act_bone= NULL; } } return 0; @@ -5117,9 +5183,10 @@ static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr) if (arm->layer & bone->layer) { // hrm... typo here? - if (~bone->flag & BONE_SELECTED) { + if ((bone->flag & BONE_SELECTED)==0) { bone->flag |= BONE_HIDDEN_P; - bone->flag &= ~BONE_ACTIVE; + if(arm->act_bone==bone) + arm->act_bone= NULL; } } return 0; @@ -5576,7 +5643,8 @@ EditBone * subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode * */ if (parent == root) { - delete_bone(arm->edbo, parent); + if(parent==arm->act_edbone) arm->act_edbone= NULL; + delete_bone(arm, parent); parent = NULL; } diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 4d65059c4c6..824e7be94d9 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -509,7 +509,7 @@ static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string); ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob); - ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); ctrl->link = src_ctrl->link; @@ -554,7 +554,7 @@ static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash * char name[32]; renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string); edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob); - edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); } @@ -1555,7 +1555,7 @@ RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm) else { rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); - make_boneList(rg->editbones, &arm->bonebase, NULL); + make_boneList(rg->editbones, &arm->bonebase, NULL, NULL); rg->flag |= RIG_FREE_BONELIST; } @@ -1607,7 +1607,7 @@ RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm) else { rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); - make_boneList(rg->editbones, &arm->bonebase, NULL); + make_boneList(rg->editbones, &arm->bonebase, NULL, NULL); rg->flag |= RIG_FREE_BONELIST; } @@ -2947,6 +2947,8 @@ void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg) } RIG_freeRigGraph((BGraph*)rigg); + ED_armature_validate_active(armedit); + // XXX // allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index f67c94eebc3..565a4782377 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -382,7 +382,7 @@ static int poselib_add_exec (bContext *C, wmOperator *op) for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { /* check if available */ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { - if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone==arm->act_bone) { /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ cks.pchan= pchan; @@ -762,7 +762,7 @@ static void poselib_apply_pose (tPoseLib_PreviewData *pld) } else if (pchan->bone) { /* only ok if bone is visible and selected */ - if ( (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) && + if ( (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) && (pchan->bone->flag & BONE_HIDDEN_P)==0 && (pchan->bone->layer & arm->layer) ) ok = 1; diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 696fa65b33a..d7741c2a5ef 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -158,12 +158,12 @@ static short pose_has_protected_selected(Object *ob, short only_selected, short if (ob->proxy) { bPoseChannel *pchan; bArmature *arm= ob->data; - + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if (pchan->bone && (pchan->bone->layer & arm->layer)) { if (pchan->bone->layer & arm->layer_protected) { - if (only_selected && (pchan->bone->flag & BONE_ACTIVE)); - else if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) + if (only_selected && (pchan->bone == arm->act_bone)); + else if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) break; } } @@ -531,7 +531,7 @@ void pose_select_constraint_target(Scene *scene) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if (arm->layer & pchan->bone->layer) { - if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) { for (con= pchan->constraints.first; con; con= con->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; @@ -570,7 +570,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *op) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if (arm->layer & pchan->bone->layer) { - if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) { for (con= pchan->constraints.first; con; con= con->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; @@ -635,7 +635,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) curbone= pchan->bone; if ((arm->layer & curbone->layer) && (curbone->flag & BONE_UNSELECTABLE)==0) { - if (curbone->flag & (BONE_ACTIVE)) { + if (curbone == arm->act_bone) { if (direction == BONE_SELECT_PARENT) { if (pchan->parent == NULL) continue; @@ -644,8 +644,8 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_P)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; - curbone->flag &= ~BONE_ACTIVE; - pabone->flag |= (BONE_ACTIVE|BONE_SELECTED); + pabone->flag |= BONE_SELECTED; + arm->act_bone= pabone; found= 1; break; @@ -658,8 +658,8 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_P)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; - curbone->flag &= ~BONE_ACTIVE; - chbone->flag |= (BONE_ACTIVE|BONE_SELECTED); + chbone->flag |= BONE_SELECTED; + arm->act_bone= chbone; found= 1; break; @@ -717,11 +717,7 @@ void pose_copy_menu(Scene *scene) if (ELEM(NULL, ob, ob->pose)) return; if ((ob==obedit) || (ob->mode & OB_MODE_POSE)==0) return; - /* find active */ - for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if (pchan->bone->flag & BONE_ACTIVE) - break; - } + pchan= get_active_posechannel(ob); if (pchan==NULL) return; pchanact= pchan; @@ -1397,7 +1393,7 @@ static int pose_group_unassign_exec (bContext *C, wmOperator *op) /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */ // NOTE: sync this view3d_context() in space_view3d.c if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { - if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) { if (pchan->agrp_index) { pchan->agrp_index= 0; done= 1; @@ -1444,7 +1440,7 @@ static short pose_select_same_group (Object *ob) /* loop in loop... bad and slow! */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if (arm->layer & pchan->bone->layer) { - if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) { /* only if group matches (and is not selected or current bone) */ for (chan= ob->pose->chanbase.first; chan; chan= chan->next) { @@ -1476,7 +1472,7 @@ static short pose_select_same_layer (Object *ob) /* figure out what bones are selected */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if (arm->layer & pchan->bone->layer) { - if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) { layers |= pchan->bone->layer; } } @@ -1637,25 +1633,21 @@ void pose_activate_flipped_bone(Scene *scene) ob= modifiers_isDeformedByArmature(ob); } if(ob && (ob->mode & OB_MODE_POSE)) { - bPoseChannel *pchan, *pchanf; + bPoseChannel *pchanf; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(arm->layer & pchan->bone->layer) { - if(pchan->bone->flag & BONE_ACTIVE) - break; - } - } - if(pchan) { + if(arm->act_bone) { char name[32]; - BLI_strncpy(name, pchan->name, 32); + BLI_strncpy(name, arm->act_bone->name, 32); bone_flip_name(name, 1); // 0 = do not strip off number extensions pchanf= get_pose_channel(ob->pose, name); - if(pchanf && pchanf!=pchan) { - pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); - pchanf->bone->flag |= (BONE_SELECTED|BONE_ACTIVE); - + if(pchanf && pchanf->bone != arm->act_bone) { + arm->act_bone->flag &= ~BONE_SELECTED; + pchanf->bone->flag |= BONE_SELECTED; + + arm->act_bone= pchanf->bone; + /* in weightpaint we select the associated vertex group too */ if(ob->mode & OB_MODE_WEIGHT_PAINT) { ED_vgroup_select_by_name(OBACT, name); diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 5cc35d4ad77..1836729e419 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -113,6 +113,7 @@ struct Bone *get_indexed_bone (struct Object *ob, int index); float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]); EditBone *ED_armature_bone_get_mirrored(struct ListBase *edbo, EditBone *ebo); // XXX this is needed for populating the context iterators void ED_armature_sync_selection(struct ListBase *edbo); +void ED_armature_validate_active(struct bArmature *arm); void add_primitive_bone(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d); EditBone *addEditBone(struct bArmature *arm, char *name); /* used by COLLADA importer */ diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 919cc3f0cfd..c02d86a567e 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -215,7 +215,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) { /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */ if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { - if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) + if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) CTX_data_list_add(result, &obact->id, &RNA_PoseChannel, pchan); } } @@ -224,21 +224,19 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } } else if(CTX_data_equals(member, "active_bone")) { - bArmature *arm= (obedit) ? obedit->data : NULL; - EditBone *ebone; - - if (arm && arm->edbo) { - for (ebone= arm->edbo->first; ebone; ebone= ebone->next) { - if (EBONE_VISIBLE(arm, ebone)) { - if (ebone->flag & BONE_ACTIVE) { - CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, ebone); - - return 1; - } - } + bArmature *arm= (obact) ? obact->data : NULL; + if(arm->edbo) { + if(arm->act_edbone) { + CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone); + return 1; + } + } + else { + if(arm->act_bone) { + CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone); + return 1; } } - } else if(CTX_data_equals(member, "active_pchan")) { bPoseChannel *pchan; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 408f4862b6f..2045397f3c9 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1104,12 +1104,10 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ /* verify if active weight group is also active bone */ par= modifiers_isDeformedByArmature(ob); if(par && (par->mode & OB_MODE_POSE)) { - bPoseChannel *pchan; - for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->bone->flag & BONE_ACTIVE) - break; - if(pchan) - ED_vgroup_select_by_name(ob, pchan->name); + bArmature *arm= ob->data; + + if(arm->act_bone) + ED_vgroup_select_by_name(ob, arm->act_bone->name); } } else { diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 026498f17af..47055851e03 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -243,26 +243,9 @@ static int buttons_context_path_material(ButsContextPath *path) return 0; } -static Bone *find_active_bone(Bone *bone) -{ - Bone *active; - - for(; bone; bone=bone->next) { - if(bone->flag & BONE_ACTIVE) - return bone; - - active= find_active_bone(bone->childbase.first); - if(active) - return active; - } - - return NULL; -} - static int buttons_context_path_bone(ButsContextPath *path) { bArmature *arm; - Bone *bone; EditBone *edbo; /* if we have an armature, get the active bone */ @@ -270,19 +253,16 @@ static int buttons_context_path_bone(ButsContextPath *path) arm= path->ptr[path->len-1].data; if(arm->edbo) { - for(edbo=arm->edbo->first; edbo; edbo=edbo->next) { - if(edbo->flag & BONE_ACTIVE) { - RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]); - path->len++; - return 1; - } + if(arm->act_edbone) { + edbo= arm->act_edbone; + RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]); + path->len++; + return 1; } } else { - bone= find_active_bone(arm->bonebase.first); - - if(bone) { - RNA_pointer_create(&arm->id, &RNA_Bone, bone, &path->ptr[path->len]); + if(arm->act_bone) { + RNA_pointer_create(&arm->id, &RNA_Bone, arm->act_bone, &path->ptr[path->len]); path->len++; return 1; } diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index bc203a9c80b..39eecd7d2de 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -2025,6 +2025,7 @@ static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) { Object *ob= (Object *)tselem->id; + bArmature *arm= ob->data; bPoseChannel *pchan= te->directdata; if(set) { @@ -2033,10 +2034,14 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen if(set==2) ED_pose_deselectall(ob, 2, 0); // 2 = clear active tag else ED_pose_deselectall(ob, 0, 0); // 0 = deselect - if(set==2 && (pchan->bone->flag & BONE_SELECTED)) - pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); - else - pchan->bone->flag |= BONE_SELECTED|BONE_ACTIVE; + if(set==2 && (pchan->bone->flag & BONE_SELECTED)) { + pchan->bone->flag &= ~BONE_SELECTED; + if(arm->act_bone==pchan->bone) + arm->act_bone= NULL; + } else { + pchan->bone->flag |= BONE_SELECTED; + arm->act_bone= pchan->bone; + } WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, ob); @@ -2060,10 +2065,14 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, if(set==2) ED_pose_deselectall(OBACT, 2, 0); // 2 is clear active tag else ED_pose_deselectall(OBACT, 0, 0); - if(set==2 && (bone->flag & BONE_SELECTED)) - bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE); - else - bone->flag |= BONE_SELECTED|BONE_ACTIVE; + if(set==2 && (bone->flag & BONE_SELECTED)) { + bone->flag &= ~BONE_SELECTED; + if(arm->act_bone==bone) + arm->act_bone= NULL; + } else { + bone->flag |= BONE_SELECTED; + arm->act_bone= bone; + } WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, OBACT); } @@ -2086,11 +2095,13 @@ static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, if(set) { if(!(ebone->flag & BONE_HIDDEN_A)) { - + bArmature *arm= scene->obedit->data; if(set==2) ED_armature_deselectall(scene->obedit, 2, 0); // only clear active tag else ED_armature_deselectall(scene->obedit, 0, 0); // deselect - ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE; + ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL; + arm->act_edbone= ebone; + // flush to parent? if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL; diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 656d7061d48..230bacf4f7f 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -166,7 +166,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co if (bcolor) { char cp[3]; - if (boneflag & BONE_ACTIVE) { + if (boneflag & BONE_DRAW_ACTIVE) { VECCOPY(cp, bcolor->active); } else if (boneflag & BONE_SELECTED) { @@ -181,7 +181,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co glColor3ub(cp[0], cp[1], cp[2]); } else { - if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); + if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); else UI_ThemeColor(TH_WIRE); } @@ -225,7 +225,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co if (bcolor) { char cp[3]; - if (boneflag & BONE_ACTIVE) { + if (boneflag & BONE_DRAW_ACTIVE) { VECCOPY(cp, bcolor->active); } else if (boneflag & BONE_SELECTED) { @@ -238,7 +238,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co glColor3ub(cp[0], cp[1], cp[2]); } else { - if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); + if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); else UI_ThemeColor(TH_BONE_SOLID); } @@ -251,7 +251,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co if (bcolor) { char cp[3]; - if (boneflag & BONE_ACTIVE) { + if (boneflag & BONE_DRAW_ACTIVE) { VECCOPY(cp, bcolor->active); cp_shade_color3ub(cp, 10); } @@ -267,7 +267,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co glColor3ub(cp[0], cp[1], cp[2]); } else { - if (boneflag & BONE_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10); + if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10); else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30); else UI_ThemeColorShade(TH_BONE_SOLID, -30); } @@ -1151,7 +1151,7 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign } else if (armflag & ARM_EDITMODE) { if (dt==OB_WIRE) { - if (boneflag & BONE_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); + if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20); else UI_ThemeColor(TH_WIRE); } @@ -1236,7 +1236,7 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned if (dt <= OB_WIRE) { /* colors */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); + if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20); else UI_ThemeColor(TH_WIRE); } @@ -1629,7 +1629,10 @@ static void draw_pose_channels(Scene *scene, View3D *v3d, ARegion *ar, Base *bas flag= bone->flag; if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) ) flag &= ~BONE_CONNECTED; - + + if(bone==arm->act_bone) + flag |= BONE_DRAW_ACTIVE; + /* set color-set to use */ set_pchan_colorset(ob, pchan); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 2edccacff7a..608a22ea529 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -575,22 +575,15 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr) static void v3d_posearmature_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim) { // uiBlock *block= uiLayoutGetBlock(layout); - bArmature *arm; +// bArmature *arm; bPoseChannel *pchan; - Bone *bone= NULL; // TransformProperties *tfp= v3d->properties_storage; PointerRNA pchanptr; uiLayout *col; // uiLayout *row; - arm = ob->data; - if (!arm || !ob->pose) return; + pchan= get_active_posechannel(ob); - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - bone = pchan->bone; - if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer)) - break; - } // row= uiLayoutRow(layout, 0); if (!pchan) { @@ -691,14 +684,9 @@ static void v3d_editarmature_buts(uiLayout *layout, View3D *v3d, Object *ob, flo uiLayout *col; PointerRNA eboneptr; - ebone= arm->edbo->first; + ebone= arm->act_edbone; - for (ebone = arm->edbo->first; ebone; ebone=ebone->next){ - if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer)) - break; - } - - if (!ebone) + if (!ebone || (ebone->layer & arm->layer)==0) return; // row= uiLayoutRow(layout, 0); @@ -821,19 +809,10 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) case B_ARMATUREPANEL3: // rotate button on channel { - bArmature *arm; bPoseChannel *pchan; - Bone *bone; float eul[3]; - arm = ob->data; - if (!arm || !ob->pose) return; - - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - bone = pchan->bone; - if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer)) - break; - } + pchan= get_active_posechannel(ob); if (!pchan) return; /* make a copy to eul[3], to allow TAB on buttons to work */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 247800c3077..2879dc3ed22 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -791,21 +791,17 @@ static void draw_selected_name(Scene *scene, Object *ob, View3D *v3d) /* show name of active bone too (if possible) */ if(arm->edbo) { - EditBone *ebo; - for (ebo=arm->edbo->first; ebo; ebo=ebo->next){ - if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { - name= ebo->name; - break; - } - } + + if(arm->act_edbone) + name= ((EditBone *)arm->act_edbone)->name; + } - else if(ob->pose && (ob->mode & OB_MODE_POSE)) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { - name= pchan->name; - break; - } + else if(ob->mode & OB_MODE_POSE) { + if(arm->act_bone) { + + if(arm->act_bone->layer & arm->layer) + name= arm->act_bone->name; + } } if(name && markern) diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f0425974f29..2505110d766 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -357,7 +357,14 @@ static void do_lasso_select_pose(ViewContext *vc, short mcords[][2], short moves if(lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) { if(select) pchan->bone->flag |= BONE_SELECTED; - else pchan->bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED); + else pchan->bone->flag &= ~BONE_SELECTED; + } + } + + { + bArmature *arm= ob->data; + if((arm->act_bone->flag & BONE_SELECTED)==0) { + arm->act_bone= NULL; } } } @@ -638,9 +645,11 @@ static void do_lasso_select_armature(ViewContext *vc, short mcords[][2], short m /* if one of points selected, we skip the bone itself */ if(didpoint==0 && lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) { if(select) ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED; - else ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + else ebone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); } } + + ED_armature_validate_active(arm); } static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short moves, short select) @@ -1534,8 +1543,12 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) // XXX select_actionchannel_by_name(base->object->action, bone->name, 1); } else { - bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED); + bArmature *arm= base->object->data; + bone->flag &= ~BONE_SELECTED; // XXX select_actionchannel_by_name(base->object->action, bone->name, 0); + if(arm->act_bone==bone) + arm->act_bone= NULL; + } } } @@ -1868,9 +1881,11 @@ static void armature_circle_select(ViewContext *vc, int selecting, short *mval, if (selecting) ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED; else - ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + ebone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); } } + + ED_armature_validate_active(arm); } /** Callbacks for circle selection in Editmode */ diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 0f4848d9120..86e83715da4 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -55,6 +55,7 @@ #include "RNA_access.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_global.h" @@ -185,18 +186,9 @@ void gimbal_axis(Object *ob, float gmat[][3]) { if(ob->mode & OB_MODE_POSE) { - bPoseChannel *pchan= NULL; + bPoseChannel *pchan= get_active_posechannel(ob); - /* use channels to get stats */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if (pchan->bone && pchan->bone->flag & BONE_ACTIVE) { - if(test_rotmode_euler(pchan->rotmode)) { - break; - } - } - } - - if(pchan) { + if(pchan && test_rotmode_euler(pchan->rotmode)) { float mat[3][3], tmat[3][3], obmat[3][3]; EulToGimbalAxis(mat, pchan->eul, pchan->rotmode); diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index d3e611178fe..7dd90a3cf13 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -78,6 +78,9 @@ typedef struct bArmature { ListBase chainbase; ListBase *edbo; /* editbone listbase, we use pointer so we can check state */ + Bone *act_bone; + void *act_edbone; + void *sketch; /* sketch struct for etch-a-ton */ int flag; @@ -154,7 +157,7 @@ typedef enum eBone_Flag { /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ BONE_HIDDEN_P = (1<<6), /* hidden Bones when drawing PoseChannels */ BONE_DONE = (1<<7), /* For detecting cyclic dependancies */ - BONE_ACTIVE = (1<<8), /* active is on mouse clicks only */ + BONE_DRAW_ACTIVE = (1<<8), /* active is on mouse clicks only - deprecated, ONLY USE FOR DRAWING */ BONE_HINGE = (1<<9), /* No parent rotation or scale */ BONE_HIDDEN_A = (1<<10), /* hidden Bones when drawing Armature Editmode */ BONE_MULT_VG_ENV = (1<<11), /* multiplies vgroup with envelope */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 96dde186260..7d88745779d 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -56,6 +56,44 @@ static void rna_Armature_update_data(bContext *C, PointerRNA *ptr) //WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); } + +static void rna_Armature_act_bone_set(PointerRNA *ptr, PointerRNA value) +{ + bArmature *arm= (bArmature*)ptr->data; + + if(value.id.data==NULL && value.data==NULL) { + arm->act_bone= NULL; + } + else { + if(value.id.data != arm) { + /* raise an error! */ + } + else { + arm->act_bone= value.data; + arm->act_bone->flag |= BONE_SELECTED; + } + } +} + +static void rna_Armature_act_edit_bone_set(PointerRNA *ptr, PointerRNA value) +{ + bArmature *arm= (bArmature*)ptr->data; + + if(value.id.data==NULL && value.data==NULL) { + arm->act_edbone= NULL; + } + else { + if(value.id.data != arm) { + /* raise an error! */ + } + else { + arm->act_edbone= value.data; + ((EditBone *)arm->act_edbone)->flag |= BONE_SELECTED; + } + } +} + + static void rna_Armature_redraw_data(bContext *C, PointerRNA *ptr) { ID *id= ptr->id.data; @@ -371,11 +409,6 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_ui_text(prop, "Connected", "When bone has a parent, bone's head is struck to the parent's tail."); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ACTIVE); - RNA_def_property_ui_text(prop, "Active", "Bone was the last bone clicked on (most operations are applied to only this bone)"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - prop= RNA_def_property(srna, "hinge", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_HINGE); RNA_def_property_ui_text(prop, "Inherit Rotation", "Bone doesn't inherit rotation or scale from parent bone."); @@ -593,7 +626,7 @@ static void rna_def_edit_bone(BlenderRNA *brna) static void rna_def_armature(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *prop_act; static EnumPropertyItem prop_drawtype_items[] = { {ARM_OCTA, "OCTAHEDRAL", 0, "Octahedral", "Display bones as octahedral shape (default)."}, @@ -634,11 +667,34 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Bone"); RNA_def_property_ui_text(prop, "Bones", ""); + { /* Collection active property */ + prop_act= RNA_def_property(srna, "bones_active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop_act, "Bone"); + RNA_def_property_pointer_sdna(prop_act, NULL, "act_bone"); + RNA_def_property_flag(prop_act, PROP_EDITABLE); + RNA_def_property_ui_text(prop_act, "Active Bone", "Armatures active bone."); + RNA_def_property_pointer_funcs(prop_act, NULL, "rna_Armature_act_bone_set", NULL); + + /* todo, redraw */ + RNA_def_property_collection_active(prop, prop_act); + } + prop= RNA_def_property(srna, "edit_bones", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "edbo", NULL); RNA_def_property_struct_type(prop, "EditBone"); RNA_def_property_ui_text(prop, "Edit Bones", ""); + { /* Collection active property */ + prop_act= RNA_def_property(srna, "edit_bones_active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop_act, "EditBone"); + RNA_def_property_pointer_sdna(prop_act, NULL, "act_edbone"); + RNA_def_property_flag(prop_act, PROP_EDITABLE); + RNA_def_property_ui_text(prop_act, "Active EditBone", "Armatures active edit bone."); + //RNA_def_property_update(prop_act, 0, "rna_Armature_act_editbone_update"); + RNA_def_property_pointer_funcs(prop_act, NULL, "rna_Armature_act_edit_bone_set", NULL); + RNA_def_property_collection_active(prop, prop_act); + } + /* Enum values */ // prop= RNA_def_property(srna, "rest_position", PROP_BOOLEAN, PROP_NONE); // RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_RESTPOS); diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index 9a9161b080f..71e91735b24 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -180,10 +180,10 @@ int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUT bPoseChannel* channel = self->m_posechannel; int attr_order = attrdef-Attributes; - int ival; - double dval; - char* sval; - KX_GameObject *oval; +// int ival; +// double dval; +// char* sval; +// KX_GameObject *oval; if (!channel) { PyErr_SetString(PyExc_AttributeError, "channel is NULL"); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index db32f18f63b..2b3838d4dfe 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1818,7 +1818,7 @@ bPoseChannel *get_active_posechannel2 (Object *ob) /* find active */ for(pchan= (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) + if(pchan->bone && (pchan->bone == arm->act_bone) && (pchan->bone->layer & arm->layer)) return pchan; } |