/* x and y are mouse coords (area space) */ void *get_nearest_bone(bContext *C, short findunsel, int x, int y) { ViewContext vc; rcti rect; unsigned int buffer[MAXPICKBUF]; short hits; view3d_set_viewcontext(C, &vc); // rect.xmin = ... mouseco! rect.xmin = rect.xmax = x; rect.ymin = rect.ymax = y; hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true); if (hits > 0) return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true); return NULL; }
/* Select MetaElement with mouse click (user can select radius circle or * stiffness circle) */ int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int toggle) { static MetaElem *startelem = NULL; Object *obedit = CTX_data_edit_object(C); ViewContext vc; MetaBall *mb = (MetaBall *)obedit->data; MetaElem *ml, *ml_act = NULL; int a, hits; unsigned int buffer[4 * MAXPICKBUF]; rcti rect; view3d_set_viewcontext(C, &vc); rect.xmin = mval[0] - 12; rect.xmax = mval[0] + 12; rect.ymin = mval[1] - 12; rect.ymax = mval[1] + 12; hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect); /* does startelem exist? */ ml = mb->editelems->first; while (ml) { if (ml == startelem) break; ml = ml->next; } if (ml == NULL) startelem = mb->editelems->first; if (hits > 0) { ml = startelem; while (ml) { for (a = 0; a < hits; a++) { /* index converted for gl stuff */ if (ml->selcol1 == buffer[4 * a + 3]) { ml->flag |= MB_SCALE_RAD; ml_act = ml; } if (ml->selcol2 == buffer[4 * a + 3]) { ml->flag &= ~MB_SCALE_RAD; ml_act = ml; } } if (ml_act) break; ml = ml->next; if (ml == NULL) ml = mb->editelems->first; if (ml == startelem) break; } /* When some metaelem was found, then it is necessary to select or * deselect it. */ if (ml_act) { if (extend) { ml_act->flag |= SELECT; } else if (deselect) { ml_act->flag &= ~SELECT; } else if (toggle) { if (ml_act->flag & SELECT) ml_act->flag &= ~SELECT; else ml_act->flag |= SELECT; } else { /* Deselect all existing metaelems */ BKE_mball_deselect_all(mb); /* Select only metaelem clicked on */ ml_act->flag |= SELECT; } mb->lastelem = ml_act; WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); return 1; } } return 0; }
/* note that BONE ROOT only gets drawn for root bones (or without IK) */ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], ListBase *edbo, int findunsel, int *selmask) { bArmature *arm = (bArmature *)vc->obedit->data; EditBone *ebone_next_act = arm->act_edbone; EditBone *ebone; rcti rect; unsigned int buffer[MAXPICKBUF]; unsigned int hitresult, besthitresult = BONESEL_NOSEL; int i, mindep = 4; short hits; glInitNames(); /* find the bone after the current active bone, so as to bump up its chances in selection. * this way overlapping bones will cycle selection state as with objects. */ if (ebone_next_act && EBONE_VISIBLE(arm, ebone_next_act) && ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) { ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first; } else { ebone_next_act = NULL; } rect.xmin = mval[0] - 5; rect.xmax = mval[0] + 5; rect.ymin = mval[1] - 5; rect.ymax = mval[1] + 5; hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect); if (hits == 0) { rect.xmin = mval[0] - 12; rect.xmax = mval[0] + 12; rect.ymin = mval[1] - 12; rect.ymax = mval[1] + 12; hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect); } /* See if there are any selected bones in this group */ if (hits > 0) { if (hits == 1) { if (!(buffer[3] & BONESEL_NOSEL)) besthitresult = buffer[3]; } else { for (i = 0; i < hits; i++) { hitresult = buffer[3 + (i * 4)]; if (!(hitresult & BONESEL_NOSEL)) { int dep; ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY); /* clicks on bone points get advantage */ if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) { /* but also the unselected one */ if (findunsel) { if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) dep = 1; else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) dep = 1; else dep = 2; } else { dep = 2; } } else { /* bone found */ if (findunsel) { if ((ebone->flag & BONE_SELECTED) == 0) dep = 2; else dep = 3; } else { dep = 3; } } if (ebone == ebone_next_act) { dep -= 1; } if (dep < mindep) { mindep = dep; besthitresult = hitresult; } } } } if (!(besthitresult & BONESEL_NOSEL)) { ebone = BLI_findlink(edbo, besthitresult & ~BONESEL_ANY); *selmask = 0; if (besthitresult & BONESEL_ROOT) *selmask |= BONE_ROOTSEL; if (besthitresult & BONESEL_TIP) *selmask |= BONE_TIPSEL; if (besthitresult & BONESEL_BONE) *selmask |= BONE_SELECTED; return ebone; } } *selmask = 0; return NULL; }