diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-06-19 17:41:18 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-06-19 17:43:01 +0300 |
commit | 750a78be9cfa71713bac5b73f9a61c40deeb994c (patch) | |
tree | aefaf46f8869e949f5a8098b9c0625baed0082c5 | |
parent | 0116c95d4c9114bc9eae03401c0471fba265cd46 (diff) |
3D View: improve selection locking
Locked selection would still occlude with objects which could not be
selected.
-rw-r--r-- | source/blender/draw/DRW_engine.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 17 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_select.c | 12 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 9 | ||||
-rw-r--r-- | source/blender/editors/metaball/mball_edit.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 36 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_view.c | 31 |
7 files changed, 96 insertions, 20 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 524a94e5886..d126dcb71aa 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -94,6 +94,8 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx); typedef enum eDRWSelectStage { DRW_SELECT_PASS_PRE = 1, DRW_SELECT_PASS_POST, } eDRWSelectStage; typedef bool (*DRW_SelectPassFn)( eDRWSelectStage stage, void *user_data); +typedef bool (*DRW_ObjectFilterFn)( + struct Object *ob, void *user_data); void DRW_draw_view(const struct bContext *C); @@ -118,7 +120,8 @@ void DRW_draw_select_loop( struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, bool use_obedit_skip, bool use_nearest, const struct rcti *rect, - DRW_SelectPassFn select_pass_fn, void *select_pass_user_data); + DRW_SelectPassFn select_pass_fn, void *select_pass_user_data, + DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data); void DRW_draw_depth_loop( struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index ef42b88fd72..fcdc4a3a016 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1634,7 +1634,8 @@ void DRW_draw_select_loop( struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect, - DRW_SelectPassFn select_pass_fn, void *select_pass_user_data) + DRW_SelectPassFn select_pass_fn, void *select_pass_user_data, + DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data) { Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); @@ -1721,6 +1722,7 @@ void DRW_draw_select_loop( #endif } else { + bool filter_exclude = false; DEG_OBJECT_ITER_BEGIN( depsgraph, ob, DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | @@ -1728,6 +1730,19 @@ void DRW_draw_select_loop( DEG_ITER_OBJECT_FLAG_DUPLI) { if ((ob->base_flag & BASE_SELECTABLED) != 0) { + + if (object_filter_fn != NULL) { + if (ob->base_flag & BASE_FROMDUPLI) { + /* pass (use previous filter_exclude value) */ + } + else { + filter_exclude = (object_filter_fn(ob, object_filter_user_data) == false); + } + if (filter_exclude) { + continue; + } + } + /* This relies on dupli instances being after their instancing object. */ if ((ob->base_flag & BASE_FROMDUPLI) == 0) { Object *ob_orig = DEG_get_original_object(ob); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index cd5a4ced26f..e295e1fd35a 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -254,7 +254,9 @@ void *get_nearest_bone( rect.xmin = rect.xmax = xy[0]; rect.ymin = rect.ymax = xy[1]; - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select( + &vc, buffer, MAXPICKBUF, &rect, + VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP); *r_base = NULL; @@ -446,9 +448,11 @@ static EditBone *get_nearest_editbonepoint( { const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP; + rcti rect; BLI_rcti_init_pt_radius(&rect, vc->mval, 12); - const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); if (hits12 == 1) { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; @@ -458,7 +462,9 @@ static EditBone *get_nearest_editbonepoint( offs = 4 * hits12; BLI_rcti_init_pt_radius(&rect, vc->mval, 5); - const int hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + const int hits5 = view3d_opengl_select( + vc, buffer + offs, MAXPICKBUF - offs, &rect, + select_mode, select_filter); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 24e5b3e2662..343bffa0082 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -351,12 +351,19 @@ typedef enum { VIEW3D_SELECT_PICK_NEAREST = 2, } eV3DSelectMode; +typedef enum { + /* Don't exclude anything. */ + VIEW3D_SELECT_FILTER_NOP = 0, + /* Don't select objects outside the current mode. */ + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1, +} eV3DSelectObjectFilter; + void view3d_opengl_select_cache_begin(void); void view3d_opengl_select_cache_end(void); int view3d_opengl_select( struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, - eV3DSelectMode select_mode); + eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter); /* 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 aea125ce4b9..1ae122a3801 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -617,7 +617,9 @@ 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, VIEW3D_SELECT_PICK_NEAREST); + hits = view3d_opengl_select( + &vc, buffer, MAXPICKBUF, &rect, + VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP); /* does startelem exist? */ ml = mb->editelems->first; @@ -682,5 +684,3 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese return false; } - - diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 9b40f03a54a..b4f3be178aa 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1172,7 +1172,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const /* so check three selection levels and compare */ static int mixed_bones_object_selectbuffer( ViewContext *vc, unsigned int *buffer, const int mval[2], - bool use_cycle, bool enumerate, + bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter, bool *r_do_nearest) { rcti rect; @@ -1211,7 +1211,7 @@ static int mixed_bones_object_selectbuffer( view3d_opengl_select_cache_begin(); BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); if (hits15 == 1) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; @@ -1222,7 +1222,7 @@ static int mixed_bones_object_selectbuffer( offs = 4 * hits15; BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); if (hits9 == 1) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; @@ -1232,7 +1232,7 @@ static int mixed_bones_object_selectbuffer( offs += 4 * hits9; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; @@ -1373,7 +1373,10 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) ED_view3d_viewcontext_init(C, &vc); - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest); + hits = mixed_bones_object_selectbuffer( + &vc, buffer, mval, + false, false, VIEW3D_SELECT_FILTER_NOP, + &do_nearest); if (hits > 0) { const bool has_bones = selectbuffer_has_bones(buffer, hits); @@ -1487,7 +1490,13 @@ static bool ed_object_select_pick( // 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); + const eV3DSelectObjectFilter select_filter = ( + (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP); + hits = mixed_bones_object_selectbuffer( + &vc, buffer, mval, + true, enumerate, select_filter, + &do_nearest); // TIMEIT_END(select_time); @@ -1968,7 +1977,9 @@ static int do_meta_box_select( unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, + VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); if (extend == false && select) BKE_mball_deselect_all(mb); @@ -2002,7 +2013,9 @@ static int do_armature_box_select( unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, + VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len); @@ -2150,7 +2163,12 @@ 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, VIEW3D_SELECT_ALL); + const eV3DSelectObjectFilter select_filter = ( + (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? + VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP); + hits = view3d_opengl_select( + vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, + VIEW3D_SELECT_ALL, select_filter); /* * 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 73b9a67ac56..abb8c688e05 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -896,6 +896,13 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data) } #endif /* WITH_OPENGL_LEGACY */ +/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */ +static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data) +{ + const Object *obact = user_data; + return BKE_object_is_mode_compat(ob, obact->mode); +} + /** * \warning be sure to account for a negative return value * This is an error, "Too many objects in select buffer" @@ -905,7 +912,7 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data) */ int view3d_opengl_select( ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, - eV3DSelectMode select_mode) + eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter) { struct bThemeState theme_state; Depsgraph *depsgraph = vc->depsgraph; @@ -953,6 +960,25 @@ int view3d_opengl_select( } } + struct { + DRW_ObjectFilterFn fn; + void *user_data; + } object_filter = {NULL, NULL}; + switch (select_filter) { + case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK: + { + Object *obact = OBACT(vc->view_layer); + if (obact && obact->mode != OB_MODE_OBJECT) { + object_filter.fn = drw_select_filter_object_mode_lock; + object_filter.user_data = obact; + } + break; + } + case VIEW3D_SELECT_FILTER_NOP: + break; + + } + /* Tools may request depth outside of regular drawing code. */ UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); @@ -1014,7 +1040,8 @@ int view3d_opengl_select( DRW_draw_select_loop( depsgraph, ar, v3d, use_obedit_skip, use_nearest, &rect, - drw_select_loop_pass, &drw_select_loop_user_data); + drw_select_loop_pass, &drw_select_loop_user_data, + object_filter.fn, object_filter.user_data); hits = drw_select_loop_user_data.hits; } #endif /* WITH_OPENGL_LEGACY */ |