diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 36544bcb086..66af2f34f0f 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -119,7 +119,7 @@ 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) + if(ebone->flag & BONE_HIDDEN_A) arm->act_edbone= NULL; } } @@ -1875,8 +1875,7 @@ void ARMATURE_OT_delete(wmOperatorType *ot) /* toggle==0: deselect * toggle==1: swap (based on test) - * toggle==2: only active tag - * toggle==3: swap (no test) + * toggle==2: swap (no test), CURRENTLY UNUSED */ void ED_armature_deselect_all(Object *obedit, int toggle) { @@ -1898,34 +1897,30 @@ void ED_armature_deselect_all(Object *obedit, int toggle) } else sel= toggle; - 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(EBONE_VISIBLE(arm, eBone)) { - eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if(arm->act_edbone==eBone) - arm->act_edbone= NULL; - } - } - else if (sel==1) { - /* select bone */ - if(EBONE_VISIBLE(arm, eBone)) { - 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); + /* Set the flags */ + for (eBone=arm->edbo->first;eBone;eBone=eBone->next) { + if (sel==2) { + /* invert selection of bone */ + if(EBONE_VISIBLE(arm, eBone)) { + eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); if(arm->act_edbone==eBone) arm->act_edbone= NULL; } } + else if (sel==1) { + /* select bone */ + if(EBONE_VISIBLE(arm, eBone)) { + 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; + } } ED_armature_sync_selection(arm->edbo); @@ -1946,6 +1941,17 @@ void ED_armature_deselect_all_visible(Object *obedit) ED_armature_sync_selection(arm->edbo); } +/* accounts for connected parents */ +static int ebone_select_flag(EditBone *ebone) +{ + if(ebone->parent && (ebone->flag & BONE_CONNECTED)) { + return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED|BONE_TIPSEL)); + } + else { + return ebone->flag & (BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + } +} + /* context: editmode armature in view3d */ int mouse_armature(bContext *C, short mval[2], int extend) { @@ -2014,7 +2020,9 @@ int mouse_armature(bContext *C, short mval[2], int extend) if(nearBone) { /* then now check for active status */ - if(nearBone->flag & BONE_SELECTED) arm->act_edbone= nearBone; + if(ebone_select_flag(nearBone)) { + arm->act_edbone= nearBone; + } } WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, vc.obedit); @@ -3098,13 +3106,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) || start==arm->act_edbone)==0) { + if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED)==0) { copy_v3_v3(head, start->tail); } else { copy_v3_v3(head, start->head); } - if ((end->flag & BONE_ROOTSEL) && ((end->flag & BONE_SELECTED) || end==arm->act_edbone)==0) { + if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED)==0) { copy_v3_v3(tail, end->head); } else { @@ -3188,7 +3196,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) || (ebo==arm->act_edbone)) ) + (ebo->flag & BONE_SELECTED) ) { /* set either end or start (end gets priority, unless it is already set) */ if (bend == NULL) { @@ -3518,9 +3526,6 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) 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); @@ -4465,9 +4470,6 @@ void ED_pose_deselectall (Object *ob, int test) } } } - - if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0) - arm->act_bone= NULL; } static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap) @@ -5174,20 +5176,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) int action = RNA_enum_get(op->ptr, "action"); if (action == SEL_TOGGLE) { - bPoseChannel *pchan= CTX_data_active_pose_bone(C); - int num_sel = CTX_DATA_COUNT(C, selected_pose_bones); - - /* cases for deselect: - * 1) there's only one bone selected, and that is the active one - * 2) there's more than one bone selected - */ - if ( ((num_sel == 1) && (pchan) && (pchan->bone->flag & BONE_SELECTED)) || - (num_sel > 1) ) - { - action = SEL_DESELECT; - } - else - action = SEL_SELECT; + action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT; } /* Set the flags */ diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index 5636b67df9a..e143425036e 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -740,7 +740,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 || pchan->bone == arm->act_bone) && + if ( (pchan->bone->flag & BONE_SELECTED) && (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 55d24550167..f1bace1201f 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -164,7 +164,7 @@ void ED_armature_exit_posemode(bContext *C, Base *base) /* if a selected or active bone is protected, throw error (oonly if warn==1) and return 1 */ /* only_selected==1 : the active bone is allowed to be protected */ -static short pose_has_protected_selected(Object *ob, short only_selected, short warn) +static short pose_has_protected_selected(Object *ob, short warn) { /* check protection */ if (ob->proxy) { @@ -174,8 +174,7 @@ static short pose_has_protected_selected(Object *ob, short only_selected, short 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 == arm->act_bone)); - else if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) + if (pchan->bone->flag & BONE_SELECTED) break; } } @@ -363,13 +362,12 @@ void POSE_OT_paths_clear (wmOperatorType *ot) static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); - bArmature *arm= ob->data; bConstraint *con; int found= 0; CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) { - if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone)) { + if (pchan->bone->flag & BONE_SELECTED) { for (con= pchan->constraints.first; con; con= con->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; @@ -527,7 +525,7 @@ static short pose_select_same_group (bContext *C, Object *ob, short extend) CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) { /* keep track of group as group to use later? */ - if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone)) { + if (pchan->bone->flag & BONE_SELECTED) { group_flags[pchan->agrp_index] = 1; tagged= 1; } @@ -574,7 +572,7 @@ static short pose_select_same_layer (bContext *C, Object *ob, short extend) CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) { /* keep track of layers to use later? */ - if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone)) + if (pchan->bone->flag & BONE_SELECTED) layers |= pchan->bone->layer; /* deselect all bones before selecting new ones? */ @@ -681,7 +679,7 @@ void pose_copy_menu(Scene *scene) /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changable, * but for constraints (just add local constraints) */ - if (pose_has_protected_selected(ob, 1, 0)) { + if (pose_has_protected_selected(ob, 0)) { i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */ if (i < 25) nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5"); diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 9803f5716c2..82f5f2597dd 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -253,7 +253,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult for (pchan= obpose->pose->chanbase.first; pchan; pchan= pchan->next) { /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */ if (PBONE_VISIBLE(arm, pchan->bone)) { - if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) + if (pchan->bone->flag & BONE_SELECTED) CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan); } } diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 6583d287cf8..7426fca844e 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -2151,8 +2151,6 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen 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; @@ -2182,8 +2180,6 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, 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; @@ -2204,27 +2200,49 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, /* ebones only draw in editmode armature */ -static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) +static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature *arm, EditBone *ebone, short sel) { - EditBone *ebone= te->directdata; - - if(set) { - if(!(ebone->flag & BONE_HIDDEN_A)) { - bArmature *arm= scene->obedit->data; - if(set==2) ED_armature_deselect_all(scene->obedit, 2); // only clear active tag - else ED_armature_deselect_all(scene->obedit, 0); // deselect - - 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; - - WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, scene->obedit); - } + if(sel) { + 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; } else { - if (ebone->flag & BONE_SELECTED) return 1; + ebone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + // flush to parent? + if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag &= ~BONE_TIPSEL; + } + + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, scene->obedit); +} +static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) +{ + bArmature *arm= scene->obedit->data; + EditBone *ebone= te->directdata; + + if(set==1) { + if(!(ebone->flag & BONE_HIDDEN_A)) { + ED_armature_deselect_all(scene->obedit, 0); // deselect + tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); + return 1; + } + } + else if (set==2) { + if(!(ebone->flag & BONE_HIDDEN_A)) { + if(!(ebone->flag & BONE_SELECTED)) { + tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); + return 1; + } + else { + /* entirely selected, so de-select */ + tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE); + return 0; + } + } + } + else if (ebone->flag & BONE_SELECTED) { + return 1; } return 0; } diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 52a2cd24254..c0db86b46f9 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -150,6 +150,9 @@ static short set_pchan_glColor (short colCode, int boneflag, int constflag) if (boneflag & BONE_DRAW_ACTIVE) { VECCOPY(cp, bcolor->active); + if(!(boneflag & BONE_SELECTED)) { + cp_shade_color3ub(cp, -80); + } } else if (boneflag & BONE_SELECTED) { VECCOPY(cp, bcolor->select); @@ -163,7 +166,8 @@ static short set_pchan_glColor (short colCode, int boneflag, int constflag) glColor3ub(cp[0], cp[1], cp[2]); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); + if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, 40); + else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */ else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); else UI_ThemeColor(TH_WIRE); } @@ -284,6 +288,13 @@ static short set_pchan_glColor (short colCode, int boneflag, int constflag) return 0; } +static void set_ebone_glColor(const unsigned int boneflag) +{ + if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT); + else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, 0.15f); /* unselected active */ + else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20); + else UI_ThemeColor(TH_WIRE); +} /* *************** Armature drawing, helper calls for parts ******************* */ @@ -1153,9 +1164,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_DRAW_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); - else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20); - else UI_ThemeColor(TH_WIRE); + set_ebone_glColor(boneflag); } else UI_ThemeColor(TH_BONE_SOLID); @@ -1238,9 +1247,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_DRAW_ACTIVE) UI_ThemeColor(TH_EDGE_SELECT); - else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20); - else UI_ThemeColor(TH_WIRE); + set_ebone_glColor(boneflag); } else if (armflag & ARM_POSEMODE) { if (constflag) { @@ -1642,7 +1649,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, flag &= ~BONE_CONNECTED; /* set temporary flag for drawing bone as active, but only if selected */ - if ((bone == arm->act_bone) && (bone->flag & BONE_SELECTED)) + if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; /* set color-set to use */ @@ -1728,7 +1735,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, flag &= ~BONE_CONNECTED; /* set temporary flag for drawing bone as active, but only if selected */ - if ((bone == arm->act_bone) && (bone->flag & BONE_SELECTED)) + if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length); @@ -1823,7 +1830,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, flag &= ~BONE_CONNECTED; /* set temporary flag for drawing bone as active, but only if selected */ - if ((bone == arm->act_bone) && (bone->flag & BONE_SELECTED)) + if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; /* extra draw service for pose mode */ @@ -1983,7 +1990,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) flag &= ~BONE_CONNECTED; /* set temporary flag for drawing bone as active, but only if selected */ - if ((eBone == arm->act_edbone) && (eBone->flag & BONE_SELECTED)) + if (eBone == arm->act_edbone) flag |= BONE_DRAW_ACTIVE; if (arm->drawtype==ARM_ENVELOPE) @@ -2022,7 +2029,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) flag &= ~BONE_CONNECTED; /* set temporary flag for drawing bone as active, but only if selected */ - if ((eBone == arm->act_edbone) && (eBone->flag & BONE_SELECTED)) + if (eBone == arm->act_edbone) flag |= BONE_DRAW_ACTIVE; if (arm->drawtype == ARM_ENVELOPE) { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a3289c4cdc0..69096843aa1 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -364,10 +364,6 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, short mcords[][2], } } } - - if(arm->act_bone && (arm->act_bone->flag & BONE_SELECTED)==0) { - arm->act_bone= NULL; - } } static void object_deselect_all_visible(Scene *scene, View3D *v3d) diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index effa5e34a91..f6b61d5f2ba 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -79,6 +79,12 @@ typedef struct bArmature { ListBase chainbase; ListBase *edbo; /* editbone listbase, we use pointer so we can check state */ + /* active bones should work like active object where possible + * - active and selection are unrelated + * - active & hidden is not allowed + * - from the user perspective active == last selected + * - active should be ignored when not visible (hidden layer) */ + Bone *act_bone; /* active bone (when not in editmode) */ void *act_edbone; /* active editbone (in editmode) */