diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-03-09 08:47:31 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-03-09 08:47:31 +0300 |
commit | b40a4f66b250ceafb8a9b8e6b644a8f1df802c1c (patch) | |
tree | 90844a3f9fb41f38ac37a26783b506d138a5a5a9 /source/blender/editors/armature/armature_select.c | |
parent | 696ed6d3caef5ad81c011d435fd02f82f6c231d3 (diff) | |
parent | 4ab322fdd2e019ba337b2560a2d36f2175c03a32 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/editors/armature/armature_select.c')
-rw-r--r-- | source/blender/editors/armature/armature_select.c | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index a6f2fa40f46..1b2b70cd60d 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -53,6 +53,8 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "GPU_select.h" + #include "armature_intern.h" /* utility macros for storing a temp int in the bone (selection flag) */ @@ -177,7 +179,7 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel) rect.xmin = rect.xmax = xy[0]; rect.ymin = rect.ymax = xy[1]; - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true); + hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); if (hits > 0) return get_bone_from_selectbuffer(vc.scene, vc.sl->basact, buffer, hits, findunsel, true); @@ -275,11 +277,24 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); } +/* utility function for get_nearest_editbonepoint */ +static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12) +{ + return hits12; +} + +static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5) +{ + const int offs = 4 * hits12; + memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int)); + return hits5; +} + /* does bones and points */ /* 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, bool findunsel, int *r_selmask) + ListBase *edbo, bool findunsel, bool use_cycle, int *r_selmask) { bArmature *arm = (bArmature *)vc->obedit->data; EditBone *ebone_next_act = arm->act_edbone; @@ -289,7 +304,9 @@ static EditBone *get_nearest_editbonepoint( unsigned int buffer[MAXPICKBUF]; unsigned int hitresult, besthitresult = BONESEL_NOSEL; int i, mindep = 5; - short hits; + int hits12, hits5 = 0; + + static int last_mval[2] = {-100, -100}; /* 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. */ @@ -303,16 +320,59 @@ static EditBone *get_nearest_editbonepoint( ebone_next_act = NULL; } - BLI_rcti_init_pt_radius(&rect, mval, 5); + bool do_nearest = false; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true); - if (hits == 0) { - BLI_rcti_init_pt_radius(&rect, mval, 12); - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true); + /* define if we use solid nearest select or not */ + if (use_cycle) { + if (vc->v3d->drawtype > OB_WIRE) { + do_nearest = true; + if (len_manhattan_v2v2_int(mval, last_mval) < 3) { + do_nearest = false; + } + } + copy_v2_v2_int(last_mval, mval); + } + else { + if (vc->v3d->drawtype > OB_WIRE) { + do_nearest = true; + } } + + /* matching logic from 'mixed_bones_object_selectbuffer' */ + const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + int hits = 0; + + /* we _must_ end cache before return, use 'goto cache_end' */ + GPU_select_cache_begin(); + + BLI_rcti_init_pt_radius(&rect, mval, 12); + hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + if (hits12 == 1) { + hits = selectbuffer_ret_hits_12(buffer, hits12); + goto cache_end; + } + else if (hits12 > 0) { + int offs; + + offs = 4 * hits12; + BLI_rcti_init_pt_radius(&rect, mval, 5); + hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + + if (hits5 == 1) { + hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); + goto cache_end; + } + + if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); goto cache_end; } + else { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; } + } + +cache_end: + GPU_select_cache_end(); + /* See if there are any selected bones in this group */ if (hits > 0) { - + if (hits == 1) { if (!(buffer[3] & BONESEL_NOSEL)) besthitresult = buffer[3]; @@ -434,7 +494,7 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d return true; } - nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, &selmask); + nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, true, &selmask); if (nearBone) { if (!extend && !deselect && !toggle) { |