diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 83f57baea18..a84958f6827 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1581,7 +1581,8 @@ static BMOpDefine bmo_poke_def = { /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */ - {"center_mode", BMO_OP_SLOT_INT}, /* calculation mode for center vertex */ + {"center_mode", BMO_OP_SLOT_INT}, /* calculation mode for center vertex */ + {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */ {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c index 939bfb3b63e..122c14021c0 100644 --- a/source/blender/bmesh/operators/bmo_poke.c +++ b/source/blender/bmesh/operators/bmo_poke.c @@ -52,8 +52,8 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op) BMFace *f; const float offset = BMO_slot_float_get(op->slots_in, "offset"); + const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); const int center_mode = BMO_slot_int_get(op->slots_in, "center_mode"); - void (*bm_face_calc_center_fn)(BMFace *f, float r_cent[3]); switch (center_mode) { @@ -80,6 +80,9 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op) * then copy to all others in the fan */ BMLoop *l_center_example; + /* 1.0 or the average length from the center to the face verts */ + float offset_fac; + int i; bm_face_calc_center_fn(f, f_center); @@ -89,6 +92,13 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op) /* handled by BM_loop_interp_from_face */ // BM_vert_interp_from_face(bm, v_center, f); + if (use_relative_offset) { + offset_fac = 0.0f; + } + else { + offset_fac = 1.0f; + } + i = 0; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { @@ -110,10 +120,20 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op) BM_elem_attrs_copy(bm, bm, l_iter->next, l_new->next); BMO_elem_flag_enable(bm, f_new, ELE_NEW); + + if (use_relative_offset) { + offset_fac += len_v3v3(f_center, l_iter->v->co); + } + } while (i++, (l_iter = l_iter->next) != l_first); + if (use_relative_offset) { + offset_fac /= (float)f->len; + } + /* else remain at 1.0 */ + copy_v3_v3(v_center->no, f->no); - madd_v3_v3fl(v_center->co, v_center->no, offset); + madd_v3_v3fl(v_center->co, v_center->no, offset * offset_fac); /* Kill Face */ BM_face_kill(bm, f); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 2dbe2852303..0fff62f411c 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2641,9 +2641,11 @@ static int edbm_poke_face_exec(bContext *C, wmOperator *op) BMOperator bmop; const float offset = RNA_float_get(op->ptr, "offset"); + const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset"); const int center_mode = RNA_enum_get(op->ptr, "center_mode"); - EDBM_op_init(em, &bmop, op, "poke faces=%hf offset=%f center_mode=%i", BM_ELEM_SELECT, offset, center_mode); + EDBM_op_init(em, &bmop, op, "poke faces=%hf offset=%f use_relative_offset=%b center_mode=%i", + BM_ELEM_SELECT, offset, use_relative_offset, center_mode); BMO_op_exec(em->bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -2662,6 +2664,34 @@ static int edbm_poke_face_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } + +void MESH_OT_poke(wmOperatorType *ot) +{ + + static EnumPropertyItem poke_center_modes[] = { + {BMOP_POKE_MEAN_WEIGHTED, "MEAN_WEIGHTED", 0, "Weighted Mean", "Weighted Mean Face Center"}, + {BMOP_POKE_MEAN, "MEAN", 0, "Mean", "Mean Face Center"}, + {BMOP_POKE_BOUNDS, "BOUNDS", 0, "Bounds", "Face Bounds Center"}, + {0, NULL, 0, NULL, NULL}}; + + + /* identifiers */ + ot->name = "Poke Faces"; + ot->idname = "MESH_OT_poke"; + ot->description = "Splits a face into a fan"; + + /* api callbacks */ + ot->exec = edbm_poke_face_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Poke Offset", "Poke Offset", -1.0f, 1.0f); + RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry"); + RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED, "Poke Center", "Poke Face Center Calculation"); +} + /********************** Quad/Tri Operators *************************/ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) @@ -2690,31 +2720,6 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void MESH_OT_poke(wmOperatorType *ot) -{ - - static EnumPropertyItem poke_center_modes[] = { - {BMOP_POKE_MEAN_WEIGHTED, "MEAN_WEIGHTED", 0, "Weighted Mean", "Weighted Mean Face Center"}, - {BMOP_POKE_MEAN, "MEAN", 0, "Mean", "Mean Face Center"}, - {BMOP_POKE_BOUNDS, "BOUNDS", 0, "Bounds", "Face Bounds Center"}, - {0, NULL, 0, NULL, NULL}}; - - - /* identifiers */ - ot->name = "Poke Faces"; - ot->idname = "MESH_OT_poke"; - ot->description = "Splits a face into a fan"; - - /* api callbacks */ - ot->exec = edbm_poke_face_exec; - ot->poll = ED_operator_editmesh; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Poke Offset", "Poke Offset", -1.0f, 1.0f); - RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED, "Poke Center", "Poke Face Center Calculation"); -} void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) {