diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-10-06 15:33:58 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-10-06 15:33:58 +0400 |
commit | 22605ec759a564428b82a3de1053c0152e9d9374 (patch) | |
tree | 60626ff89a25a8077cf7e3ed36e0affb7d94b17f /source | |
parent | c12cb02c56ef575720f468ed1de7dc065f153580 (diff) |
Bone Selections: Ability to set bones as unselectable
In the Outliner, it is now possible to toggle per bone the selectability of the bone in the viewport, as for Objects using the restriction columns. This can also be set using the RNA-api.
I've tested all commonly used tools IMO, but there may still be a few which I've missed. Please report those cases.
PS. For some reason, the define was already there, but not connected up to anything. Can't remember why anymore, but here it is...
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 186 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 10 | ||||
-rw-r--r-- | source/blender/editors/object/object_select.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner.c | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_armature.c | 5 |
5 files changed, 123 insertions, 92 deletions
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 402715dbb02..c32837be420 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -110,17 +110,20 @@ void ED_armature_sync_selection(ListBase *edbo) EditBone *ebo; for (ebo=edbo->first; ebo; ebo= ebo->next) { - if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) { - if (ebo->parent->flag & BONE_TIPSEL) - ebo->flag |= BONE_ROOTSEL; + /* 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_ROOTSEL; + ebo->flag &= ~BONE_SELECTED; } - - if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) - ebo->flag |= BONE_SELECTED; - else - ebo->flag &= ~BONE_SELECTED; } } @@ -1127,7 +1130,7 @@ static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int * /* no singular posemode, so check for correct object */ if(base->selcol == (hitresult & 0xFFFF)) { bone = get_indexed_bone(base->object, hitresult); - + if (findunsel) sel = (bone->flag & BONE_SELECTED); else @@ -1347,45 +1350,42 @@ void POSE_OT_flags_set (wmOperatorType *ot) /* **************** Posemode stuff ********************** */ -static void selectconnected_posebonechildren (Object *ob, Bone *bone) +static void selectconnected_posebonechildren (Object *ob, Bone *bone, int extend) { Bone *curBone; - int shift= 0; // XXX - if (!(bone->flag & BONE_CONNECTED)) + /* stop when unconnected child is encontered, or when unselectable bone is encountered */ + if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE)) return; // XXX old cruft! use notifiers instead //select_actionchannel_by_name (ob->action, bone->name, !(shift)); - if (shift) + if (extend) bone->flag &= ~BONE_SELECTED; else bone->flag |= BONE_SELECTED; - for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ - selectconnected_posebonechildren (ob, curBone); - } + for (curBone=bone->childbase.first; curBone; curBone=curBone->next) + selectconnected_posebonechildren(ob, curBone, extend); } /* within active object context */ /* previously known as "selectconnected_posearmature" */ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ARegion *ar= CTX_wm_region(C); + Object *ob= CTX_data_edit_object(C); Bone *bone, *curBone, *next= NULL; - int shift= 0; // XXX in pose mode, Shift+L is bound to another command - // named "PoseLib Add Current Pose" + int extend= RNA_boolean_get(op->ptr, "extend"); int x, y; - ARegion *ar; - Object *ob= CTX_data_edit_object(C); - ar= CTX_wm_region(C); - + x= event->x - ar->winrct.xmin; y= event->y - ar->winrct.ymin; view3d_operator_needs_opengl(C); - if (shift) + if (extend) bone= get_nearest_bone(C, 0, x, y); else bone= get_nearest_bone(C, 1, x, y); @@ -1395,26 +1395,29 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *ev /* Select parents */ for (curBone=bone; curBone; curBone=next){ - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name (ob->action, curBone->name, !(shift)); - if (shift) - curBone->flag &= ~BONE_SELECTED; - else - curBone->flag |= BONE_SELECTED; - - if (curBone->flag & BONE_CONNECTED) - next=curBone->parent; + /* ignore bone if cannot be selected */ + if ((curBone->flag & BONE_UNSELECTABLE) == 0) { + // XXX old cruft! use notifiers instead + //select_actionchannel_by_name (ob->action, curBone->name, !(shift)); + + if (extend) + curBone->flag &= ~BONE_SELECTED; + else + curBone->flag |= BONE_SELECTED; + + if (curBone->flag & BONE_CONNECTED) + next=curBone->parent; + else + next=NULL; + } else - next=NULL; + next= NULL; } /* Select children */ - for (curBone=bone->childbase.first; curBone; curBone=next){ - selectconnected_posebonechildren (ob, curBone); - } + for (curBone=bone->childbase.first; curBone; curBone=next) + selectconnected_posebonechildren(ob, curBone, extend); - // XXX this only counted the number of pose channels selected - //countall(); // flushes selection! WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob); return OPERATOR_FINISHED; @@ -1435,6 +1438,7 @@ void POSE_OT_select_linked(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* props */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); } /* **************** END Posemode stuff ********************** */ @@ -1446,7 +1450,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e { bArmature *arm; EditBone *bone, *curBone, *next; - int shift= 0; // XXX + int extend= RNA_boolean_get(op->ptr, "extend"); int x, y; ARegion *ar; Object *obedit= CTX_data_edit_object(C); @@ -1458,7 +1462,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e view3d_operator_needs_opengl(C); - if (shift) + if (extend) bone= get_nearest_bone(C, 0, x, y); else bone= get_nearest_bone(C, 1, x, y); @@ -1467,14 +1471,16 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e return OPERATOR_CANCELLED; /* Select parents */ - for (curBone=bone; curBone; curBone=next){ - if (shift){ - curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - } - else{ - curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + for (curBone=bone; curBone; curBone=next) { + if ((curBone->flag & BONE_UNSELECTABLE) == 0) { + if (extend) { + curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + } + else{ + curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + } } - + if (curBone->flag & BONE_CONNECTED) next=curBone->parent; else @@ -1482,19 +1488,19 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e } /* Select children */ - while (bone){ - for (curBone=arm->edbo->first; curBone; curBone=next){ + while (bone) { + for (curBone=arm->edbo->first; curBone; curBone=next) { next = curBone->next; - if (curBone->parent == bone){ - if (curBone->flag & BONE_CONNECTED){ - if (shift) + if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE)==0) { + if (curBone->flag & BONE_CONNECTED) { + if (extend) curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); else curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); bone=curBone; break; } - else{ + else { bone=NULL; break; } @@ -1502,15 +1508,12 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e } if (!curBone) bone=NULL; - } - + ED_armature_sync_selection(arm->edbo); - - /* BIF_undo_push("Select connected"); */ - + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit); - + return OPERATOR_FINISHED; } @@ -1527,6 +1530,9 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties s*/ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); } /* does bones and points */ @@ -3966,9 +3972,12 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op) { /* Set the flags */ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { - /* select bone */ - ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - ebone->flag &= ~BONE_ACTIVE; + /* ignore bone if selection can't change */ + if ((ebone->flag & BONE_UNSELECTABLE) == 0) { + /* select bone */ + ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone->flag &= ~BONE_ACTIVE; + } } CTX_DATA_END; @@ -3979,7 +3988,6 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op) void ARMATURE_OT_select_inverse(wmOperatorType *ot) { - /* identifiers */ ot->name= "Select Inverse"; ot->idname= "ARMATURE_OT_select_inverse"; @@ -4002,15 +4010,18 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { - if (sel==1) { - /* select bone */ - 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 | BONE_ACTIVE); + /* ignore bone if selection can't change */ + if ((ebone->flag & BONE_UNSELECTABLE) == 0) { + if (sel==1) { + /* select bone */ + 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 | BONE_ACTIVE); + } } } CTX_DATA_END; @@ -4051,7 +4062,8 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) arm= (bArmature *)ob->data; for (curbone= arm->edbo->first; curbone; curbone= curbone->next) { - if (EBONE_VISIBLE(arm, curbone)) { + /* 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 (direction == BONE_SELECT_PARENT) { if (curbone->parent == NULL) continue; @@ -4071,7 +4083,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) chbone = editbone_get_child(arm, curbone, 1); if (chbone == NULL) continue; - if (EBONE_VISIBLE(arm, chbone)) { + if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE)==0) { chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); if (!add_to_sel) { @@ -4301,8 +4313,9 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor if (!ob || !ob->pose) return 0; nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1); - - if (nearBone) { + + /* if the bone cannot be affected, don't do anything */ + if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) { bArmature *arm= ob->data; /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */ @@ -4381,7 +4394,8 @@ void ED_pose_deselectall (Object *ob, int test, int doundo) /* Set the flags accordingly */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { + /* ignore the pchan if it isn't visible or if its selection cannot be changed */ + 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; @@ -4960,8 +4974,10 @@ static int pose_select_inverse_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { - pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - pchan->bone->flag &= ~BONE_ACTIVE; + if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) { + pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + pchan->bone->flag &= ~BONE_ACTIVE; + } } CTX_DATA_END; @@ -4995,9 +5011,11 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { - /* select pchan */ - if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); - else pchan->bone->flag |= BONE_SELECTED; + /* select pchan, only if selectable */ + if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) { + if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + else pchan->bone->flag |= BONE_SELECTED; + } } CTX_DATA_END; @@ -5031,7 +5049,7 @@ static int pose_select_parent_exec(bContext *C, wmOperator *op) pchan=CTX_data_active_pchan(C); if (pchan) { parent=pchan->parent; - if ((parent) && !(parent->bone->flag & BONE_HIDDEN_P)) { + 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; diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index d4b7aa149df..edbc7b9ae9b 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -543,7 +543,7 @@ void pose_select_constraint_target(Scene *scene) for (ct= targets.first; ct; ct= ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget); - if(pchanc) + if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; } } @@ -582,7 +582,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *op) for (ct= targets.first; ct; ct= ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget); - if(pchanc) { + if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) { pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; found= 1; } @@ -634,7 +634,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { curbone= pchan->bone; - if (arm->layer & curbone->layer) { + if ((arm->layer & curbone->layer) && (curbone->flag & BONE_UNSELECTABLE)==0) { if (curbone->flag & (BONE_ACTIVE)) { if (direction == BONE_SELECT_PARENT) { @@ -646,7 +646,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; curbone->flag &= ~BONE_ACTIVE; pabone->flag |= (BONE_ACTIVE|BONE_SELECTED); - + found= 1; break; } @@ -660,7 +660,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; curbone->flag &= ~BONE_ACTIVE; chbone->flag |= (BONE_ACTIVE|BONE_SELECTED); - + found= 1; break; } diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 98603ee843a..4fa0e04728f 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -82,7 +82,7 @@ void ED_base_object_select(Base *base, short mode) if (base) { if (mode==BA_SELECT) { if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) - if (mode==BA_SELECT) base->flag |= SELECT; + base->flag |= SELECT; } else if (mode==BA_DESELECT) { base->flag &= ~SELECT; diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index e62c1dedb1b..3c10375c14b 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -4875,19 +4875,27 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar else if(tselem->type==TSE_POSE_CHANNEL) { bPoseChannel *pchan= (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); + + bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); } else if(tselem->type==TSE_EBONE) { EditBone *ebone= (EditBone *)te->directdata; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); + + bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); } } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 5dbfdd3e6f1..6c9d9263eeb 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -380,6 +380,11 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_CYCLICOFFSET); RNA_def_property_ui_text(prop, "Cyclic Offset", "When bone doesn't have a parent, it receives cyclic offset effects."); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + + prop= RNA_def_property(srna, "selectable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_UNSELECTABLE); + RNA_def_property_ui_text(prop, "Selectable", "Bone is able to be selected"); + RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* Number values */ /* envelope deform settings */ |