Operator: Add 'use_dissolve_ortho_edges' option for Extrude
This commit is contained in:
parent
7af84255c7
commit
fe513a5b61
|
@ -1046,6 +1046,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
|
|||
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */
|
||||
{"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
|
||||
{"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */
|
||||
{"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
|
||||
{{'\0'}},
|
||||
},
|
||||
|
|
|
@ -39,6 +39,7 @@ enum {
|
|||
EXT_INPUT = 1,
|
||||
EXT_KEEP = 2,
|
||||
EXT_DEL = 4,
|
||||
EXT_TAG = 8,
|
||||
};
|
||||
|
||||
#define VERT_MARK 1
|
||||
|
@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
|||
const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
|
||||
const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in,
|
||||
"use_normal_from_adjacent");
|
||||
const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in,
|
||||
"use_dissolve_ortho_edges");
|
||||
|
||||
/* initialize our sub-operators */
|
||||
BMO_op_initf(bm,
|
||||
|
@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
BMVert **dissolve_verts = NULL;
|
||||
int dissolve_verts_len = 0;
|
||||
float average_normal[3];
|
||||
if (use_dissolve_ortho_edges) {
|
||||
/* Calc average normal. */
|
||||
zero_v3(average_normal);
|
||||
BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) {
|
||||
add_v3_v3(average_normal, f->no);
|
||||
}
|
||||
if (normalize_v3(average_normal) == 0.0f) {
|
||||
average_normal[2] = 1.0f;
|
||||
}
|
||||
|
||||
/* Allocate array to store possible vertices that will be dissolved. */
|
||||
int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out");
|
||||
dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__);
|
||||
}
|
||||
|
||||
BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out");
|
||||
|
||||
slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude");
|
||||
|
@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
|||
continue;
|
||||
}
|
||||
|
||||
BMFace *join_face = NULL;
|
||||
if (use_dissolve_ortho_edges) {
|
||||
if (BM_edge_is_boundary(e)) {
|
||||
join_face = e->l->f;
|
||||
if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) {
|
||||
join_face = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool edge_normal_flip;
|
||||
if (use_normal_from_adjacent == false) {
|
||||
/* Orient loop to give same normal as a loop of 'e_new'
|
||||
|
@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
|||
f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
|
||||
#endif
|
||||
|
||||
bm_extrude_copy_face_loop_attributes(bm, f);
|
||||
if (join_face) {
|
||||
BMVert *v1 = e->v1;
|
||||
BMVert *v2 = e->v2;
|
||||
if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) {
|
||||
BMO_elem_flag_enable(bm, v1, EXT_TAG);
|
||||
dissolve_verts[dissolve_verts_len++] = v1;
|
||||
}
|
||||
if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) {
|
||||
BMO_elem_flag_enable(bm, v2, EXT_TAG);
|
||||
dissolve_verts[dissolve_verts_len++] = v2;
|
||||
}
|
||||
bmesh_kernel_join_face_kill_edge(bm, join_face, f, e);
|
||||
}
|
||||
else {
|
||||
bm_extrude_copy_face_loop_attributes(bm, f);
|
||||
}
|
||||
}
|
||||
|
||||
/* link isolated vert */
|
||||
|
@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
|||
BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE);
|
||||
}
|
||||
|
||||
if (dissolve_verts) {
|
||||
BMVert **v_iter = &dissolve_verts[0];
|
||||
for (int i = dissolve_verts_len; i--; v_iter++) {
|
||||
v = *v_iter;
|
||||
e = v->e;
|
||||
BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
|
||||
if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) {
|
||||
/* Lose edge or BMVert is edge pair. */
|
||||
BM_edge_collapse(bm, e, v, true, false);
|
||||
}
|
||||
else {
|
||||
BLI_assert(!BM_vert_is_edge_pair(v));
|
||||
}
|
||||
}
|
||||
MEM_freeN(dissolve_verts);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (delorig) {
|
||||
BMO_op_finish(bm, &delop);
|
||||
|
|
|
@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit,
|
|||
char htype,
|
||||
const char hflag,
|
||||
const bool use_normal_flip,
|
||||
const bool use_dissolve_ortho_edges,
|
||||
const bool use_mirror,
|
||||
const bool use_select_history)
|
||||
{
|
||||
|
@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit,
|
|||
|
||||
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
|
||||
BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip);
|
||||
BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges);
|
||||
BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history);
|
||||
BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
|
||||
|
||||
|
@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
|
|||
mul_v3_m3v3(offset_local, tmat, offset);
|
||||
|
||||
for (int a = 0; a < steps; a++) {
|
||||
edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true);
|
||||
edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true);
|
||||
BMO_op_callf(
|
||||
em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT);
|
||||
}
|
||||
|
@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
|
|||
static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
|
||||
{
|
||||
const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
|
||||
const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges");
|
||||
const char htype = edbm_extrude_htype_from_em_select(em);
|
||||
enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr;
|
||||
bool changed = false;
|
||||
|
@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
|
|||
case NONE:
|
||||
return false;
|
||||
case ELEM_FLAG:
|
||||
changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true);
|
||||
changed = edbm_extrude_ex(obedit,
|
||||
em,
|
||||
htype,
|
||||
BM_ELEM_SELECT,
|
||||
use_normal_flip,
|
||||
use_dissolve_ortho_edges,
|
||||
true,
|
||||
true);
|
||||
break;
|
||||
case VERT_ONLY:
|
||||
changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
|
||||
|
@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
|
||||
RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
|
||||
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
|
||||
}
|
||||
|
||||
|
@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
|
||||
RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
|
||||
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
|
||||
}
|
||||
|
||||
|
@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
|
|||
}
|
||||
}
|
||||
|
||||
edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true);
|
||||
edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true);
|
||||
EDBM_op_callf(
|
||||
vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat);
|
||||
EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs);
|
||||
|
|
Loading…
Reference in New Issue