Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2014-08-25 10:48:47 +0400
committerCampbell Barton <ideasman42@gmail.com>2014-08-25 10:57:38 +0400
commitca1bca442ab3ae6ab4332a24a784a1c79bde4e27 (patch)
treeb67221277ced8aca98d8659e00542b9d93f89ef5 /source/blender/bmesh
parent470e694652a28d20d31e001240fdb9727a6d1480 (diff)
Fix T40993: Store selection history for extrude
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c21
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c5
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c11
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c64
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
8 files changed, 111 insertions, 7 deletions
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index e23a5721234..cde842cab3e 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -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)
{
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 655ace6de5f..9e0c0923164 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -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__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 5e568f88843..886181cd204 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -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 */
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index ef4990ab56e..287aafc8f9f 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -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, \
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 7f872613896..6bca5ca7a43 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -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);
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 794c688b26b..cd5592f08c9 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -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);
+ }
}
/**
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 510c3ae0078..88b53b63abb 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -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
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index fa77e6b509c..d9f50ac891c 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -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");