diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/armature/armature_select.c | 32 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_sketch.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 14 | ||||
-rw-r--r-- | source/blender/editors/metaball/mball_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 61 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_view.c | 57 |
6 files changed, 128 insertions, 40 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index ec0f193e780..3a0d07c02ee 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -177,7 +177,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.scene->basact, buffer, hits, findunsel, true); @@ -279,7 +279,7 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot) /* 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; @@ -290,6 +290,7 @@ static EditBone *get_nearest_editbonepoint( unsigned int hitresult, besthitresult = BONESEL_NOSEL; int i, mindep = 5; short hits; + 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,12 +304,33 @@ static EditBone *get_nearest_editbonepoint( ebone_next_act = NULL; } + bool do_nearest = false; + + /* 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; + } + } + + const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + + /* TODO: select larger region first (so we can use GPU_select_cache) */ BLI_rcti_init_pt_radius(&rect, mval, 5); + hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); - 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); + hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); } /* See if there are any selected bones in this group */ if (hits > 0) { @@ -434,7 +456,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) { diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index 8690072ca85..bba486bc65c 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -1909,7 +1909,7 @@ static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], c BLI_rcti_init_pt_radius(&rect, mval, 5); - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true); + hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); if (hits > 0) { int besthitresult = -1; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 5514dc0d3df..af6f37d937c 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -302,7 +302,19 @@ bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], con /* select */ #define MAXPICKELEMS 2500 #define MAXPICKBUF (4 * MAXPICKELEMS) -short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest); + +enum { + /* all elements in the region, ignore depth */ + VIEW3D_SELECT_ALL = 0, + /* pick also depth sorts (only for small regions!) */ + VIEW3D_SELECT_PICK_ALL = 1, + /* sorts and only returns visible objects (only for small regions!) */ + VIEW3D_SELECT_PICK_NEAREST = 2, +}; + +int view3d_opengl_select( + struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, + int select_mode); /* view3d_select.c */ float ED_view3d_select_dist_px(void); diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index fff53d6885e..bc42717b69f 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -594,7 +594,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese BLI_rcti_init_pt_radius(&rect, mval, 12); - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true); + hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); /* does startelem exist? */ ml = mb->editelems->first; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 49f24ef634f..0b3468f2c23 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -96,8 +96,12 @@ #include "GPU_draw.h" +#include "GPU_select.h" + #include "view3d_intern.h" /* own include */ +// #include "PIL_time_utildefines.h" + float ED_view3d_select_dist_px(void) { return 75.0f * U.pixelsize; @@ -1091,7 +1095,7 @@ static Base *object_mouse_select_menu( bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], bool toggle) { - int baseCount = 0; + short baseCount = 0; bool ok; LinkNode *linklist = NULL; @@ -1236,44 +1240,56 @@ static int mixed_bones_object_selectbuffer( do_nearest = do_nearest && !enumerate; + 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 finally' */ + GPU_select_cache_begin(); + BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest); + hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); if (hits15 == 1) { - return selectbuffer_ret_hits_15(buffer, hits15); + hits = selectbuffer_ret_hits_15(buffer, hits15); + goto finally; } else if (hits15 > 0) { has_bones15 = selectbuffer_has_bones(buffer, hits15); offs = 4 * hits15; BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest); + hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits9 == 1) { - return selectbuffer_ret_hits_9(buffer, hits15, hits9); + hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); + goto finally; } else if (hits9 > 0) { has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); offs += 4 * hits9; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest); + hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits5 == 1) { - return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + goto finally; } else if (hits5 > 0) { has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); } } - if (has_bones5) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); - else if (has_bones9) return selectbuffer_ret_hits_9(buffer, hits15, hits9); - else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15); - - if (hits5 > 0) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); - else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer, hits15, hits9); - else return selectbuffer_ret_hits_15(buffer, hits15); + if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } + else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } + else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } + + if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } + else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } + else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } } - - return 0; + +finally: + GPU_select_cache_end(); + + return hits; } /* returns basact */ @@ -1466,10 +1482,13 @@ static bool ed_object_select_pick( unsigned int buffer[MAXPICKBUF]; bool do_nearest; + // TIMEIT_START(select_time); + /* if objects have posemode set, the bones are in the same selection buffer */ - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest); - + + // TIMEIT_END(select_time); + if (hits > 0) { /* note: bundles are handling in the same way as bones */ const bool has_bones = selectbuffer_has_bones(buffer, hits); @@ -1908,7 +1927,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false); + hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); if (extend == false && select) BKE_mball_deselect_all(mb); @@ -1942,7 +1961,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false); + hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); /* clear flag we use to detect point was affected */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) @@ -2039,7 +2058,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); - hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, false); + hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); /* * LOGIC NOTES (theeth): * The buffer and ListBase have the same relative order, which makes the selection diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 20361b73e78..9d1a3633786 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1170,18 +1170,24 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi * * \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection. */ -short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest) +int view3d_opengl_select( + ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, + int select_mode) { Scene *scene = vc->scene; View3D *v3d = vc->v3d; ARegion *ar = vc->ar; rcti rect; - short hits; + int hits; const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL); - const bool do_passes = do_nearest && GPU_select_query_check_active(); + const bool is_pick_select = (U.gpu_select_pick_deph != 0); + const bool do_passes = ( + (is_pick_select == false) && + (select_mode == VIEW3D_SELECT_PICK_NEAREST) && + GPU_select_query_check_active()); + + char gpu_select_mode; - G.f |= G_PICKSEL; - /* case not a border select */ if (input->xmin == input->xmax) { /* seems to be default value for bones only now */ @@ -1190,7 +1196,38 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b else { rect = *input; } - + + if (is_pick_select) { + if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) { + gpu_select_mode = GPU_SELECT_PICK_NEAREST; + } + else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) { + gpu_select_mode = GPU_SELECT_PICK_ALL; + } + else { + gpu_select_mode = GPU_SELECT_ALL; + } + } + else { + if (do_passes) { + gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS; + } + else { + gpu_select_mode = GPU_SELECT_ALL; + } + } + + /* Re-use cache (rect must be smaller then the cached) + * other context is assumed to be unchanged */ + if (GPU_select_is_cached()) { + GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); + GPU_select_cache_load_id(); + hits = GPU_select_end(); + goto finally; + } + + G.f |= G_PICKSEL; + view3d_winmatrix_set(ar, v3d, &rect); mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); @@ -1202,10 +1239,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b if (vc->rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_set(vc->rv3d); - if (do_passes) - GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); - else - GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0); + GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip); @@ -1231,7 +1265,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b if (vc->rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_disable(); - + +finally: if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */ return hits; |