EditMesh: add delete loose operator (access from Cleanup menu)
This commit is contained in:
parent
7df8452d1a
commit
5568d7c3a1
|
@ -2301,6 +2301,10 @@ class VIEW3D_MT_edit_mesh_clean(Menu):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("mesh.delete_loose")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("mesh.fill_holes")
|
||||
layout.operator("mesh.vert_connect_nonplanar")
|
||||
|
||||
|
|
|
@ -382,6 +382,107 @@ void MESH_OT_delete(wmOperatorType *ot)
|
|||
ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 0, "Type", "Method used for deleting mesh data");
|
||||
}
|
||||
|
||||
|
||||
static bool bm_face_is_loose(BMFace *f)
|
||||
{
|
||||
BMLoop *l_iter, *l_first;
|
||||
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
if (!BM_edge_is_boundary(l_iter->e)) {
|
||||
return false;
|
||||
}
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
|
||||
const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && bm->totvertsel);
|
||||
const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && bm->totedgesel);
|
||||
const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && bm->totfacesel);
|
||||
|
||||
const int totelem[3] = {bm->totvert, bm->totedge, bm->totface};
|
||||
|
||||
|
||||
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
|
||||
|
||||
if (use_faces) {
|
||||
BMFace *f;
|
||||
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
BM_elem_flag_set(f, BM_ELEM_TAG, bm_face_is_loose(f));
|
||||
}
|
||||
}
|
||||
|
||||
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
|
||||
}
|
||||
|
||||
if (use_edges) {
|
||||
BMEdge *e;
|
||||
|
||||
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
|
||||
BM_elem_flag_set(e, BM_ELEM_TAG, BM_edge_is_wire(e));
|
||||
}
|
||||
}
|
||||
|
||||
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_EDGES);
|
||||
}
|
||||
|
||||
if (use_verts) {
|
||||
BMVert *v;
|
||||
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
|
||||
BM_elem_flag_set(v, BM_ELEM_TAG, (v->e == NULL));
|
||||
}
|
||||
}
|
||||
|
||||
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
|
||||
}
|
||||
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
||||
EDBM_update_generic(em, true, true);
|
||||
|
||||
BKE_reportf(op->reports, RPT_INFO,
|
||||
"Removed: %d vertices, %d edges, %d faces",
|
||||
totelem[0] - bm->totvert, totelem[1] - bm->totedge, totelem[2] - bm->totface);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void MESH_OT_delete_loose(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Delete Loose";
|
||||
ot->description = "Delete loose vertices, edges or faces";
|
||||
ot->idname = "MESH_OT_delete_loose";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = edbm_delete_loose_exec;
|
||||
|
||||
ot->poll = ED_operator_editmesh;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* props */
|
||||
RNA_def_boolean(ot->srna, "use_verts", true, "Vertices", "Remove loose vertices");
|
||||
RNA_def_boolean(ot->srna, "use_edges", true, "Edges", "Remove loose edges");
|
||||
RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces");
|
||||
}
|
||||
|
||||
|
||||
static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
|
|
|
@ -184,6 +184,7 @@ void MESH_OT_uvs_reverse(struct wmOperatorType *ot);
|
|||
void MESH_OT_colors_rotate(struct wmOperatorType *ot);
|
||||
void MESH_OT_colors_reverse(struct wmOperatorType *ot);
|
||||
void MESH_OT_delete(struct wmOperatorType *ot);
|
||||
void MESH_OT_delete_loose(struct wmOperatorType *ot);
|
||||
void MESH_OT_edge_collapse(struct wmOperatorType *ot);
|
||||
void MESH_OT_faces_shade_smooth(struct wmOperatorType *ot);
|
||||
void MESH_OT_faces_shade_flat(struct wmOperatorType *ot);
|
||||
|
|
|
@ -121,6 +121,7 @@ void ED_operatortypes_mesh(void)
|
|||
#endif
|
||||
|
||||
WM_operatortype_append(MESH_OT_delete);
|
||||
WM_operatortype_append(MESH_OT_delete_loose);
|
||||
WM_operatortype_append(MESH_OT_edge_collapse);
|
||||
|
||||
WM_operatortype_append(MESH_OT_separate);
|
||||
|
|
Loading…
Reference in New Issue