static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select) { Bone *bone; for (bone = bone_parent->childbase.first; bone; bone = bone->next) { if (select && PBONE_SELECTABLE(arm, bone)) bone->flag |= BONE_SELECTED; else bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); do_outliner_bone_select_recursive(arm, bone, select); } }
/* Utility method for changing the selection status of a bone */ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) { bArmature *arm; /* sanity checks */ // XXX: actually, we can probably still get away with no object - at most we have no updates if (ELEM4(NULL, ob, ob->pose, pchan, pchan->bone)) return; arm = ob->data; /* can only change selection state if bone can be modified */ if (PBONE_SELECTABLE(arm, pchan->bone)) { /* change selection state - activate too if selected */ if (select) { pchan->bone->flag |= BONE_SELECTED; arm->act_bone = pchan->bone; } else { pchan->bone->flag &= ~BONE_SELECTED; arm->act_bone = NULL; } // TODO: select and activate corresponding vgroup? /* tag necessary depsgraph updates * (see rna_Bone_select_update() in rna_armature.c for details) */ if (arm->flag & ARM_HAS_VIZ_DEPS) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } /* send necessary notifiers */ WM_main_add_notifier(NC_GEOM | ND_DATA, ob); } }
static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = ob->data; Bone *curbone, *pabone, *chbone; int direction = RNA_enum_get(op->ptr, "direction"); const bool add_to_sel = RNA_boolean_get(op->ptr, "extend"); bool found = false; CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) { curbone = pchan->bone; if ((curbone->flag & BONE_UNSELECTABLE) == 0) { if (curbone == arm->act_bone) { if (direction == BONE_SELECT_PARENT) { if (pchan->parent == NULL) continue; else pabone = pchan->parent->bone; if (PBONE_SELECTABLE(arm, pabone)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; pabone->flag |= BONE_SELECTED; arm->act_bone = pabone; found = 1; break; } } else { /* direction == BONE_SELECT_CHILD */ /* the child member is only assigned to connected bones, see [#30340] */ #if 0 if (pchan->child == NULL) continue; else chbone = pchan->child->bone; #else /* instead. find _any_ visible child bone, using the first one is a little arbitrary - campbell */ chbone = pchan->child ? pchan->child->bone : NULL; if (chbone == NULL) { bPoseChannel *pchan_child; for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) { /* possible we have multiple children, some invisible */ if (PBONE_SELECTABLE(arm, pchan_child->bone)) { if (pchan_child->parent == pchan) { chbone = pchan_child->bone; break; } } } } if (chbone == NULL) continue; #endif if (PBONE_SELECTABLE(arm, chbone)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; chbone->flag |= BONE_SELECTED; arm->act_bone = chbone; found = 1; break; } } } } }