forked from bartvdbraak/blender
Fix T40993: Store selection history for extrude
This commit is contained in:
parent
470e694652
commit
ca1bca442a
@ -899,6 +899,27 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map from BMVert/Edge/Face -> BMEditSelection
|
||||
*/
|
||||
GHash *BM_select_history_map_create(BMesh *bm)
|
||||
{
|
||||
BMEditSelection *ese;
|
||||
GHash *map;
|
||||
|
||||
if (BLI_listbase_is_empty(&bm->selected)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
map = BLI_ghash_ptr_new(__func__);
|
||||
|
||||
for (ese = bm->selected.first; ese; ese = ese->next) {
|
||||
BLI_ghash_insert(map, ese->ele, ese);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
|
||||
const bool respecthide, const bool overwrite, const char hflag_test)
|
||||
{
|
||||
|
@ -100,5 +100,12 @@ void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref,
|
||||
void BM_select_history_validate(BMesh *bm);
|
||||
void BM_select_history_clear(BMesh *bm);
|
||||
bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
|
||||
struct GHash *BM_select_history_map_create(BMesh *bm);
|
||||
|
||||
#define BM_SELECT_HISTORY_BACKUP(bm) { \
|
||||
ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected)
|
||||
|
||||
#define BM_SELECT_HISTORY_RESTORE(bm) \
|
||||
(bm)->selected = _bm_prev_selected; } (void)0
|
||||
|
||||
#endif /* __BMESH_MARKING_H__ */
|
||||
|
@ -854,6 +854,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
|
||||
"extrude_discrete_faces",
|
||||
/* slots_in */
|
||||
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
|
||||
{{'\0'}},
|
||||
},
|
||||
/* slots_out */
|
||||
@ -874,6 +875,7 @@ static BMOpDefine bmo_extrude_edge_only_def = {
|
||||
"extrude_edge_only",
|
||||
/* slots_in */
|
||||
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
|
||||
{{'\0'}},
|
||||
},
|
||||
/* slots_out */
|
||||
@ -893,6 +895,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
|
||||
"extrude_vert_indiv",
|
||||
/* slots_in */
|
||||
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
|
||||
{{'\0'}},
|
||||
},
|
||||
/* slots_out */
|
||||
@ -982,6 +985,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
|
||||
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
|
||||
{"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
|
||||
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
|
||||
{{'\0'}},
|
||||
},
|
||||
/* slots_out */
|
||||
@ -1267,6 +1271,7 @@ static BMOpDefine bmo_duplicate_def = {
|
||||
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
|
||||
/* destination bmesh, if NULL will use current on */
|
||||
{"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
|
||||
{"use_select_history", BMO_OP_SLOT_BOOL},
|
||||
{{'\0'}},
|
||||
},
|
||||
/* slots_out */
|
||||
|
@ -338,7 +338,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, cons
|
||||
void BMO_mesh_selected_remap(BMesh *bm,
|
||||
BMOpSlot *slot_vert_map,
|
||||
BMOpSlot *slot_edge_map,
|
||||
BMOpSlot *slot_face_map);
|
||||
BMOpSlot *slot_face_map,
|
||||
const bool check_select);
|
||||
|
||||
/* copies the values from another slot to the end of the output slot */
|
||||
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
|
||||
|
@ -605,7 +605,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
|
||||
void BMO_mesh_selected_remap(BMesh *bm,
|
||||
BMOpSlot *slot_vert_map,
|
||||
BMOpSlot *slot_edge_map,
|
||||
BMOpSlot *slot_face_map)
|
||||
BMOpSlot *slot_face_map,
|
||||
const bool check_select)
|
||||
{
|
||||
if (bm->selected.first) {
|
||||
BMEditSelection *ese, *ese_next;
|
||||
@ -623,7 +624,7 @@ void BMO_mesh_selected_remap(BMesh *bm,
|
||||
ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
|
||||
|
||||
if (UNLIKELY((ese->ele == NULL) ||
|
||||
(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))
|
||||
(check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))))
|
||||
{
|
||||
BLI_remlink(&bm->selected, ese);
|
||||
MEM_freeN(ese);
|
||||
|
@ -183,6 +183,7 @@ static BMFace *bmo_face_copy(BMOperator *op,
|
||||
*/
|
||||
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
|
||||
{
|
||||
const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
|
||||
|
||||
BMVert *v = NULL, *v2;
|
||||
BMEdge *e = NULL;
|
||||
@ -285,6 +286,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
|
||||
/* free pointer hashes */
|
||||
BLI_ghash_free(vhash, NULL, NULL);
|
||||
BLI_ghash_free(ehash, NULL, NULL);
|
||||
|
||||
if (use_select_history) {
|
||||
BLI_assert(bm_src == bm_dst);
|
||||
BMO_mesh_selected_remap(
|
||||
bm_dst,
|
||||
slot_vert_map_out,
|
||||
slot_edge_map_out,
|
||||
slot_face_map_out,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,9 +53,16 @@ enum {
|
||||
|
||||
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
|
||||
GHash *select_history_map = NULL;
|
||||
|
||||
BMOIter siter;
|
||||
BMFace *f_org;
|
||||
|
||||
if (use_select_history) {
|
||||
select_history_map = BM_select_history_map_create(bm);
|
||||
}
|
||||
|
||||
BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) {
|
||||
BMFace *f_new;
|
||||
BMLoop *l_org, *l_org_first;
|
||||
@ -66,6 +73,14 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
|
||||
f_new = BM_face_copy(bm, bm, f_org, true, true);
|
||||
BMO_elem_flag_enable(bm, f_new, EXT_KEEP);
|
||||
|
||||
if (select_history_map) {
|
||||
BMEditSelection *ese;
|
||||
ese = BLI_ghash_lookup(select_history_map, f_org);
|
||||
if (ese) {
|
||||
ese->ele = (BMElem *)f_new;
|
||||
}
|
||||
}
|
||||
|
||||
l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org);
|
||||
l_new = BM_FACE_FIRST_LOOP(f_new);
|
||||
|
||||
@ -85,10 +100,28 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
|
||||
BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next;
|
||||
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next;
|
||||
BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
|
||||
|
||||
if (select_history_map) {
|
||||
BMEditSelection *ese;
|
||||
|
||||
ese = BLI_ghash_lookup(select_history_map, l_org->v);
|
||||
if (ese) {
|
||||
ese->ele = (BMElem *)l_new->v;
|
||||
}
|
||||
ese = BLI_ghash_lookup(select_history_map, l_org->e);
|
||||
if (ese) {
|
||||
ese->ele = (BMElem *)l_new->e;
|
||||
}
|
||||
}
|
||||
|
||||
} while (((l_new = l_new->next),
|
||||
(l_org = l_org->next)) != l_org_first);
|
||||
}
|
||||
|
||||
if (select_history_map) {
|
||||
BLI_ghash_free(select_history_map, NULL, NULL);
|
||||
}
|
||||
|
||||
BMO_op_callf(bm, op->flag,
|
||||
"delete geom=%ff context=%i",
|
||||
EXT_DEL, DEL_ONLYFACES);
|
||||
@ -157,7 +190,11 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
|
||||
BMO_elem_flag_enable(bm, e->v2, EXT_INPUT);
|
||||
}
|
||||
|
||||
BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%fve", EXT_INPUT);
|
||||
BMO_op_initf(
|
||||
bm, &dupeop, op->flag,
|
||||
"duplicate geom=%fve use_select_history=%b",
|
||||
EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history"));
|
||||
|
||||
BMO_op_exec(bm, &dupeop);
|
||||
|
||||
/* disable root flag on all new skin nodes */
|
||||
@ -205,10 +242,16 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
|
||||
|
||||
void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
|
||||
BMOIter siter;
|
||||
BMVert *v, *dupev;
|
||||
BMEdge *e;
|
||||
const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
|
||||
GHash *select_history_map = NULL;
|
||||
|
||||
if (use_select_history) {
|
||||
select_history_map = BM_select_history_map_create(bm);
|
||||
}
|
||||
|
||||
for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
|
||||
dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
|
||||
@ -217,6 +260,14 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
|
||||
if (has_vskin)
|
||||
bm_extrude_disable_skin_root(bm, v);
|
||||
|
||||
if (select_history_map) {
|
||||
BMEditSelection *ese;
|
||||
ese = BLI_ghash_lookup(select_history_map, v);
|
||||
if (ese) {
|
||||
ese->ele = (BMElem *)dupev;
|
||||
}
|
||||
}
|
||||
|
||||
/* not essential, but ensures face normals from extruded edges are contiguous */
|
||||
if (BM_vert_is_wire_endpoint(v)) {
|
||||
if (v->e->v1 == v) {
|
||||
@ -228,6 +279,10 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
|
||||
BMO_elem_flag_enable(bm, e, EXT_KEEP);
|
||||
}
|
||||
|
||||
if (select_history_map) {
|
||||
BLI_ghash_free(select_history_map, NULL, NULL);
|
||||
}
|
||||
|
||||
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP);
|
||||
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
|
||||
}
|
||||
@ -245,8 +300,11 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
|
||||
BMOpSlot *slot_edges_exclude;
|
||||
|
||||
/* initialize our sub-operators */
|
||||
BMO_op_init(bm, &dupeop, op->flag, "duplicate");
|
||||
|
||||
BMO_op_initf(
|
||||
bm, &dupeop, op->flag,
|
||||
"duplicate use_select_history=%b",
|
||||
BMO_slot_bool_get(op->slots_in, "use_select_history"));
|
||||
|
||||
BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT);
|
||||
|
||||
/* if one flagged face is bordered by an un-flagged face, then we delete
|
||||
|
@ -154,7 +154,7 @@ static unsigned int bmesh_face_attribute_fill(BMesh *bm,
|
||||
return face_tot;
|
||||
}
|
||||
|
||||
void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
|
||||
void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
|
||||
const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
@ -65,105 +66,25 @@ static void add_normal_aligned(float nor[3], const float add[3])
|
||||
}
|
||||
}
|
||||
|
||||
/* individual face extrude */
|
||||
/* will use vertex normals for extrusion directions, so *nor is unaffected */
|
||||
static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMOIter siter;
|
||||
BMIter liter;
|
||||
BMFace *f;
|
||||
BMLoop *l;
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(em, &bmop, op, "extrude_discrete_faces faces=%hf", hflag);
|
||||
|
||||
/* deselect original verts */
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
|
||||
BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
|
||||
BM_face_select_set(em->bm, f, true);
|
||||
|
||||
/* set face vertex normals to face normal */
|
||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
||||
copy_v3_v3(l->v->no, f->no);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 's'; /* s is shrink/fatten */
|
||||
}
|
||||
|
||||
/* extrudes individual edges */
|
||||
static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(em, &bmop, op, "extrude_edge_only edges=%he", hflag);
|
||||
|
||||
/* deselect original verts */
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 'n'; /* n is normal grab */
|
||||
}
|
||||
|
||||
/* extrudes individual vertices */
|
||||
static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag);
|
||||
|
||||
/* deselect original verts */
|
||||
BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 'g'; /* g is grab */
|
||||
}
|
||||
|
||||
static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
|
||||
static void edbm_extrude_edge_exclude_mirror(
|
||||
Object *obedit, BMEditMesh *em,
|
||||
const char hflag,
|
||||
BMOperator *op, BMOpSlot *slot_edges_exclude)
|
||||
{
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMOIter siter;
|
||||
BMOperator extop;
|
||||
BMEdge *edge;
|
||||
BMFace *f;
|
||||
ModifierData *md;
|
||||
BMElem *ele;
|
||||
BMOpSlot *slot_edges_exclude;
|
||||
|
||||
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
|
||||
BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag);
|
||||
|
||||
slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
|
||||
|
||||
/* If a mirror modifier with clipping is on, we need to adjust some
|
||||
/* If a mirror modifier with clipping is on, we need to adjust some
|
||||
* of the cases above to handle edges on the line of symmetry.
|
||||
*/
|
||||
md = obedit->modifiers.first;
|
||||
for (; md; md = md->next) {
|
||||
for (md = obedit->modifiers.first; md; md = md->next) {
|
||||
if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
|
||||
MirrorModifierData *mmd = (MirrorModifierData *) md;
|
||||
|
||||
|
||||
if (mmd->flag & MOD_MIR_CLIPPING) {
|
||||
BMIter iter;
|
||||
BMEdge *edge;
|
||||
|
||||
float mtx[4][4];
|
||||
if (mmd->mirror_ob) {
|
||||
float imtx[4][4];
|
||||
@ -190,21 +111,21 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
|
||||
if ((fabsf(co1[0]) < mmd->tolerance) &&
|
||||
(fabsf(co2[0]) < mmd->tolerance))
|
||||
{
|
||||
BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
|
||||
BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
|
||||
}
|
||||
}
|
||||
if (mmd->flag & MOD_MIR_AXIS_Y) {
|
||||
if ((fabsf(co1[1]) < mmd->tolerance) &&
|
||||
(fabsf(co2[1]) < mmd->tolerance))
|
||||
{
|
||||
BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
|
||||
BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
|
||||
}
|
||||
}
|
||||
if (mmd->flag & MOD_MIR_AXIS_Z) {
|
||||
if ((fabsf(co1[2]) < mmd->tolerance) &&
|
||||
(fabsf(co2[2]) < mmd->tolerance))
|
||||
{
|
||||
BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge);
|
||||
BMO_slot_map_empty_insert(op, slot_edges_exclude, edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,9 +133,120 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* individual face extrude */
|
||||
/* will use vertex normals for extrusion directions, so *nor is unaffected */
|
||||
static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMOIter siter;
|
||||
BMIter liter;
|
||||
BMFace *f;
|
||||
BMLoop *l;
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(
|
||||
em, &bmop, op,
|
||||
"extrude_discrete_faces faces=%hf use_select_history=%b",
|
||||
hflag, true);
|
||||
|
||||
/* deselect original verts */
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
|
||||
BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
|
||||
BM_face_select_set(em->bm, f, true);
|
||||
|
||||
/* set face vertex normals to face normal */
|
||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
||||
copy_v3_v3(l->v->no, f->no);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 's'; /* s is shrink/fatten */
|
||||
}
|
||||
|
||||
/* extrudes individual edges */
|
||||
static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMesh *bm = em->bm;
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(
|
||||
em, &bmop, op,
|
||||
"extrude_edge_only edges=%he use_select_history=%b",
|
||||
hflag, true);
|
||||
|
||||
/* deselect original verts */
|
||||
BM_SELECT_HISTORY_BACKUP(bm);
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
BM_SELECT_HISTORY_RESTORE(bm);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 'n'; /* n is normal grab */
|
||||
}
|
||||
|
||||
/* extrudes individual vertices */
|
||||
static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor))
|
||||
{
|
||||
BMOperator bmop;
|
||||
|
||||
EDBM_op_init(
|
||||
em, &bmop, op,
|
||||
"extrude_vert_indiv verts=%hv use_select_history=%b",
|
||||
hflag, true);
|
||||
|
||||
/* deselect original verts */
|
||||
BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
|
||||
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 'g'; /* g is grab */
|
||||
}
|
||||
|
||||
static short edbm_extrude_edge_ex(
|
||||
Object *obedit, BMEditMesh *em,
|
||||
const char hflag, float nor[3],
|
||||
const bool use_mirror,
|
||||
const bool use_select_history)
|
||||
{
|
||||
BMesh *bm = em->bm;
|
||||
BMOIter siter;
|
||||
BMOperator extop;
|
||||
BMFace *f;
|
||||
BMElem *ele;
|
||||
|
||||
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
|
||||
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", BM_VERT | BM_EDGE | BM_FACE, hflag);
|
||||
|
||||
if (use_mirror) {
|
||||
BMOpSlot *slot_edges_exclude;
|
||||
slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude");
|
||||
|
||||
edbm_extrude_edge_exclude_mirror(obedit, em, hflag, &extop, slot_edges_exclude);
|
||||
}
|
||||
|
||||
BM_SELECT_HISTORY_BACKUP(bm);
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
BM_SELECT_HISTORY_RESTORE(bm);
|
||||
|
||||
BMO_op_exec(bm, &extop);
|
||||
|
||||
zero_v3(nor);
|
||||
@ -236,6 +268,13 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
|
||||
return is_zero_v3(nor) ? 'g' : 'n';
|
||||
}
|
||||
|
||||
static short edbm_extrude_edge(
|
||||
Object *obedit, BMEditMesh *em,
|
||||
const char hflag, float nor[3])
|
||||
{
|
||||
return edbm_extrude_edge_ex(obedit, em, hflag, nor, true, true);
|
||||
}
|
||||
|
||||
static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
|
||||
{
|
||||
BMIter iter;
|
||||
@ -288,13 +327,12 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
|
||||
mul_m3_v3(tmat, dvec);
|
||||
|
||||
for (a = 0; a < steps; a++) {
|
||||
edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor);
|
||||
//BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT);
|
||||
BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
|
||||
"translate vec=%v verts=%hv",
|
||||
dvec, BM_ELEM_SELECT);
|
||||
//extrudeflag(obedit, em, SELECT, nor);
|
||||
//translateflag(em, SELECT, dvec);
|
||||
edbm_extrude_edge_ex(obedit, em, BM_ELEM_SELECT, nor, false, false);
|
||||
|
||||
BMO_op_callf(
|
||||
em->bm, BMO_FLAG_DEFAULTS,
|
||||
"translate vec=%v verts=%hv",
|
||||
dvec, BM_ELEM_SELECT);
|
||||
}
|
||||
|
||||
EDBM_mesh_normals_update(em);
|
||||
|
@ -1019,28 +1019,23 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
|
||||
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
||||
BMesh *bm = em->bm;
|
||||
BMOperator bmop;
|
||||
ListBase bm_selected_store = {NULL, NULL};
|
||||
|
||||
EDBM_op_init(
|
||||
em, &bmop, op,
|
||||
"duplicate geom=%hvef use_select_history=%b",
|
||||
BM_ELEM_SELECT, true);
|
||||
|
||||
BMO_op_exec(bm, &bmop);
|
||||
|
||||
/* de-select all would clear otherwise */
|
||||
SWAP(ListBase, bm->selected, bm_selected_store);
|
||||
BM_SELECT_HISTORY_BACKUP(bm);
|
||||
|
||||
EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT);
|
||||
|
||||
BMO_op_exec(bm, &bmop);
|
||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||
|
||||
BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
|
||||
|
||||
/* rebuild editselection */
|
||||
bm->selected = bm_selected_store;
|
||||
|
||||
if (bm->selected.first) {
|
||||
BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out");
|
||||
BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out");
|
||||
BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out");
|
||||
|
||||
BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out);
|
||||
}
|
||||
BM_SELECT_HISTORY_RESTORE(bm);
|
||||
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -1328,6 +1328,15 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
|
||||
|
||||
/* don't keep stale derivedMesh data around, see: [#38872] */
|
||||
BKE_editmesh_free_derivedmesh(em);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
BMEditSelection *ese;
|
||||
for (ese = em->bm->selected.first; ese; ese = ese->next) {
|
||||
BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* poll call for mesh operators requiring a view3d context */
|
||||
|
Loading…
Reference in New Issue
Block a user