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 #pragma once 18 19 /** \file 20 * \ingroup bmesh 21 */ 22 23 /** 24 * \brief BMesh Iterators 25 * 26 * The functions and structures in this file 27 * provide a unified method for iterating over 28 * the elements of a mesh and answering simple 29 * adjacency queries. Tool authors should use 30 * the iterators provided in this file instead 31 * of inspecting the structure directly. 32 */ 33 34 #include "BLI_compiler_attrs.h" 35 #include "BLI_mempool.h" 36 37 /* Defines for passing to BM_iter_new. 38 * 39 * "OF" can be substituted for "around" 40 * so BM_VERTS_OF_FACE means "vertices 41 * around a face." 42 */ 43 44 /* these iterator over all elements of a specific 45 * type in the mesh. 46 * 47 * be sure to keep 'bm_iter_itype_htype_map' in sync with any changes 48 */ 49 typedef enum BMIterType { 50 BM_VERTS_OF_MESH = 1, 51 BM_EDGES_OF_MESH = 2, 52 BM_FACES_OF_MESH = 3, 53 /* these are topological iterators. */ 54 BM_EDGES_OF_VERT = 4, 55 BM_FACES_OF_VERT = 5, 56 BM_LOOPS_OF_VERT = 6, 57 BM_VERTS_OF_EDGE = 7, /* just v1, v2: added so py can use generalized sequencer wrapper */ 58 BM_FACES_OF_EDGE = 8, 59 BM_VERTS_OF_FACE = 9, 60 BM_EDGES_OF_FACE = 10, 61 BM_LOOPS_OF_FACE = 11, 62 /* returns elements from all boundaries, and returns 63 * the first element at the end to flag that we're entering 64 * a different face hole boundary*/ 65 // BM_ALL_LOOPS_OF_FACE = 12, 66 /* iterate through loops around this loop, which are fetched 67 * from the other faces in the radial cycle surrounding the 68 * input loop's edge.*/ 69 BM_LOOPS_OF_LOOP = 12, 70 BM_LOOPS_OF_EDGE = 13, 71 } BMIterType; 72 73 #define BM_ITYPE_MAX 14 74 75 /* the iterator htype for each iterator */ 76 extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; 77 78 #define BM_ITER_MESH(ele, iter, bm, itype) \ 79 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); ele; \ 80 BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) 81 82 #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \ 83 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; \ 84 BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) 85 86 /* a version of BM_ITER_MESH which keeps the next item in storage 87 * so we can delete the current item, see bug T36923. */ 88 #ifdef DEBUG 89 # define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ 90 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ 91 ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \ 92 (void)(ele_next = BM_iter_step(iter)), \ 93 1) : \ 94 0; \ 95 BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next) 96 #else 97 # define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ 98 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ 99 ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \ 100 ele = ele_next) 101 #endif 102 103 #define BM_ITER_ELEM(ele, iter, data, itype) \ 104 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); ele; \ 105 BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) 106 107 #define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar) \ 108 for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; \ 109 BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) 110 111 /* iterator type structs */ 112 struct BMIter__elem_of_mesh { 113 BLI_mempool_iter pooliter; 114 }; 115 struct BMIter__edge_of_vert { 116 BMVert *vdata; 117 BMEdge *e_first, *e_next; 118 }; 119 struct BMIter__face_of_vert { 120 BMVert *vdata; 121 BMLoop *l_first, *l_next; 122 BMEdge *e_first, *e_next; 123 }; 124 struct BMIter__loop_of_vert { 125 BMVert *vdata; 126 BMLoop *l_first, *l_next; 127 BMEdge *e_first, *e_next; 128 }; 129 struct BMIter__loop_of_edge { 130 BMEdge *edata; 131 BMLoop *l_first, *l_next; 132 }; 133 struct BMIter__loop_of_loop { 134 BMLoop *ldata; 135 BMLoop *l_first, *l_next; 136 }; 137 struct BMIter__face_of_edge { 138 BMEdge *edata; 139 BMLoop *l_first, *l_next; 140 }; 141 struct BMIter__vert_of_edge { 142 BMEdge *edata; 143 }; 144 struct BMIter__vert_of_face { 145 BMFace *pdata; 146 BMLoop *l_first, *l_next; 147 }; 148 struct BMIter__edge_of_face { 149 BMFace *pdata; 150 BMLoop *l_first, *l_next; 151 }; 152 struct BMIter__loop_of_face { 153 BMFace *pdata; 154 BMLoop *l_first, *l_next; 155 }; 156 157 typedef void (*BMIter__begin_cb)(void *); 158 typedef void *(*BMIter__step_cb)(void *); 159 160 /* Iterator Structure */ 161 /* note: some of these vars are not used, 162 * so they have been commented to save stack space since this struct is used all over */ 163 typedef struct BMIter { 164 /* keep union first */ 165 union { 166 struct BMIter__elem_of_mesh elem_of_mesh; 167 168 struct BMIter__edge_of_vert edge_of_vert; 169 struct BMIter__face_of_vert face_of_vert; 170 struct BMIter__loop_of_vert loop_of_vert; 171 struct BMIter__loop_of_edge loop_of_edge; 172 struct BMIter__loop_of_loop loop_of_loop; 173 struct BMIter__face_of_edge face_of_edge; 174 struct BMIter__vert_of_edge vert_of_edge; 175 struct BMIter__vert_of_face vert_of_face; 176 struct BMIter__edge_of_face edge_of_face; 177 struct BMIter__loop_of_face loop_of_face; 178 } data; 179 180 BMIter__begin_cb begin; 181 BMIter__step_cb step; 182 183 int count; /* note, only some iterators set this, don't rely on it */ 184 char itype; 185 } BMIter; 186 187 void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; 188 int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); 189 void *BM_iter_as_arrayN(BMesh *bm, 190 const char itype, 191 void *data, 192 int *r_len, 193 void **stack_array, 194 int stack_array_size) ATTR_WARN_UNUSED_RESULT; 195 int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], 196 const char *slot_name, 197 const char restrictmask, 198 void **array, 199 const int len); 200 void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], 201 const char *slot_name, 202 const char restrictmask, 203 int *r_len, 204 /* optional args to avoid an alloc (normally stack array) */ 205 void **stack_array, 206 int stack_array_size); 207 208 int BM_iter_mesh_bitmap_from_filter(const char itype, 209 BMesh *bm, 210 uint *bitmap, 211 bool (*test_fn)(BMElem *, void *user_data), 212 void *user_data); 213 int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm, 214 uint *bitmap, 215 bool (*test_fn)(BMFace *, void *user_data), 216 void *user_data); 217 218 int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); 219 int BMO_iter_elem_count_flag( 220 BMesh *bm, const char itype, void *data, const short oflag, const bool value); 221 int BM_iter_mesh_count(const char itype, BMesh *bm); 222 int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value); 223 224 /* private for bmesh_iterators_inline.c */ 225 226 #define BMITER_CB_DEF(name) \ 227 struct BMIter__##name; \ 228 void bmiter__##name##_begin(struct BMIter__##name *iter); \ 229 void *bmiter__##name##_step(struct BMIter__##name *iter) 230 231 BMITER_CB_DEF(elem_of_mesh); 232 BMITER_CB_DEF(edge_of_vert); 233 BMITER_CB_DEF(face_of_vert); 234 BMITER_CB_DEF(loop_of_vert); 235 BMITER_CB_DEF(loop_of_edge); 236 BMITER_CB_DEF(loop_of_loop); 237 BMITER_CB_DEF(face_of_edge); 238 BMITER_CB_DEF(vert_of_edge); 239 BMITER_CB_DEF(vert_of_face); 240 BMITER_CB_DEF(edge_of_face); 241 BMITER_CB_DEF(loop_of_face); 242 243 #undef BMITER_CB_DEF 244 245 #include "intern/bmesh_iterators_inline.h" 246 247 #define BM_ITER_CHECK_TYPE_DATA(data) \ 248 CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *) 249 250 #define BM_iter_new(iter, bm, itype, data) \ 251 (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data)) 252 #define BM_iter_init(iter, bm, itype, data) \ 253 (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data)) 254