Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_select.c
| Show All 39 Lines | |||||
| #include "BLI_math_bits.h" | #include "BLI_math_bits.h" | ||||
| #include "BLI_rand.h" | #include "BLI_rand.h" | ||||
| #include "BLI_array.h" | #include "BLI_array.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BKE_paint.h" | #include "BKE_paint.h" | ||||
| #include "BKE_editmesh.h" | #include "BKE_editmesh.h" | ||||
| #include "BKE_layer.h" | |||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| ▲ Show 20 Lines • Show All 841 Lines • ▼ Show 20 Lines | |||||
| /* best distance based on screen coords. | /* best distance based on screen coords. | ||||
| * use em->selectmode to define how to use | * use em->selectmode to define how to use | ||||
| * selected vertices and edges get disadvantage | * selected vertices and edges get disadvantage | ||||
| * return 1 if found one | * return 1 if found one | ||||
| */ | */ | ||||
| static int unified_findnearest( | static int unified_findnearest( | ||||
| const struct EvaluationContext *eval_ctx, ViewContext *vc, | const struct EvaluationContext *eval_ctx, ViewContext *vc, | ||||
| BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) | Base **r_base, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) | ||||
| { | { | ||||
| BMEditMesh *em = vc->em; | BMEditMesh *em = vc->em; | ||||
| static short mval_prev[2] = {-1, -1}; | static short mval_prev[2] = {-1, -1}; | ||||
| /* only cycle while the mouse remains still */ | /* only cycle while the mouse remains still */ | ||||
| const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1])); | const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1])); | ||||
| const float dist_init = ED_view3d_select_dist_px(); | const float dist_init = ED_view3d_select_dist_px(); | ||||
| /* since edges select lines, we give dots advantage of ~20 pix */ | /* since edges select lines, we give dots advantage of ~20 pix */ | ||||
| const float dist_margin = (dist_init / 2); | const float dist_margin = (dist_init / 2); | ||||
| float dist = dist_init; | float dist = dist_init; | ||||
| BMFace *efa_zbuf = NULL; | BMFace *efa_zbuf = NULL; | ||||
| BMEdge *eed_zbuf = NULL; | BMEdge *eed_zbuf = NULL; | ||||
| BMVert *eve = NULL; | BMVert *eve = NULL; | ||||
| BMEdge *eed = NULL; | BMEdge *eed = NULL; | ||||
| BMFace *efa = NULL; | BMFace *efa = NULL; | ||||
| uint bases_len = 0; | |||||
| Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( | |||||
| eval_ctx->view_layer, &bases_len); | |||||
| /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ | /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ | ||||
| ED_view3d_backbuf_validate(eval_ctx, vc); | |||||
| if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { | if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { | ||||
| float dist_center = 0.0f; | float dist_center = 0.0f; | ||||
| float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; | float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; | ||||
| efa = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); | |||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | |||||
| Base *base_iter = bases[base_index]; | |||||
| Object *obedit = base_iter->object; | |||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| ED_view3d_backbuf_validate(eval_ctx, vc); | |||||
| BMFace *efa_test = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); | |||||
| if (efa && dist_center_p) { | if (efa && dist_center_p) { | ||||
| dist = min_ff(dist_margin, dist_center); | dist = min_ff(dist_margin, dist_center); | ||||
| } | } | ||||
| if (efa_test) { | |||||
| *r_base = base_iter; | |||||
| efa = efa_test; | |||||
| } | |||||
| } /* bases */ | |||||
| } | } | ||||
| if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { | if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { | ||||
| float dist_center = 0.0f; | float dist_center = 0.0f; | ||||
| float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; | float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; | ||||
| eed = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); | |||||
| for (uint base_index = 0; base_index < bases_len; base_index++) { | |||||
| Base *base_iter = bases[base_index]; | |||||
| Object *obedit = base_iter->object; | |||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| ED_view3d_backbuf_validate(eval_ctx, vc); | |||||
| BMEdge *eed_test = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); | |||||
| if (eed && dist_center_p) { | if (eed && dist_center_p) { | ||||
| dist = min_ff(dist_margin, dist_center); | dist = min_ff(dist_margin, dist_center); | ||||
| } | } | ||||
| if (eed_test) { | |||||
| *r_base = base_iter; | |||||
| eed = eed_test; | |||||
| } | |||||
| } /* bases */ | |||||
| } | } | ||||
| if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { | if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { | ||||
| eve = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle); | for (uint base_index = 0; base_index < bases_len; base_index++) { | ||||
| Base *base_iter = bases[base_index]; | |||||
| Object *obedit = base_iter->object; | |||||
| ED_view3d_viewcontext_init_object(vc, obedit); | |||||
| ED_view3d_backbuf_validate(eval_ctx, vc); | |||||
| BMVert *eve_test = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle); | |||||
| if (eve_test) { | |||||
| *r_base = base_iter; | |||||
| eve = eve_test; | |||||
| } | } | ||||
| } /* bases */ | |||||
| } | |||||
| MEM_SAFE_FREE(bases); | |||||
| /* return only one of 3 pointers, for frontbuffer redraws */ | /* return only one of 3 pointers, for frontbuffer redraws */ | ||||
| if (eve) { | if (eve) { | ||||
| efa = NULL; eed = NULL; | efa = NULL; eed = NULL; | ||||
| } | } | ||||
| else if (eed) { | else if (eed) { | ||||
| efa = NULL; | efa = NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 806 Lines • ▼ Show 20 Lines | void MESH_OT_edgering_select(wmOperatorType *ot) | ||||
| RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); | RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); | ||||
| RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); | RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); | ||||
| RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); | RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); | ||||
| } | } | ||||
| /* ******************** (de)select all operator **************** */ | /* ******************** (de)select all operator **************** */ | ||||
| static int edbm_select_all_exec(bContext *C, wmOperator *op) | static int edbm_select_all_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| int action = RNA_enum_get(op->ptr, "action"); | |||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| if (action == SEL_TOGGLE) { | |||||
| action = SEL_SELECT; | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *obedit = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| const int action = RNA_enum_get(op->ptr, "action"); | if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) { | ||||
| action = SEL_DESELECT; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *obedit = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| switch (action) { | switch (action) { | ||||
| case SEL_TOGGLE: | |||||
| EDBM_select_toggle_all(em); | |||||
| break; | |||||
| case SEL_SELECT: | case SEL_SELECT: | ||||
| EDBM_flag_enable_all(em, BM_ELEM_SELECT); | EDBM_flag_enable_all(em, BM_ELEM_SELECT); | ||||
| break; | break; | ||||
| case SEL_DESELECT: | case SEL_DESELECT: | ||||
| EDBM_flag_disable_all(em, BM_ELEM_SELECT); | EDBM_flag_disable_all(em, BM_ELEM_SELECT); | ||||
| break; | break; | ||||
| case SEL_INVERT: | case SEL_INVERT: | ||||
| EDBM_select_swap(em); | EDBM_select_swap(em); | ||||
| EDBM_selectmode_flush(em); | EDBM_selectmode_flush(em); | ||||
| break; | break; | ||||
| } | } | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | ||||
| } | |||||
| MEM_SAFE_FREE(objects); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void MESH_OT_select_all(wmOperatorType *ot) | void MESH_OT_select_all(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "(De)select All"; | ot->name = "(De)select All"; | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| /* ************************************************** */ | /* ************************************************** */ | ||||
| /* here actual select happens */ | /* here actual select happens */ | ||||
| /* gets called via generic mouse select operator */ | /* gets called via generic mouse select operator */ | ||||
| bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) | bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) | ||||
| { | { | ||||
| EvaluationContext eval_ctx; | EvaluationContext eval_ctx; | ||||
| ViewContext vc; | ViewContext vc; | ||||
| Base *basact = NULL; | |||||
| BMVert *eve = NULL; | BMVert *eve = NULL; | ||||
| BMEdge *eed = NULL; | BMEdge *eed = NULL; | ||||
| BMFace *efa = NULL; | BMFace *efa = NULL; | ||||
| /* setup view context for argument to callbacks */ | /* setup view context for argument to callbacks */ | ||||
| CTX_data_eval_ctx(C, &eval_ctx); | CTX_data_eval_ctx(C, &eval_ctx); | ||||
| em_setup_viewcontext(C, &vc); | em_setup_viewcontext(C, &vc); | ||||
| vc.mval[0] = mval[0]; | vc.mval[0] = mval[0]; | ||||
| vc.mval[1] = mval[1]; | vc.mval[1] = mval[1]; | ||||
| if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa)) { | if (unified_findnearest(&eval_ctx, &vc, &basact, &eve, &eed, &efa)) { | ||||
| ED_view3d_viewcontext_init_object(&vc, basact->object); | |||||
| /* Deselect everything */ | /* Deselect everything */ | ||||
| if (extend == false && deselect == false && toggle == false) | if (extend == false && deselect == false && toggle == false) { | ||||
| EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT); | uint objects_len = 0; | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| eval_ctx.view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob_iter = objects[ob_index]; | |||||
| EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT); | |||||
| if (basact->object != ob_iter) { | |||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (efa) { | if (efa) { | ||||
| if (extend) { | if (extend) { | ||||
| /* set the last selected face */ | /* set the last selected face */ | ||||
| BM_mesh_active_face_set(vc.em->bm, efa); | BM_mesh_active_face_set(vc.em->bm, efa); | ||||
| /* Work-around: deselect first, so we can guarantee it will */ | /* Work-around: deselect first, so we can guarantee it will */ | ||||
| /* be active even if it was already selected */ | /* be active even if it was already selected */ | ||||
| ▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | if (efa) { | ||||
| * currently select update handles redraw. */ | * currently select update handles redraw. */ | ||||
| vc.obedit->actfmap = map; | vc.obedit->actfmap = map; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Changing active object is handy since it allows us to | |||||
| * switch UV layers, vgroups for eg. | |||||
| * | |||||
| * XXX(MULTI_EDIT): Edit-mesh undo currently wont track these changes, | |||||
| * we might need special handling for this case. */ | |||||
| eval_ctx.view_layer->basact = basact; | |||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static void edbm_strip_selections(BMEditMesh *em) | static void edbm_strip_selections(BMEditMesh *em) | ||||
| ▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | else if (selectmode_old == SCE_SELECT_FACE) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* user facing function, does notification */ | /* user facing function, does notification */ | ||||
| bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new, | bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new, | ||||
| const int action, const bool use_extend, const bool use_expand) | const int action, const bool use_extend, const bool use_expand) | ||||
| { | { | ||||
| EvaluationContext eval_ctx; | |||||
| ToolSettings *ts = CTX_data_tool_settings(C); | ToolSettings *ts = CTX_data_tool_settings(C); | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| BMEditMesh *em = NULL; | BMEditMesh *em = NULL; | ||||
| bool ret = false; | bool ret = false; | ||||
| CTX_data_eval_ctx(C, &eval_ctx); | |||||
| if (obedit && obedit->type == OB_MESH) { | if (obedit && obedit->type == OB_MESH) { | ||||
| em = BKE_editmesh_from_object(obedit); | em = BKE_editmesh_from_object(obedit); | ||||
| } | } | ||||
| if (em == NULL) { | if (em == NULL) { | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| bool only_update = false; | |||||
| switch (action) { | switch (action) { | ||||
| case -1: | case -1: | ||||
| /* already set */ | /* already set */ | ||||
| break; | break; | ||||
| case 0: /* disable */ | case 0: /* disable */ | ||||
| /* check we have something to do */ | /* check we have something to do */ | ||||
| if ((em->selectmode & selectmode_new) == 0) { | if ((em->selectmode & selectmode_new) == 0) { | ||||
| return false; | only_update = true; | ||||
| break; | |||||
| } | } | ||||
| em->selectmode &= ~selectmode_new; | em->selectmode &= ~selectmode_new; | ||||
| break; | break; | ||||
| case 1: /* enable */ | case 1: /* enable */ | ||||
| /* check we have something to do */ | /* check we have something to do */ | ||||
| if ((em->selectmode & selectmode_new) != 0) { | if ((em->selectmode & selectmode_new) != 0) { | ||||
| return false; | only_update = true; | ||||
| break; | |||||
| } | } | ||||
| em->selectmode |= selectmode_new; | em->selectmode |= selectmode_new; | ||||
| break; | break; | ||||
| case 2: /* toggle */ | case 2: /* toggle */ | ||||
| /* can't disable this flag if its the only one set */ | /* can't disable this flag if its the only one set */ | ||||
| if (em->selectmode == selectmode_new) { | if (em->selectmode == selectmode_new) { | ||||
| return false; | only_update = true; | ||||
| break; | |||||
| } | } | ||||
| em->selectmode ^= selectmode_new; | em->selectmode ^= selectmode_new; | ||||
| break; | break; | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| break; | break; | ||||
| } | } | ||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| eval_ctx.view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob_iter = objects[ob_index]; | |||||
| BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); | |||||
| if (em_iter != em) { | |||||
| em_iter->selectmode = em->selectmode; | |||||
| } | |||||
| } | |||||
| if (only_update) { | |||||
| MEM_SAFE_FREE(objects); | |||||
| return false; | |||||
| } | |||||
| if (use_extend == 0 || em->selectmode == 0) { | if (use_extend == 0 || em->selectmode == 0) { | ||||
| if (use_expand) { | if (use_expand) { | ||||
| const short selmode_max = highest_order_bit_s(ts->selectmode); | const short selmode_max = highest_order_bit_s(ts->selectmode); | ||||
| EDBM_selectmode_convert(em, selmode_max, selectmode_new); | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| Object *ob_iter = objects[ob_index]; | |||||
| BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); | |||||
| EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| switch (selectmode_new) { | switch (selectmode_new) { | ||||
| case SCE_SELECT_VERTEX: | case SCE_SELECT_VERTEX: | ||||
| if (use_extend == 0 || em->selectmode == 0) { | if (use_extend == 0 || em->selectmode == 0) { | ||||
| em->selectmode = SCE_SELECT_VERTEX; | em->selectmode = SCE_SELECT_VERTEX; | ||||
| } | } | ||||
| ts->selectmode = em->selectmode; | |||||
| EDBM_selectmode_set(em); | |||||
| ret = true; | ret = true; | ||||
| break; | break; | ||||
| case SCE_SELECT_EDGE: | case SCE_SELECT_EDGE: | ||||
| if (use_extend == 0 || em->selectmode == 0) { | if (use_extend == 0 || em->selectmode == 0) { | ||||
| em->selectmode = SCE_SELECT_EDGE; | em->selectmode = SCE_SELECT_EDGE; | ||||
| } | } | ||||
| ts->selectmode = em->selectmode; | |||||
| EDBM_selectmode_set(em); | |||||
| ret = true; | ret = true; | ||||
| break; | break; | ||||
| case SCE_SELECT_FACE: | case SCE_SELECT_FACE: | ||||
| if (use_extend == 0 || em->selectmode == 0) { | if (use_extend == 0 || em->selectmode == 0) { | ||||
| em->selectmode = SCE_SELECT_FACE; | em->selectmode = SCE_SELECT_FACE; | ||||
| } | } | ||||
| ts->selectmode = em->selectmode; | |||||
| EDBM_selectmode_set(em); | |||||
| ret = true; | ret = true; | ||||
| break; | break; | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| break; | break; | ||||
| } | } | ||||
| if (ret == true) { | if (ret == true) { | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | ts->selectmode = em->selectmode; | ||||
| em = NULL; | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob_iter = objects[ob_index]; | |||||
| BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); | |||||
| EDBM_selectmode_set(em_iter); | |||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); | |||||
| } | |||||
| WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); | WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); | ||||
| } | } | ||||
| MEM_SAFE_FREE(objects); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| /** | /** | ||||
| * Use to disable a selectmode if its enabled, Using another mode as a fallback | * Use to disable a selectmode if its enabled, Using another mode as a fallback | ||||
| * if the disabled mode is the only mode set. | * if the disabled mode is the only mode set. | ||||
| * | * | ||||
| * \return true if the mode is changed. | * \return true if the mode is changed. | ||||
| ▲ Show 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit) | ||||
| if (delimit) { | if (delimit) { | ||||
| select_linked_delimit_end(em); | select_linked_delimit_end(em); | ||||
| } | } | ||||
| } | } | ||||
| static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | |||||
| EvaluationContext eval_ctx; | EvaluationContext eval_ctx; | ||||
| ViewContext vc; | ViewContext vc; | ||||
| BMEditMesh *em; | Base *basact = NULL; | ||||
| BMesh *bm; | |||||
| BMVert *eve; | BMVert *eve; | ||||
| BMEdge *eed; | BMEdge *eed; | ||||
| BMFace *efa; | BMFace *efa; | ||||
| const bool sel = !RNA_boolean_get(op->ptr, "deselect"); | const bool sel = !RNA_boolean_get(op->ptr, "deselect"); | ||||
| int index; | int index; | ||||
| if (RNA_struct_property_is_set(op->ptr, "index")) { | if (RNA_struct_property_is_set(op->ptr, "index")) { | ||||
| return edbm_select_linked_pick_exec(C, op); | return edbm_select_linked_pick_exec(C, op); | ||||
| } | } | ||||
| /* unified_finednearest needs ogl */ | /* unified_finednearest needs ogl */ | ||||
| view3d_operator_needs_opengl(C); | view3d_operator_needs_opengl(C); | ||||
| /* setup view context for argument to callbacks */ | /* setup view context for argument to callbacks */ | ||||
| CTX_data_eval_ctx(C, &eval_ctx); | CTX_data_eval_ctx(C, &eval_ctx); | ||||
| em_setup_viewcontext(C, &vc); | em_setup_viewcontext(C, &vc); | ||||
| em = vc.em; | |||||
| bm = em->bm; | |||||
| if (bm->totedge == 0) { | { | ||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| eval_ctx.view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| bool has_edges = false; | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *ob_iter = objects[ob_index]; | |||||
| ED_view3d_viewcontext_init_object(&vc, ob_iter); | |||||
| if (vc.em->bm->totedge) { | |||||
| has_edges = true; | |||||
| } | |||||
| } | |||||
| MEM_SAFE_FREE(objects); | |||||
| if (has_edges == false) { | |||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| } | |||||
| vc.mval[0] = event->mval[0]; | vc.mval[0] = event->mval[0]; | ||||
| vc.mval[1] = event->mval[1]; | vc.mval[1] = event->mval[1]; | ||||
| /* return warning! */ | /* return warning! */ | ||||
| if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) { | if (unified_findnearest(&eval_ctx, &vc, &basact, &eve, &eed, &efa) == 0) { | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| ED_view3d_viewcontext_init_object(&vc, basact->object); | |||||
| BMEditMesh *em = vc.em; | |||||
| BMesh *bm = em->bm; | |||||
| #ifdef USE_LINKED_SELECT_DEFAULT_HACK | #ifdef USE_LINKED_SELECT_DEFAULT_HACK | ||||
| int delimit = select_linked_delimit_default_from_op(op, em); | int delimit = select_linked_delimit_default_from_op(op, vc.em); | ||||
| #else | #else | ||||
| int delimit = RNA_enum_get(op->ptr, "delimit"); | int delimit = RNA_enum_get(op->ptr, "delimit"); | ||||
| #endif | #endif | ||||
| BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa); | BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa); | ||||
| edbm_select_linked_pick_ex(em, ele, sel, delimit); | edbm_select_linked_pick_ex(em, ele, sel, delimit); | ||||
| /* to support redo */ | /* to support redo */ | ||||
| BM_mesh_elem_index_ensure(bm, ele->head.htype); | BM_mesh_elem_index_ensure(bm, ele->head.htype); | ||||
| index = EDBM_elem_to_index_any(em, ele); | index = EDBM_elem_to_index_any(em, ele); | ||||
| /* TODO(MULTI_EDIT), index doesn't know which object, | |||||
| * index selections isn't very common. */ | |||||
| RNA_int_set(op->ptr, "index", index); | RNA_int_set(op->ptr, "index", index); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) | static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| ▲ Show 20 Lines • Show All 1,242 Lines • Show Last 20 Lines | |||||