diff options
author | Hans Goudey <h.goudey@me.com> | 2022-10-07 07:26:44 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-10-07 07:26:44 +0300 |
commit | 2c803124d371bbbd564dd4c5051258f53b799d36 (patch) | |
tree | 2fc642f1aa96ed9464483a7a7c57cf82f7531578 /source/blender/editors/space_view3d/view3d_select.cc | |
parent | 846d8ef8568c035cd7d4e1a8168a4ba391de9119 (diff) | |
parent | cafd204af6d9969654bdee5ae14fef220640487c (diff) |
Merge branch 'master' into refactor-mesh-position-generic
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_select.cc')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.cc | 170 |
1 files changed, 107 insertions, 63 deletions
diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index a3917e0ed44..ed7d6e74bb0 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -28,6 +28,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -574,11 +575,16 @@ static bool do_lasso_select_objects(ViewContext *vc, BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */ - short region_co[2]; + float region_co[2]; const bool is_select = base->flag & BASE_SELECTED; - const bool is_inside = - (ED_view3d_project_base(vc->region, base, region_co) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcoords, mcoords_len, region_co[0], region_co[1], IS_CLIPPED); + const bool is_inside = (ED_view3d_project_base(vc->region, base, region_co) == + V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside(mcoords, + mcoords_len, + int(region_co[0]), + int(region_co[1]), + /* Dummy value. */ + INT_MAX); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT); @@ -696,7 +702,7 @@ static bool do_lasso_select_pose(ViewContext *vc, static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); @@ -775,7 +781,7 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); @@ -883,7 +889,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, } static void do_lasso_select_curve__doSelect(void *userData, - Nurb *UNUSED(nu), + Nurb * /*nu*/, BPoint *bp, BezTriple *bezt, int beztindex, @@ -1442,8 +1448,8 @@ static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE]; /* special (crappy) operator only for menu select */ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, - PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), + PointerRNA * /*ptr*/, + PropertyRNA * /*prop*/, bool *r_free) { EnumPropertyItem *item = nullptr, item_tmp = {0}; @@ -1588,13 +1594,24 @@ static bool object_mouse_select_menu(bContext *C, const SelectPick_Params *params, Base **r_basact) { + + const float mval_fl[2] = {float(mval[0]), float(mval[1])}; + /* Distance from object center to use for selection. */ + const float dist_threshold_sq = square_f(15 * U.pixelsize); int base_count = 0; - bool ok; - LinkNodePair linklist = {nullptr, nullptr}; + + struct BaseRefWithDepth { + struct BaseRefWithDepth *next, *prev; + Base *base; + /** The scale isn't defined, simply use for sorting. */ + uint depth_id; + }; + ListBase base_ref_list = {nullptr, nullptr}; /* List of #BaseRefWithDepth. */ /* handle base->object->select_id */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - ok = false; + bool ok = false; + uint depth_id; /* two selection methods, the CTRL select uses max dist of 15 */ if (buffer) { @@ -1602,28 +1619,29 @@ static bool object_mouse_select_menu(bContext *C, /* index was converted */ if (base->object->runtime.select_id == (buffer[a].id & ~0xFFFF0000)) { ok = true; + depth_id = buffer[a].depth; break; } } } else { - const int dist = 15 * U.pixelsize; - short region_co[2]; + float region_co[2]; if (ED_view3d_project_base(vc->region, base, region_co) == V3D_PROJ_RET_OK) { - const int delta_px[2] = {region_co[0] - mval[0], region_co[1] - mval[1]}; - if (len_manhattan_v2_int(delta_px) < dist) { + const float dist_test_sq = len_squared_v2v2(mval_fl, region_co); + if (dist_test_sq < dist_threshold_sq) { ok = true; + /* Match GPU depth logic, as the float is always positive, it can be sorted as an int. */ + depth_id = float_as_uint(dist_test_sq); } } } if (ok) { base_count++; - BLI_linklist_append(&linklist, base); - - if (base_count == SEL_MENU_SIZE) { - break; - } + BaseRefWithDepth *base_ref = MEM_new<BaseRefWithDepth>(__func__); + base_ref->base = base; + base_ref->depth_id = depth_id; + BLI_addtail(&base_ref_list, (void *)base_ref); } } CTX_DATA_END; @@ -1634,20 +1652,30 @@ static bool object_mouse_select_menu(bContext *C, return false; } if (base_count == 1) { - Base *base = (Base *)linklist.list->link; - BLI_linklist_free(linklist.list, nullptr); + Base *base = ((BaseRefWithDepth *)base_ref_list.first)->base; + BLI_freelistN(&base_ref_list); *r_basact = base; return false; } + /* Sort by depth or distance to cursor. */ + BLI_listbase_sort(&base_ref_list, [](const void *a, const void *b) { + return int(static_cast<const BaseRefWithDepth *>(a)->depth_id > + static_cast<const BaseRefWithDepth *>(b)->depth_id); + }); + + while (base_count > SEL_MENU_SIZE) { + BLI_freelinkN(&base_ref_list, base_ref_list.last); + base_count -= 1; + } + /* UI, full in static array values that we later use in an enum function */ - LinkNode *node; - int i; memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); - for (node = linklist.list, i = 0; node; node = node->next, i++) { - Base *base = static_cast<Base *>(node->link); + int i; + LISTBASE_FOREACH_INDEX (BaseRefWithDepth *, base_ref, &base_ref_list, i) { + Base *base = base_ref->base; Object *ob = base->object; const char *name = ob->id.name + 2; @@ -1665,7 +1693,7 @@ static bool object_mouse_select_menu(bContext *C, WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); - BLI_linklist_free(linklist.list, nullptr); + BLI_freelistN(&base_ref_list); return true; } @@ -1782,8 +1810,20 @@ static bool bone_mouse_select_menu(bContext *C, BLI_assert(buffer); int bone_count = 0; - LinkNodePair base_list = {nullptr, nullptr}; - LinkNodePair bone_list = {nullptr, nullptr}; + + struct BoneRefWithDepth { + struct BoneRefWithDepth *next, *prev; + Base *base; + union { + EditBone *ebone; + bPoseChannel *pchan; + void *bone_ptr; + }; + /** The scale isn't defined, simply use for sorting. */ + uint depth_id; + }; + ListBase bone_ref_list = {nullptr, nullptr}; + GSet *added_bones = BLI_gset_ptr_new("Bone mouse select menu"); /* Select logic taken from ed_armature_pick_bone_from_selectbuffer_impl in armature_select.c */ @@ -1815,18 +1855,16 @@ static bool bone_mouse_select_menu(bContext *C, /* Determine what the current bone is */ if (is_editmode) { - EditBone *ebone; const uint hit_bone = (hitresult & ~BONESEL_ANY) >> 16; bArmature *arm = static_cast<bArmature *>(bone_base->object->data); - ebone = static_cast<EditBone *>(BLI_findlink(arm->edbo, hit_bone)); + EditBone *ebone = static_cast<EditBone *>(BLI_findlink(arm->edbo, hit_bone)); if (ebone && !(ebone->flag & BONE_UNSELECTABLE)) { bone_ptr = ebone; } } else { - bPoseChannel *pchan; const uint hit_bone = (hitresult & ~BONESEL_ANY) >> 16; - pchan = static_cast<bPoseChannel *>( + bPoseChannel *pchan = static_cast<bPoseChannel *>( BLI_findlink(&bone_base->object->pose->chanbase, hit_bone)); if (pchan && !(pchan->bone->flag & BONE_UNSELECTABLE)) { bone_ptr = pchan; @@ -1842,13 +1880,13 @@ static bool bone_mouse_select_menu(bContext *C, if (!is_duplicate_bone) { bone_count++; - BLI_linklist_append(&base_list, bone_base); - BLI_linklist_append(&bone_list, bone_ptr); - BLI_gset_insert(added_bones, bone_ptr); + BoneRefWithDepth *bone_ref = MEM_new<BoneRefWithDepth>(__func__); + bone_ref->base = bone_base; + bone_ref->bone_ptr = bone_ptr; + bone_ref->depth_id = buffer[a].depth; + BLI_addtail(&bone_ref_list, (void *)bone_ref); - if (bone_count == SEL_MENU_SIZE) { - break; - } + BLI_gset_insert(added_bones, bone_ptr); } } @@ -1858,31 +1896,38 @@ static bool bone_mouse_select_menu(bContext *C, return false; } if (bone_count == 1) { - BLI_linklist_free(base_list.list, nullptr); - BLI_linklist_free(bone_list.list, nullptr); + BLI_freelistN(&bone_ref_list); return false; } - /* UI, full in static array values that we later use in an enum function */ - LinkNode *bone_node, *base_node; - int i; + /* Sort by depth or distance to cursor. */ + BLI_listbase_sort(&bone_ref_list, [](const void *a, const void *b) { + return int(static_cast<const BoneRefWithDepth *>(a)->depth_id > + static_cast<const BoneRefWithDepth *>(b)->depth_id); + }); + while (bone_count > SEL_MENU_SIZE) { + BLI_freelinkN(&bone_ref_list, bone_ref_list.last); + bone_count -= 1; + } + + /* UI, full in static array values that we later use in an enum function */ memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); - for (base_node = base_list.list, bone_node = bone_list.list, i = 0; bone_node; - base_node = base_node->next, bone_node = bone_node->next, i++) { + int i; + LISTBASE_FOREACH_INDEX (BoneRefWithDepth *, bone_ref, &bone_ref_list, i) { char *name; - object_mouse_select_menu_data[i].base_ptr = static_cast<Base *>(base_node->link); + object_mouse_select_menu_data[i].base_ptr = bone_ref->base; if (is_editmode) { - EditBone *ebone = static_cast<EditBone *>(bone_node->link); - object_mouse_select_menu_data[i].item_ptr = ebone; + EditBone *ebone = bone_ref->ebone; + object_mouse_select_menu_data[i].item_ptr = static_cast<void *>(ebone); name = ebone->name; } else { - bPoseChannel *pchan = static_cast<bPoseChannel *>(bone_node->link); - object_mouse_select_menu_data[i].item_ptr = pchan; + bPoseChannel *pchan = bone_ref->pchan; + object_mouse_select_menu_data[i].item_ptr = static_cast<void *>(pchan); name = pchan->name; } @@ -1900,8 +1945,7 @@ static bool bone_mouse_select_menu(bContext *C, WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); - BLI_linklist_free(base_list.list, nullptr); - BLI_linklist_free(bone_list.list, nullptr); + BLI_freelistN(&bone_ref_list); return true; } @@ -1916,7 +1960,7 @@ static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hit } /* utility function for mixed_bones_object_selectbuffer */ -static int selectbuffer_ret_hits_15(GPUSelectResult *UNUSED(buffer), const int hits15) +static int selectbuffer_ret_hits_15(GPUSelectResult * /*buffer*/, const int hits15) { return hits15; } @@ -3260,7 +3304,7 @@ static bool do_paintface_box_select(ViewContext *vc, } static void do_nurbs_box_select__doSelect(void *userData, - Nurb *UNUSED(nu), + Nurb * /*nu*/, BPoint *bp, BezTriple *bezt, int beztindex, @@ -3360,7 +3404,7 @@ static bool do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp s static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); @@ -3427,7 +3471,7 @@ static void do_mesh_box_select__doSelectEdge_pass1( static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData); const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); @@ -3995,7 +4039,7 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); @@ -4008,7 +4052,7 @@ static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], - int UNUSED(index)) + int /*index*/) { CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); @@ -4020,7 +4064,7 @@ static void mesh_circle_doSelectEdge(void *userData, static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], - int UNUSED(index)) + int /*index*/) { CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); @@ -4240,11 +4284,11 @@ static bool paint_vertsel_circle_select(ViewContext *vc, } static void nurbscurve_circle_doSelect(void *userData, - Nurb *UNUSED(nu), + Nurb * /*nu*/, BPoint *bp, BezTriple *bezt, int beztindex, - bool UNUSED(handles_visible), + bool /*handles_visible*/, const float screen_co[2]) { CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData); |