Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_tools.c
| Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| #include "mesh_intern.h" /* own include */ | #include "mesh_intern.h" /* own include */ | ||||
| #include "bmesh_tools.h" | #include "bmesh_tools.h" | ||||
| #define USE_FACE_CREATE_SEL_EXTEND | #define USE_FACE_CREATE_SEL_EXTEND | ||||
| static int edbm_subdivide_exec(bContext *C, wmOperator *op) | static int edbm_subdivide_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| /* no indent for diff noise. */ | |||||
| 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 cuts = RNA_int_get(op->ptr, "number_cuts"); | const int cuts = RNA_int_get(op->ptr, "number_cuts"); | ||||
| float smooth = RNA_float_get(op->ptr, "smoothness"); | float smooth = RNA_float_get(op->ptr, "smoothness"); | ||||
| const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f; | const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f; | ||||
| const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal"); | const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal"); | ||||
| if (RNA_boolean_get(op->ptr, "quadtri") && | if (RNA_boolean_get(op->ptr, "quadtri") && | ||||
| RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) | RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) | ||||
| { | { | ||||
| RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT); | RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT); | ||||
| } | } | ||||
| BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, | BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, | ||||
| smooth, SUBD_FALLOFF_LIN, false, | smooth, SUBD_FALLOFF_LIN, false, | ||||
| fractal, along_normal, | fractal, along_normal, | ||||
| cuts, | cuts, | ||||
| SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), | SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), | ||||
| RNA_boolean_get(op->ptr, "quadtri"), true, false, | RNA_boolean_get(op->ptr, "quadtri"), true, false, | ||||
| RNA_int_get(op->ptr, "seed")); | RNA_int_get(op->ptr, "seed")); | ||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| } | |||||
| MEM_SAFE_FREE(objects); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| /* Note, these values must match delete_mesh() event values */ | /* Note, these values must match delete_mesh() event values */ | ||||
| static const EnumPropertyItem prop_mesh_cornervert_types[] = { | static const EnumPropertyItem prop_mesh_cornervert_types[] = { | ||||
| {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, | {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, | ||||
| {SUBD_CORNER_PATH, "PATH", 0, "Path", ""}, | {SUBD_CORNER_PATH, "PATH", 0, "Path", ""}, | ||||
| {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""}, | {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""}, | ||||
| ▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | |||||
| enum { | enum { | ||||
| MESH_DELETE_VERT = 0, | MESH_DELETE_VERT = 0, | ||||
| MESH_DELETE_EDGE = 1, | MESH_DELETE_EDGE = 1, | ||||
| MESH_DELETE_FACE = 2, | MESH_DELETE_FACE = 2, | ||||
| MESH_DELETE_EDGE_FACE = 3, | MESH_DELETE_EDGE_FACE = 3, | ||||
| MESH_DELETE_ONLY_FACE = 4, | MESH_DELETE_ONLY_FACE = 4, | ||||
| }; | }; | ||||
| static void edbm_report_delete_info(ReportList *reports, BMesh *bm, const int totelem[3]) | static void edbm_report_delete_info(ReportList *reports, const int totelem_old[3], const int totelem_new[3]) | ||||
| { | { | ||||
| BKE_reportf(reports, RPT_INFO, | BKE_reportf(reports, RPT_INFO, | ||||
| "Removed: %d vertices, %d edges, %d faces", | "Removed: %d vertices, %d edges, %d faces", | ||||
| totelem[0] - bm->totvert, totelem[1] - bm->totedge, totelem[2] - bm->totface); | totelem_old[0] - totelem_new[0], totelem_old[1] - totelem_new[1], totelem_old[2] - totelem_new[2]); | ||||
| } | } | ||||
| static int edbm_delete_exec(bContext *C, wmOperator *op) | static int edbm_delete_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| 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 type = RNA_enum_get(op->ptr, "type"); | const int type = RNA_enum_get(op->ptr, "type"); | ||||
| switch (type) { | switch (type) { | ||||
| case MESH_DELETE_VERT: | case MESH_DELETE_VERT: | ||||
| if (!EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)) /* Erase Vertices */ | if (!EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS)) /* Erase Vertices */ | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| break; | break; | ||||
| Show All 18 Lines | switch (type) { | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| break; | break; | ||||
| } | } | ||||
| EDBM_flag_disable_all(em, BM_ELEM_SELECT); | EDBM_flag_disable_all(em, BM_ELEM_SELECT); | ||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| } /* objects */ | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void MESH_OT_delete(wmOperatorType *ot) | void MESH_OT_delete(wmOperatorType *ot) | ||||
| { | { | ||||
| static const EnumPropertyItem prop_mesh_delete_types[] = { | static const EnumPropertyItem prop_mesh_delete_types[] = { | ||||
| {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""}, | {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""}, | ||||
| {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""}, | {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""}, | ||||
| Show All 34 Lines | do { | ||||
| } | } | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| return true; | return true; | ||||
| } | } | ||||
| static int edbm_delete_loose_exec(bContext *C, wmOperator *op) | static int edbm_delete_loose_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | int totelem_old_sel[3]; | ||||
| BMesh *bm = em->bm; | int totelem_old[3]; | ||||
| BMIter iter; | |||||
| const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && bm->totvertsel); | uint objects_len = 0; | ||||
| const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && bm->totedgesel); | Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | ||||
| const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && bm->totfacesel); | view_layer, &objects_len, | ||||
| .no_dupe_data = true); | |||||
| EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel); | |||||
| const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]); | |||||
| const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]); | |||||
| const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]); | |||||
| const int totelem[3] = {bm->totvert, bm->totedge, bm->totface}; | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| Object *obedit = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| BMesh *bm = em->bm; | |||||
| BMIter iter; | |||||
| BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); | BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); | ||||
| if (use_faces) { | if (use_faces) { | ||||
| BMFace *f; | BMFace *f; | ||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | ||||
| if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { | if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { | ||||
| Show All 27 Lines | if (use_verts) { | ||||
| BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS); | BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS); | ||||
| } | } | ||||
| EDBM_flag_disable_all(em, BM_ELEM_SELECT); | EDBM_flag_disable_all(em, BM_ELEM_SELECT); | ||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| edbm_report_delete_info(op->reports, bm, totelem); | // no indent | ||||
| } | |||||
| int totelem_new[3]; | |||||
| EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL); | |||||
| edbm_report_delete_info(op->reports, totelem_old, totelem_new); | |||||
| MEM_SAFE_FREE(objects); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void MESH_OT_delete_loose(wmOperatorType *ot) | void MESH_OT_delete_loose(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ▲ Show 20 Lines • Show All 3,388 Lines • ▼ Show 20 Lines | void MESH_OT_poke(wmOperatorType *ot) | ||||
| RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED, | RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED, | ||||
| "Poke Center", "Poke Face Center Calculation"); | "Poke Center", "Poke Face Center Calculation"); | ||||
| } | } | ||||
| /********************** Quad/Tri Operators *************************/ | /********************** Quad/Tri Operators *************************/ | ||||
| static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) | static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| BMOperator bmop; | |||||
| const int quad_method = RNA_enum_get(op->ptr, "quad_method"); | const int quad_method = RNA_enum_get(op->ptr, "quad_method"); | ||||
| const int ngon_method = RNA_enum_get(op->ptr, "ngon_method"); | const int ngon_method = RNA_enum_get(op->ptr, "ngon_method"); | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| /* no indent for diff noise. */ | |||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *obedit = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| BMOperator bmop; | |||||
| BMOIter oiter; | BMOIter oiter; | ||||
| BMFace *f; | BMFace *f; | ||||
| EDBM_op_init(em, &bmop, op, "triangulate faces=%hf quad_method=%i ngon_method=%i", BM_ELEM_SELECT, quad_method, ngon_method); | EDBM_op_init(em, &bmop, op, "triangulate faces=%hf quad_method=%i ngon_method=%i", BM_ELEM_SELECT, quad_method, ngon_method); | ||||
| BMO_op_exec(em->bm, &bmop); | BMO_op_exec(em->bm, &bmop); | ||||
| /* select the output */ | /* select the output */ | ||||
| BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); | BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); | ||||
| /* remove the doubles */ | /* remove the doubles */ | ||||
| BMO_ITER (f, &oiter, bmop.slots_out, "face_map_double.out", BM_FACE) { | BMO_ITER (f, &oiter, bmop.slots_out, "face_map_double.out", BM_FACE) { | ||||
| BM_face_kill(em->bm, f); | BM_face_kill(em->bm, f); | ||||
| } | } | ||||
| EDBM_selectmode_flush(em); | EDBM_selectmode_flush(em); | ||||
| // XXX, TODO | |||||
| #if 0 | |||||
| if (!EDBM_op_finish(em, &bmop, op, true)) { | if (!EDBM_op_finish(em, &bmop, op, true)) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| #endif | |||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| } /* objects */ | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) | void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Triangulate Faces"; | ot->name = "Triangulate Faces"; | ||||
| Show All 10 Lines | void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) | ||||
| RNA_def_enum(ot->srna, "quad_method", rna_enum_modifier_triangulate_quad_method_items, MOD_TRIANGULATE_QUAD_BEAUTY, | RNA_def_enum(ot->srna, "quad_method", rna_enum_modifier_triangulate_quad_method_items, MOD_TRIANGULATE_QUAD_BEAUTY, | ||||
| "Quad Method", "Method for splitting the quads into triangles"); | "Quad Method", "Method for splitting the quads into triangles"); | ||||
| RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_ngon_method_items, MOD_TRIANGULATE_NGON_BEAUTY, | RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_ngon_method_items, MOD_TRIANGULATE_NGON_BEAUTY, | ||||
| "Polygon Method", "Method for splitting the polygons into triangles"); | "Polygon Method", "Method for splitting the polygons into triangles"); | ||||
| } | } | ||||
| static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) | static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| 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); | |||||
| } | |||||
| /* no indent for diff noise. */ | |||||
| 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); | ||||
| bool do_seam, do_sharp, do_uvs, do_vcols, do_materials; | bool do_seam, do_sharp, do_uvs, do_vcols, do_materials; | ||||
| float angle_face_threshold, angle_shape_threshold; | float angle_face_threshold, angle_shape_threshold; | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| /* When joining exactly 2 faces, no limit. | /* When joining exactly 2 faces, no limit. | ||||
| * this is useful for one off joins while editing. */ | * this is useful for one off joins while editing. */ | ||||
| prop = RNA_struct_find_property(op->ptr, "face_threshold"); | prop = RNA_struct_find_property(op->ptr, "face_threshold"); | ||||
| if ((em->bm->totfacesel == 2) && | if (is_face_pair && | ||||
| (RNA_property_is_set(op->ptr, prop) == false)) | (RNA_property_is_set(op->ptr, prop) == false)) | ||||
| { | { | ||||
| angle_face_threshold = DEG2RADF(180.0f); | angle_face_threshold = DEG2RADF(180.0f); | ||||
| } | } | ||||
| else { | else { | ||||
| angle_face_threshold = RNA_property_float_get(op->ptr, prop); | angle_face_threshold = RNA_property_float_get(op->ptr, prop); | ||||
| } | } | ||||
| prop = RNA_struct_find_property(op->ptr, "shape_threshold"); | prop = RNA_struct_find_property(op->ptr, "shape_threshold"); | ||||
| if ((em->bm->totfacesel == 2) && | if (is_face_pair && | ||||
| (RNA_property_is_set(op->ptr, prop) == false)) | (RNA_property_is_set(op->ptr, prop) == false)) | ||||
| { | { | ||||
| angle_shape_threshold = DEG2RADF(180.0f); | angle_shape_threshold = DEG2RADF(180.0f); | ||||
| } | } | ||||
| else { | else { | ||||
| angle_shape_threshold = RNA_property_float_get(op->ptr, prop); | angle_shape_threshold = RNA_property_float_get(op->ptr, prop); | ||||
| } | } | ||||
| do_seam = RNA_boolean_get(op->ptr, "seam"); | do_seam = RNA_boolean_get(op->ptr, "seam"); | ||||
| do_sharp = RNA_boolean_get(op->ptr, "sharp"); | do_sharp = RNA_boolean_get(op->ptr, "sharp"); | ||||
| do_uvs = RNA_boolean_get(op->ptr, "uvs"); | do_uvs = RNA_boolean_get(op->ptr, "uvs"); | ||||
| do_vcols = RNA_boolean_get(op->ptr, "vcols"); | do_vcols = RNA_boolean_get(op->ptr, "vcols"); | ||||
| do_materials = RNA_boolean_get(op->ptr, "materials"); | do_materials = RNA_boolean_get(op->ptr, "materials"); | ||||
| if (!EDBM_op_call_and_selectf( | if (!EDBM_op_call_and_selectf( | ||||
| em, op, | em, op, | ||||
| "faces.out", true, | "faces.out", true, | ||||
| "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f " | "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f " | ||||
| "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b", | "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b", | ||||
| BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold, | BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold, | ||||
| do_seam, do_sharp, do_uvs, do_vcols, do_materials)) | do_seam, do_sharp, do_uvs, do_vcols, do_materials)) | ||||
| { | { | ||||
| return OPERATOR_CANCELLED; | continue; | ||||
| } | } | ||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| } /* objects */ | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static void join_triangle_props(wmOperatorType *ot) | static void join_triangle_props(wmOperatorType *ot) | ||||
| { | { | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| prop = RNA_def_float_rotation( | prop = RNA_def_float_rotation( | ||||
| ▲ Show 20 Lines • Show All 478 Lines • ▼ Show 20 Lines | void MESH_OT_dissolve_limited(wmOperatorType *ot) | ||||
| RNA_def_boolean(ot->srna, "use_dissolve_boundaries", false, "All Boundaries", | RNA_def_boolean(ot->srna, "use_dissolve_boundaries", false, "All Boundaries", | ||||
| "Dissolve all vertices inbetween face boundaries"); | "Dissolve all vertices inbetween face boundaries"); | ||||
| RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_NORMAL, "Delimit", | RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_NORMAL, "Delimit", | ||||
| "Delimit dissolve operation"); | "Delimit dissolve operation"); | ||||
| } | } | ||||
| static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) | static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| int totelem_old[3] = {0, 0, 0}; | |||||
| int totelem_new[3] = {0, 0, 0}; | |||||
| uint objects_len = 0; | |||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( | |||||
| view_layer, &objects_len, | |||||
| .no_dupe_data = true); | |||||
| 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); | ||||
| BMesh *bm = em->bm; | |||||
| totelem_old[0] += bm->totvert; | |||||
| totelem_old[1] += bm->totedge; | |||||
| totelem_old[2] += bm->totface; | |||||
| } /* objects */ | |||||
| const float thresh = RNA_float_get(op->ptr, "threshold"); | const float thresh = RNA_float_get(op->ptr, "threshold"); | ||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | |||||
| Object *obedit = objects[ob_index]; | |||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | |||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| const int totelem[3] = {bm->totvert, bm->totedge, bm->totface}; | |||||
| if (!EDBM_op_callf( | if (!EDBM_op_callf( | ||||
| em, op, | em, op, | ||||
| "dissolve_degenerate edges=%he dist=%f", | "dissolve_degenerate edges=%he dist=%f", | ||||
| BM_ELEM_SELECT, thresh)) | BM_ELEM_SELECT, thresh)) | ||||
| { | { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| /* tricky to maintain correct selection here, so just flush up from verts */ | /* tricky to maintain correct selection here, so just flush up from verts */ | ||||
| EDBM_select_flush(em); | EDBM_select_flush(em); | ||||
| EDBM_update_generic(em, true, true); | EDBM_update_generic(em, true, true); | ||||
| edbm_report_delete_info(op->reports, bm, totelem); | totelem_new[0] += bm->totvert; | ||||
| totelem_new[1] += bm->totedge; | |||||
| totelem_new[2] += bm->totface; | |||||
| // no indent | |||||
| } /* objects */ | |||||
| edbm_report_delete_info(op->reports, totelem_old, totelem_new); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void MESH_OT_dissolve_degenerate(wmOperatorType *ot) | void MESH_OT_dissolve_degenerate(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Degenerate Dissolve"; | ot->name = "Degenerate Dissolve"; | ||||
| ▲ Show 20 Lines • Show All 1,481 Lines • Show Last 20 Lines | |||||