static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { EditBone *actbone = CTX_data_active_bone(C); uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE); uiLayout *layout = uiPupMenuLayout(pup); int allchildbones = 0; CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ebone != actbone) { if (ebone->parent != actbone) allchildbones = 1; } } CTX_DATA_END; uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT); /* ob becomes parent, make the associated menus */ if (allchildbones) uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET); uiPupMenuEnd(C, pup); return OPERATOR_CANCELLED; }
static int armature_select_similar_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; EditBone *ebone_act = CTX_data_active_bone(C); /* Get props */ int type = RNA_enum_get(op->ptr, "type"); float thresh = RNA_float_get(op->ptr, "threshold"); /* Check for active bone */ if (ebone_act == NULL) { BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } switch (type) { case SIMEDBONE_LENGTH: select_similar_length(arm, ebone_act, thresh); break; case SIMEDBONE_DIRECTION: select_similar_direction(arm, ebone_act, thresh); break; case SIMEDBONE_PREFIX: select_similar_prefix(arm, ebone_act); break; case SIMEDBONE_SUFFIX: select_similar_suffix(arm, ebone_act); break; case SIMEDBONE_LAYER: select_similar_layer(arm, ebone_act); break; } WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); return OPERATOR_FINISHED; }
static int armature_parent_set_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); bArmature *arm = (bArmature *)ob->data; EditBone *actbone = CTX_data_active_bone(C); EditBone *actmirb = NULL; short val = RNA_enum_get(op->ptr, "type"); /* there must be an active bone */ if (actbone == NULL) { BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } else if (arm->flag & ARM_MIRROR_EDIT) { /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R"). * This is useful for arm-chains, for example parenting lower arm to upper arm * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent") * then just use actbone. Useful when doing upper arm to spine. */ actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone); if (actmirb == NULL) actmirb = actbone; } /* if there is only 1 selected bone, we assume that that is the active bone, * since a user will need to have clicked on a bone (thus selecting it) to make it active */ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) { /* When only the active bone is selected, and it has a parent, * connect it to the parent, as that is the only possible outcome. */ if (actbone->parent) { bone_connect_to_existing_parent(actbone); if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent)) bone_connect_to_existing_parent(actmirb); } } else { /* Parent 'selected' bones to the active one * - the context iterator contains both selected bones and their mirrored copies, * so we assume that unselected bones are mirrored copies of some selected bone * - since the active one (and/or its mirror) will also be selected, we also need * to check that we are not trying to operate on them, since such an operation * would cause errors */ /* parent selected bones to the active one */ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ELEM(ebone, actbone, actmirb) == 0) { if (ebone->flag & BONE_SELECTED) bone_connect_to_new_parent(arm->edbo, ebone, actbone, val); else bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val); } } CTX_DATA_END; } /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); return OPERATOR_FINISHED; }