diff options
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r-- | source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 41 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife_project.c | 46 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_preselect_edgering.c | 28 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 28 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 262 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_undo.c | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_utils.c | 5 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.c | 11 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_mirror.c | 5 |
11 files changed, 241 insertions, 198 deletions
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 38d530ba911..1af489b60ce 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -468,7 +468,9 @@ void MESH_GGT_spin(struct wmGizmoGroupType *gzgt) gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; gzgt->setup = gizmo_mesh_spin_init_setup; - gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + /* This works well with right click selection but overrides left-mouse selection + * when clicking which is needed to create a full 360 degree revolution, see: T89912. */ + // gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; gzgt->refresh = gizmo_mesh_spin_init_refresh; gzgt->message_subscribe = gizmo_mesh_spin_init_message_subscribe; gzgt->draw_prepare = gizmo_mesh_spin_init_draw_prepare; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 73f6a3f3238..3e3593d18fd 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2630,24 +2630,24 @@ static void knife_init_colors(KnifeColors *colors) } /* called when modal loop selection gets set up... */ -static void knifetool_init(bContext *C, +static void knifetool_init(ViewContext *vc, KnifeTool_OpData *kcd, const bool only_select, const bool cut_through, const bool is_interactive) { - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); + kcd->vc = *vc; + + Scene *scene = vc->scene; + Object *obedit = vc->obedit; /* assign the drawing handle for drawing preview line... */ kcd->scene = scene; kcd->ob = obedit; - kcd->region = CTX_wm_region(C); + kcd->region = vc->region; invert_m4_m4_safe_ortho(kcd->ob_imat, kcd->ob->obmat); - em_setup_viewcontext(C, &kcd->vc); - kcd->em = BKE_editmesh_from_object(kcd->ob); /* cut all the way through the mesh if use_occlude_geometry button not pushed */ @@ -2694,14 +2694,14 @@ static void knifetool_init(bContext *C, } /* called when modal loop selection is done... */ -static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd) +static void knifetool_exit_ex(KnifeTool_OpData *kcd) { if (!kcd) { return; } if (kcd->is_interactive) { - WM_cursor_modal_restore(CTX_wm_window(C)); + WM_cursor_modal_restore(kcd->vc.win); /* deactivate the extra drawing stuff in 3D-View */ ED_region_draw_cb_exit(kcd->region->type, kcd->draw_handle); @@ -2735,10 +2735,10 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd) /* destroy kcd itself */ MEM_freeN(kcd); } -static void knifetool_exit(bContext *C, wmOperator *op) +static void knifetool_exit(wmOperator *op) { KnifeTool_OpData *kcd = op->customdata; - knifetool_exit_ex(C, kcd); + knifetool_exit_ex(kcd); op->customdata = NULL; } @@ -2827,10 +2827,10 @@ static void knifetool_finish(wmOperator *op) /** \name Operator (#MESH_OT_knife_tool) * \{ */ -static void knifetool_cancel(bContext *C, wmOperator *op) +static void knifetool_cancel(bContext *UNUSED(C), wmOperator *op) { /* this is just a wrapper around exit() */ - knifetool_exit(C, op); + knifetool_exit(op); } wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) @@ -2872,7 +2872,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) bool do_refresh = false; if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) { - knifetool_exit(C, op); + knifetool_exit(op); ED_workspace_status_text(C, NULL); return OPERATOR_FINISHED; } @@ -2893,7 +2893,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) /* finish */ ED_region_tag_redraw(kcd->region); - knifetool_exit(C, op); + knifetool_exit(op); ED_workspace_status_text(C, NULL); return OPERATOR_CANCELLED; @@ -2902,7 +2902,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_region_tag_redraw(kcd->region); knifetool_finish(op); - knifetool_exit(C, op); + knifetool_exit(op); ED_workspace_status_text(C, NULL); return OPERATOR_FINISHED; @@ -3066,8 +3066,11 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry"); const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input"); + ViewContext vc; KnifeTool_OpData *kcd; + em_setup_viewcontext(C, &vc); + if (only_select) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3080,7 +3083,7 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* alloc new customdata */ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__); - knifetool_init(C, kcd, only_select, cut_through, true); + knifetool_init(&vc, kcd, only_select, cut_through, true); op->flag |= OP_IS_MODAL_CURSOR_REGION; @@ -3165,7 +3168,7 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2]) /** * \param use_tag: When set, tag all faces inside the polylines. */ -void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through) +void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_through) { KnifeTool_OpData *kcd; @@ -3176,7 +3179,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__); - knifetool_init(C, kcd, only_select, cut_through, is_interactive); + knifetool_init(vc, kcd, only_select, cut_through, is_interactive); kcd->ignore_edge_snapping = true; kcd->ignore_vert_snapping = true; @@ -3313,7 +3316,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug #undef F_ISECT_SET_OUTSIDE } - knifetool_exit_ex(C, kcd); + knifetool_exit_ex(kcd); kcd = NULL; } } diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 09b17acf56d..669a09b3fd3 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -32,6 +32,8 @@ #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" +#include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_object.h" @@ -114,7 +116,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, BKE_nurbList_free(&nurbslist); if (me_eval_needs_free) { - BKE_mesh_free((struct Mesh *)me_eval); + BKE_id_free(NULL, (ID *)me_eval); } } @@ -124,21 +126,39 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, static int knifeproject_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); const bool cut_through = RNA_boolean_get(op->ptr, "cut_through"); LinkNode *polys = NULL; CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - if (ob != obedit) { - polys = knifeproject_poly_from_object(C, scene, ob, polys); + if (BKE_object_is_in_editmode(ob)) { + continue; } + polys = knifeproject_poly_from_object(C, scene, ob, polys); } CTX_DATA_END; - if (polys) { - EDBM_mesh_knife(C, polys, true, cut_through); + if (polys == NULL) { + BKE_report(op->reports, + RPT_ERROR, + "No other selected objects have wire or boundary edges to use for projection"); + return OPERATOR_CANCELLED; + } + + ViewContext vc; + em_setup_viewcontext(C, &vc); + + /* TODO: Ideally meshes would occlude each other, currently they don't + * since each knife-project runs as a separate operation. */ + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + vc.view_layer, vc.v3d, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ED_view3d_viewcontext_init_object(&vc, obedit); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + EDBM_mesh_knife(&vc, polys, true, cut_through); /* select only tagged faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); @@ -148,16 +168,12 @@ static int knifeproject_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); BM_mesh_select_mode_flush(em->bm); - - BLI_linklist_freeN(polys); - - return OPERATOR_FINISHED; } + MEM_freeN(objects); + + BLI_linklist_freeN(polys); - BKE_report(op->reports, - RPT_ERROR, - "No other selected objects have wire or boundary edges to use for projection"); - return OPERATOR_CANCELLED; + return OPERATOR_FINISHED; } void MESH_OT_knife_project(wmOperatorType *ot) diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c index 43e36957dc9..c58f29917b1 100644 --- a/source/blender/editors/mesh/editmesh_preselect_edgering.c +++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c @@ -20,6 +20,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_userdef_types.h" + #include "BLI_math.h" #include "BLI_stack.h" @@ -160,16 +162,21 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } GPU_depth_test(GPU_DEPTH_NONE); + GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); GPU_matrix_mul(matrix); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColor3(TH_GIZMO_PRIMARY); - if (psel->edges_len > 0) { + float viewport[4]; + GPU_viewport_size_get_f(viewport); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniform2fv("viewportSize", &viewport[2]); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + immUniform1f("lineWidth", U.pixelsize); immBegin(GPU_PRIM_LINES, psel->edges_len * 2); for (int i = 0; i < psel->edges_len; i++) { @@ -178,10 +185,18 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); } if (psel->verts_len > 0) { - GPU_point_size(3.0f); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + + /* Same size as an edit mode vertex */ + immUniform1f("size", + 2.0 * U.pixelsize * + (max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f))); immBegin(GPU_PRIM_POINTS, psel->verts_len); @@ -190,14 +205,15 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); + GPU_program_point_size(false); } - immUnbindProgram(); - GPU_matrix_pop(); /* Reset default */ GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + GPU_blend(GPU_BLEND_NONE); } static void view3d_preselect_mesh_edgering_update_verts_from_edge( diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 830c9abb41e..8e38d41f971 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1860,10 +1860,16 @@ void MESH_OT_loop_select(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend 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, "ring", 0, "Select Ring", "Select ring"); + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } void MESH_OT_edgering_select(wmOperatorType *ot) @@ -1880,10 +1886,16 @@ void MESH_OT_edgering_select(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend 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, "ring", 1, "Select Ring", "Select ring"); + /* Properties. */ + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 41a9f426798..956658bd2b7 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -467,40 +467,50 @@ static int edbm_delete_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); const int type = RNA_enum_get(op->ptr, "type"); - BM_custom_loop_normals_to_vector_layer(em->bm); - switch (type) { case MESH_DELETE_VERT: /* Erase Vertices */ - if (!(em->bm->totvertsel && - EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS))) { + if (em->bm->totvertsel == 0) { + continue; + } + BM_custom_loop_normals_to_vector_layer(em->bm); + if (!EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)) { continue; } break; case MESH_DELETE_EDGE: /* Erase Edges */ - if (!(em->bm->totedgesel && - EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES))) { + if (em->bm->totedgesel == 0) { + continue; + } + BM_custom_loop_normals_to_vector_layer(em->bm); + if (!EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES)) { continue; } break; case MESH_DELETE_FACE: /* Erase Faces */ - if (!(em->bm->totfacesel && - EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES))) { + if (em->bm->totfacesel == 0) { + continue; + } + BM_custom_loop_normals_to_vector_layer(em->bm); + if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES)) { continue; } break; - case MESH_DELETE_EDGE_FACE: - /* Edges and Faces */ - if (!((em->bm->totedgesel || em->bm->totfacesel) && - EDBM_op_callf( - em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES))) { + case MESH_DELETE_EDGE_FACE: /* Edges and Faces */ + if ((em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) { + continue; + } + BM_custom_loop_normals_to_vector_layer(em->bm); + if (!EDBM_op_callf( + em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES)) { continue; } break; - case MESH_DELETE_ONLY_FACE: - /* Only faces. */ - if (!(em->bm->totfacesel && - EDBM_op_callf( - em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES))) { + case MESH_DELETE_ONLY_FACE: /* Only faces. */ + if (em->bm->totfacesel == 0) { + continue; + } + BM_custom_loop_normals_to_vector_layer(em->bm); + if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES)) { continue; } break; @@ -2183,6 +2193,61 @@ static bool flip_custom_normals(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr) /* -------------------------------------------------------------------- */ /** \name Flip Normals Operator * \{ */ + +static void edbm_flip_normals_custom_loop_normals(Object *obedit, BMEditMesh *em) +{ + if (!CustomData_has_layer(&em->bm->ldata, CD_CUSTOMLOOPNORMAL)) { + return; + } + + /* The mesh has custom normal data, flip them. */ + BMesh *bm = em->bm; + + BM_lnorspace_update(bm); + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + negate_v3(lnor_ed->nloc); + + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data); + } + BM_loop_normal_editdata_array_free(lnors_ed_arr); + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); +} + +static void edbm_flip_normals_face_winding(wmOperator *op, Object *obedit, BMEditMesh *em) +{ + + bool has_flipped_faces = false; + + /* See if we have any custom normals to flip. */ + BMLoopNorEditDataArray *lnors_ed_arr = flip_custom_normals_init_data(em->bm); + + if (EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) { + has_flipped_faces = true; + } + + if (flip_custom_normals(em->bm, lnors_ed_arr) || has_flipped_faces) { + EDBM_update(obedit->data, + &(const struct EDBMUpdate_Params){ + .calc_looptri = true, + .calc_normals = false, + .is_destructive = false, + }); + } + + if (lnors_ed_arr != NULL) { + BM_loop_normal_editdata_array_free(lnors_ed_arr); + } +} + static int edbm_flip_normals_exec(bContext *C, wmOperator *op) { const bool only_clnors = RNA_boolean_get(op->ptr, "only_clnors"); @@ -2197,56 +2262,16 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); if (only_clnors) { - if (CustomData_has_layer(&em->bm->ldata, CD_CUSTOMLOOPNORMAL)) { - /* The mesh has custom normal data, flip them. */ - BMesh *bm = em->bm; - - BM_lnorspace_update(bm); - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); - BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; - - for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { - negate_v3(lnor_ed->nloc); - - BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], - lnor_ed->nloc, - lnor_ed->clnors_data); - } - BM_loop_normal_editdata_array_free(lnors_ed_arr); - EDBM_update(obedit->data, - &(const struct EDBMUpdate_Params){ - .calc_looptri = true, - .calc_normals = false, - .is_destructive = false, - }); + if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) { + continue; } - continue; - } - - if (em->bm->totfacesel == 0) { - continue; - } - - bool has_flipped_faces = false; - - /* See if we have any custom normals to flip. */ - BMLoopNorEditDataArray *lnors_ed_arr = flip_custom_normals_init_data(em->bm); - - if (EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) { - has_flipped_faces = true; - } - - if (flip_custom_normals(em->bm, lnors_ed_arr) || has_flipped_faces) { - EDBM_update(obedit->data, - &(const struct EDBMUpdate_Params){ - .calc_looptri = true, - .calc_normals = false, - .is_destructive = false, - }); + edbm_flip_normals_custom_loop_normals(obedit, em); } - - if (lnors_ed_arr != NULL) { - BM_loop_normal_editdata_array_free(lnors_ed_arr); + else { + if (em->bm->totfacesel == 0) { + continue; + } + edbm_flip_normals_face_winding(op, obedit, em); } } @@ -2748,9 +2773,6 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { - BMIter fiter; - BMFace *f; - int tot_invalid = 0; int tot_unselected = 0; ViewLayer *view_layer = CTX_data_view_layer(C); @@ -2777,22 +2799,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) if (em->bm->totvertsel == 0) { tot_unselected++; - tot_invalid++; - continue; - } - - bool is_invalid = false; - /* Check if select faces are triangles. */ - BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - if (f->len > 4) { - tot_invalid++; - is_invalid = true; - break; - } - } - } - if (is_invalid) { continue; } @@ -2841,10 +2847,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_WARNING, "No selected vertex"); return OPERATOR_CANCELLED; } - if (tot_invalid == objects_len) { - BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads"); - return OPERATOR_CANCELLED; - } return OPERATOR_FINISHED; } @@ -4666,7 +4668,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const int type = RNA_enum_get(op->ptr, "type"); - int retval = 0; + bool changed_multi = false; if (ED_operator_editmesh(C)) { uint bases_len = 0; @@ -4676,6 +4678,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) for (uint bs_index = 0; bs_index < bases_len; bs_index++) { Base *base = bases[bs_index]; BMEditMesh *em = BKE_editmesh_from_object(base->object); + bool changed = false; if (type == 0) { if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) { @@ -4690,20 +4693,20 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) /* editmode separate */ switch (type) { case MESH_SEPARATE_SELECTED: - retval = mesh_separate_selected(bmain, scene, view_layer, base, em->bm); + changed = mesh_separate_selected(bmain, scene, view_layer, base, em->bm); break; case MESH_SEPARATE_MATERIAL: - retval = mesh_separate_material(bmain, scene, view_layer, base, em->bm); + changed = mesh_separate_material(bmain, scene, view_layer, base, em->bm); break; case MESH_SEPARATE_LOOSE: - retval = mesh_separate_loose(bmain, scene, view_layer, base, em->bm); + changed = mesh_separate_loose(bmain, scene, view_layer, base, em->bm); break; default: BLI_assert(0); break; } - if (retval) { + if (changed) { EDBM_update(base->object->data, &(const struct EDBMUpdate_Params){ .calc_looptri = true, @@ -4711,6 +4714,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) .is_destructive = true, }); } + changed_multi |= changed; } MEM_freeN(bases); } @@ -4727,7 +4731,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) Mesh *me = ob->data; if (!ID_IS_LINKED(me)) { BMesh *bm_old = NULL; - int retval_iter = 0; + bool changed = false; bm_old = BM_mesh_create(&bm_mesh_allocsize_default, &((struct BMeshCreateParams){ @@ -4738,17 +4742,17 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) switch (type) { case MESH_SEPARATE_MATERIAL: - retval_iter = mesh_separate_material(bmain, scene, view_layer, base_iter, bm_old); + changed = mesh_separate_material(bmain, scene, view_layer, base_iter, bm_old); break; case MESH_SEPARATE_LOOSE: - retval_iter = mesh_separate_loose(bmain, scene, view_layer, base_iter, bm_old); + changed = mesh_separate_loose(bmain, scene, view_layer, base_iter, bm_old); break; default: BLI_assert(0); break; } - if (retval_iter) { + if (changed) { BM_mesh_bm_to_me(bmain, bm_old, me, @@ -4762,14 +4766,14 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) BM_mesh_free(bm_old); - retval |= retval_iter; + changed_multi |= changed; } } } CTX_DATA_END; } - if (retval) { + if (changed_multi) { /* delay depsgraph recalc until all objects are duplicated */ DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); @@ -5572,24 +5576,24 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( view_layer, CTX_wm_view3d(C), &objects_len); - bool is_face_pair; + const bool do_seam = RNA_boolean_get(op->ptr, "seam"); + const bool do_sharp = RNA_boolean_get(op->ptr, "sharp"); + const bool do_uvs = RNA_boolean_get(op->ptr, "uvs"); + const bool do_vcols = RNA_boolean_get(op->ptr, "vcols"); + const bool do_materials = RNA_boolean_get(op->ptr, "materials"); + float angle_face_threshold, angle_shape_threshold; + bool is_face_pair; { int totelem_sel[3]; EDBM_mesh_stats_multi(objects, objects_len, NULL, totelem_sel); is_face_pair = (totelem_sel[2] == 2); } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - bool do_seam, do_sharp, do_uvs, do_vcols, do_materials; - float angle_face_threshold, angle_shape_threshold; + /* When joining exactly 2 faces, no limit. + * this is useful for one off joins while editing. */ + { PropertyRNA *prop; - - /* When joining exactly 2 faces, no limit. - * this is useful for one off joins while editing. */ prop = RNA_struct_find_property(op->ptr, "face_threshold"); if (is_face_pair && (RNA_property_is_set(op->ptr, prop) == false)) { angle_face_threshold = DEG2RADF(180.0f); @@ -5605,12 +5609,15 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) else { angle_shape_threshold = RNA_property_float_get(op->ptr, prop); } + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); - do_seam = RNA_boolean_get(op->ptr, "seam"); - do_sharp = RNA_boolean_get(op->ptr, "sharp"); - do_uvs = RNA_boolean_get(op->ptr, "uvs"); - do_vcols = RNA_boolean_get(op->ptr, "vcols"); - do_materials = RNA_boolean_get(op->ptr, "materials"); + if (em->bm->totfacesel == 0) { + continue; + } BM_custom_loop_normals_to_vector_layer(em->bm); @@ -6335,7 +6342,7 @@ static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) BMesh *bm = em->bm; if (!EDBM_op_callf(em, op, "dissolve_degenerate edges=%he dist=%f", BM_ELEM_SELECT, thresh)) { - return OPERATOR_CANCELLED; + continue; } /* tricky to maintain correct selection here, so just flush up from verts */ @@ -8620,7 +8627,7 @@ static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent * RNA_enum_set(op->ptr, "mode", mode); } - /* Only handle mousemove event in case we are in mouse mode. */ + /* Only handle mouse-move event in case we are in mouse mode. */ if (event->type == MOUSEMOVE || force_mousemove) { if (mode == EDBM_CLNOR_POINTTO_MODE_MOUSE) { ARegion *region = CTX_wm_region(C); @@ -9527,6 +9534,10 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; + if (bm->totfacesel == 0) { + continue; + } + BMFace *f; BMVert *v; BMEdge *e; @@ -9538,18 +9549,11 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) BKE_editmesh_ensure_autosmooth(em, obedit->data); BKE_editmesh_lnorspace_update(em, obedit->data); - float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__); - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - const int v_index = BM_elem_index_get(v); - add_v3_v3(vnors[v_index], f->no); - } - } - } - for (int i = 0; i < bm->totvert; i++) { - if (!is_zero_v3(vnors[i]) && normalize_v3(vnors[i]) < CLNORS_VALID_VEC_LEN) { - zero_v3(vnors[i]); + float(*vnors)[3] = MEM_mallocN(sizeof(*vnors) * bm->totvert, __func__); + { + int v_index; + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, v_index) { + BM_vert_calc_normal_ex(v, BM_ELEM_SELECT, vnors[v_index]); } } diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index fc9e1aa8b1a..f52cd94b8dc 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -755,11 +755,11 @@ static void undomesh_free_data(UndoMesh *um) #endif if (me->key) { - BKE_key_free(me->key); + BKE_key_free_data(me->key); MEM_freeN(me->key); } - BKE_mesh_free(me); + BKE_mesh_free_data_for_undo(me); } static Object *editmesh_object_from_context(bContext *C) diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 85c646d689c..c6a8e771362 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -355,10 +355,7 @@ void EDBM_mesh_clear(BMEditMesh *em) /* free tessellation data */ em->tottri = 0; - if (em->looptris) { - MEM_freeN(em->looptris); - em->looptris = NULL; - } + MEM_SAFE_FREE(em->looptris); } void EDBM_mesh_load(Main *bmain, Object *ob) diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index b2379610f65..c075d2550cb 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -1007,15 +1007,8 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator if (me->flag & ME_AUTOSMOOTH) { float(*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__); - BKE_mesh_calc_normals_poly(me->mvert, - NULL, - me->totvert, - me->mloop, - me->mpoly, - me->totloop, - me->totpoly, - polynors, - true); + BKE_mesh_calc_normals_poly( + me->mvert, me->totvert, me->mloop, me->totloop, me->mpoly, me->totpoly, polynors); BKE_edges_sharp_from_angle_set(me->mvert, me->totvert, diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index f25317e8e85..03c99e40d1e 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -150,7 +150,10 @@ void MESH_OT_face_split_by_edges(struct wmOperatorType *ot); /* *** editmesh_knife.c *** */ void MESH_OT_knife_tool(struct wmOperatorType *ot); void MESH_OT_knife_project(struct wmOperatorType *ot); -void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys, bool use_tag, bool cut_through); +void EDBM_mesh_knife(struct ViewContext *vc, + struct LinkNode *polys, + bool use_tag, + bool cut_through); struct wmKeyMap *knifetool_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 5eb69aab48b..1a3e6a59588 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -365,10 +365,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store) { - if (mesh_topo_store->index_lookup) { - MEM_freeN(mesh_topo_store->index_lookup); - } - mesh_topo_store->index_lookup = NULL; + MEM_SAFE_FREE(mesh_topo_store->index_lookup); mesh_topo_store->prev_vert_tot = -1; mesh_topo_store->prev_edge_tot = -1; } |