1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup bmesh
19 *
20 * Edge-Split.
21 */
22
23 #include "MEM_guardedalloc.h"
24
25 #include "BLI_utildefines.h"
26
27 #include "bmesh.h"
28
29 #include "bmesh_edgesplit.h" /* own include */
30
31 /**
32 * \param use_verts: Use flagged verts instead of edges.
33 * \param tag_only: Only split tagged edges.
34 * \param copy_select: Copy selection history.
35 */
BM_mesh_edgesplit(BMesh * bm,const bool use_verts,const bool tag_only,const bool copy_select)36 void BM_mesh_edgesplit(BMesh *bm,
37 const bool use_verts,
38 const bool tag_only,
39 const bool copy_select)
40 {
41 BMIter iter;
42 BMEdge *e;
43
44 bool use_ese = false;
45 GHash *ese_gh = NULL;
46
47 if (copy_select && bm->selected.first) {
48 BMEditSelection *ese;
49
50 ese_gh = BLI_ghash_ptr_new(__func__);
51 for (ese = bm->selected.first; ese; ese = ese->next) {
52 if (ese->htype != BM_FACE) {
53 BLI_ghash_insert(ese_gh, ese->ele, ese);
54 }
55 }
56
57 use_ese = true;
58 }
59
60 if (tag_only == false) {
61 BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false);
62 }
63
64 if (use_verts) {
65 /* prevent one edge having both verts unflagged
66 * we could alternately disable these edges, either way its a corner case.
67 *
68 * This is needed so we don't split off the edge but then none of its verts which
69 * would leave a duplicate edge.
70 */
71 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
72 if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
73 if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) &&
74 (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false)))) {
75 BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
76 BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
77 }
78 }
79 }
80 }
81 else {
82 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
83 if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
84 BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
85 BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
86 }
87 }
88 }
89
90 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
91 if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
92 uint i;
93 for (i = 0; i < 2; i++) {
94 BMVert *v = ((&e->v1)[i]);
95 if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
96 BM_elem_flag_disable(v, BM_ELEM_TAG);
97
98 if (use_ese) {
99 BMVert **vtar;
100 int vtar_len;
101
102 BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len);
103
104 /* first value is always in 'v' */
105 if (vtar_len > 1) {
106 BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v);
107 BLI_assert(v == vtar[0]);
108 if (UNLIKELY(ese)) {
109 int j;
110 for (j = 1; j < vtar_len; j++) {
111 BLI_assert(v != vtar[j]);
112 BM_select_history_store_after_notest(bm, ese, vtar[j]);
113 }
114 }
115 }
116 MEM_freeN(vtar);
117 }
118 else {
119 BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL);
120 }
121 }
122 }
123 }
124 }
125
126 #ifndef NDEBUG
127 /* ensure we don't have any double edges! */
128 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
129 if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
130 BLI_assert(BM_edge_find_double(e) == NULL);
131 }
132 }
133 #endif
134
135 if (use_ese) {
136 BLI_ghash_free(ese_gh, NULL, NULL);
137 }
138 }
139