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  * Functions to abstract looping over bmesh data structures.
21  *
22  * See: bmesh_iterators_inlin.c too, some functions are here for speed reasons.
23  */
24 
25 #include "MEM_guardedalloc.h"
26 
27 #include "BLI_bitmap.h"
28 #include "BLI_utildefines.h"
29 
30 #include "bmesh.h"
31 #include "intern/bmesh_private.h"
32 
33 const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
34     '\0',
35     BM_VERT, /* BM_VERTS_OF_MESH */
36     BM_EDGE, /* BM_EDGES_OF_MESH */
37     BM_FACE, /* BM_FACES_OF_MESH */
38     BM_EDGE, /* BM_EDGES_OF_VERT */
39     BM_FACE, /* BM_FACES_OF_VERT */
40     BM_LOOP, /* BM_LOOPS_OF_VERT */
41     BM_VERT, /* BM_VERTS_OF_EDGE */
42     BM_FACE, /* BM_FACES_OF_EDGE */
43     BM_VERT, /* BM_VERTS_OF_FACE */
44     BM_EDGE, /* BM_EDGES_OF_FACE */
45     BM_LOOP, /* BM_LOOPS_OF_FACE */
46     BM_LOOP, /* BM_LOOPS_OF_LOOP */
47     BM_LOOP, /* BM_LOOPS_OF_EDGE */
48 };
49 
50 /**
51  * Utility function.
52  */
BM_iter_mesh_count(const char itype,BMesh * bm)53 int BM_iter_mesh_count(const char itype, BMesh *bm)
54 {
55   int count;
56 
57   switch (itype) {
58     case BM_VERTS_OF_MESH:
59       count = bm->totvert;
60       break;
61     case BM_EDGES_OF_MESH:
62       count = bm->totedge;
63       break;
64     case BM_FACES_OF_MESH:
65       count = bm->totface;
66       break;
67     default:
68       count = 0;
69       BLI_assert(0);
70       break;
71   }
72 
73   return count;
74 }
75 
76 /**
77  * \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays.
78  */
BM_iter_at_index(BMesh * bm,const char itype,void * data,int index)79 void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
80 {
81   BMIter iter;
82   void *val;
83   int i;
84 
85   /* sanity check */
86   if (index < 0) {
87     return NULL;
88   }
89 
90   val = BM_iter_new(&iter, bm, itype, data);
91 
92   i = 0;
93   while (i < index) {
94     val = BM_iter_step(&iter);
95     i++;
96   }
97 
98   return val;
99 }
100 
101 /**
102  * \brief Iterator as Array
103  *
104  * Sometimes its convenient to get the iterator as an array
105  * to avoid multiple calls to #BM_iter_at_index.
106  */
BM_iter_as_array(BMesh * bm,const char itype,void * data,void ** array,const int len)107 int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
108 {
109   int i = 0;
110 
111   /* sanity check */
112   if (len > 0) {
113     BMIter iter;
114     void *ele;
115 
116     for (ele = BM_iter_new(&iter, bm, itype, data); ele; ele = BM_iter_step(&iter)) {
117       array[i] = ele;
118       i++;
119       if (i == len) {
120         return len;
121       }
122     }
123   }
124 
125   return i;
126 }
127 /**
128  * \brief Operator Iterator as Array
129  *
130  * Sometimes its convenient to get the iterator as an array.
131  */
BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],const char * slot_name,const char restrictmask,void ** array,const int len)132 int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
133                       const char *slot_name,
134                       const char restrictmask,
135                       void **array,
136                       const int len)
137 {
138   int i = 0;
139 
140   /* sanity check */
141   if (len > 0) {
142     BMOIter oiter;
143     void *ele;
144 
145     for (ele = BMO_iter_new(&oiter, slot_args, slot_name, restrictmask); ele;
146          ele = BMO_iter_step(&oiter)) {
147       array[i] = ele;
148       i++;
149       if (i == len) {
150         return len;
151       }
152     }
153   }
154 
155   return i;
156 }
157 
158 /**
159  * \brief Iterator as Array
160  *
161  * Allocates a new array, has the advantage that you dont need to know the size ahead of time.
162  *
163  * Takes advantage of less common iterator usage to avoid counting twice,
164  * which you might end up doing when #BM_iter_as_array is used.
165  *
166  * Caller needs to free the array.
167  */
BM_iter_as_arrayN(BMesh * bm,const char itype,void * data,int * r_len,void ** stack_array,int stack_array_size)168 void *BM_iter_as_arrayN(BMesh *bm,
169                         const char itype,
170                         void *data,
171                         int *r_len,
172                         /* optional args to avoid an alloc (normally stack array) */
173                         void **stack_array,
174                         int stack_array_size)
175 {
176   BMIter iter;
177 
178   BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
179 
180   /* we can't rely on coun't being set */
181   switch (itype) {
182     case BM_VERTS_OF_MESH:
183       iter.count = bm->totvert;
184       break;
185     case BM_EDGES_OF_MESH:
186       iter.count = bm->totedge;
187       break;
188     case BM_FACES_OF_MESH:
189       iter.count = bm->totface;
190       break;
191     default:
192       break;
193   }
194 
195   if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) {
196     BMElem *ele;
197     BMElem **array = iter.count > stack_array_size ?
198                          MEM_mallocN(sizeof(ele) * iter.count, __func__) :
199                          stack_array;
200     int i = 0;
201 
202     *r_len = iter.count; /* set before iterating */
203 
204     while ((ele = BM_iter_step(&iter))) {
205       array[i++] = ele;
206     }
207     return array;
208   }
209 
210   *r_len = 0;
211   return NULL;
212 }
213 
BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],const char * slot_name,const char restrictmask,int * r_len,void ** stack_array,int stack_array_size)214 void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
215                          const char *slot_name,
216                          const char restrictmask,
217                          int *r_len,
218                          /* optional args to avoid an alloc (normally stack array) */
219                          void **stack_array,
220                          int stack_array_size)
221 {
222   BMOIter iter;
223   BMElem *ele;
224   int count = BMO_slot_buffer_count(slot_args, slot_name);
225 
226   BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
227 
228   if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) {
229     BMElem **array = count > stack_array_size ? MEM_mallocN(sizeof(ele) * count, __func__) :
230                                                 stack_array;
231     int i = 0;
232 
233     do {
234       array[i++] = ele;
235     } while ((ele = BMO_iter_step(&iter)));
236     BLI_assert(i <= count);
237 
238     if (i != count) {
239       if ((void **)array != stack_array) {
240         array = MEM_reallocN(array, sizeof(ele) * i);
241       }
242     }
243     *r_len = i;
244     return array;
245   }
246 
247   *r_len = 0;
248   return NULL;
249 }
250 
BM_iter_mesh_bitmap_from_filter(const char itype,BMesh * bm,BLI_bitmap * bitmap,bool (* test_fn)(BMElem *,void * user_data),void * user_data)251 int BM_iter_mesh_bitmap_from_filter(const char itype,
252                                     BMesh *bm,
253                                     BLI_bitmap *bitmap,
254                                     bool (*test_fn)(BMElem *, void *user_data),
255                                     void *user_data)
256 {
257   BMIter iter;
258   BMElem *ele;
259   int i;
260   int bitmap_enabled = 0;
261 
262   BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) {
263     if (test_fn(ele, user_data)) {
264       BLI_BITMAP_ENABLE(bitmap, i);
265       bitmap_enabled++;
266     }
267     else {
268       BLI_BITMAP_DISABLE(bitmap, i);
269     }
270   }
271 
272   return bitmap_enabled;
273 }
274 
275 /**
276  * Needed when we want to check faces, but return a loop aligned array.
277  */
BM_iter_mesh_bitmap_from_filter_tessface(BMesh * bm,BLI_bitmap * bitmap,bool (* test_fn)(BMFace *,void * user_data),void * user_data)278 int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
279                                              BLI_bitmap *bitmap,
280                                              bool (*test_fn)(BMFace *, void *user_data),
281                                              void *user_data)
282 {
283   BMIter iter;
284   BMFace *f;
285   int i;
286   int j = 0;
287   int bitmap_enabled = 0;
288 
289   BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
290     if (test_fn(f, user_data)) {
291       for (int tri = 2; tri < f->len; tri++) {
292         BLI_BITMAP_ENABLE(bitmap, j);
293         bitmap_enabled++;
294         j++;
295       }
296     }
297     else {
298       for (int tri = 2; tri < f->len; tri++) {
299         BLI_BITMAP_DISABLE(bitmap, j);
300         j++;
301       }
302     }
303   }
304 
305   return bitmap_enabled;
306 }
307 
308 /**
309  * \brief Elem Iter Flag Count
310  *
311  * Counts how many flagged / unflagged items are found in this element.
312  */
BM_iter_elem_count_flag(const char itype,void * data,const char hflag,const bool value)313 int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value)
314 {
315   BMIter iter;
316   BMElem *ele;
317   int count = 0;
318 
319   BM_ITER_ELEM (ele, &iter, data, itype) {
320     if (BM_elem_flag_test_bool(ele, hflag) == value) {
321       count++;
322     }
323   }
324 
325   return count;
326 }
327 
328 /**
329  * \brief Elem Iter Tool Flag Count
330  *
331  * Counts how many flagged / unflagged items are found in this element.
332  */
BMO_iter_elem_count_flag(BMesh * bm,const char itype,void * data,const short oflag,const bool value)333 int BMO_iter_elem_count_flag(
334     BMesh *bm, const char itype, void *data, const short oflag, const bool value)
335 {
336   BMIter iter;
337   int count = 0;
338 
339   /* loops have no header flags */
340   BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP);
341 
342   switch (bm_iter_itype_htype_map[itype]) {
343     case BM_VERT: {
344       BMVert *ele;
345       BM_ITER_ELEM (ele, &iter, data, itype) {
346         if (BMO_vert_flag_test_bool(bm, ele, oflag) == value) {
347           count++;
348         }
349       }
350       break;
351     }
352     case BM_EDGE: {
353       BMEdge *ele;
354       BM_ITER_ELEM (ele, &iter, data, itype) {
355         if (BMO_edge_flag_test_bool(bm, ele, oflag) == value) {
356           count++;
357         }
358       }
359       break;
360     }
361     case BM_FACE: {
362       BMFace *ele;
363       BM_ITER_ELEM (ele, &iter, data, itype) {
364         if (BMO_face_flag_test_bool(bm, ele, oflag) == value) {
365           count++;
366         }
367       }
368       break;
369     }
370   }
371   return count;
372 }
373 
374 /**
375  * \brief Mesh Iter Flag Count
376  *
377  * Counts how many flagged / unflagged items are found in this mesh.
378  */
BM_iter_mesh_count_flag(const char itype,BMesh * bm,const char hflag,const bool value)379 int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
380 {
381   BMIter iter;
382   BMElem *ele;
383   int count = 0;
384 
385   BM_ITER_MESH (ele, &iter, bm, itype) {
386     if (BM_elem_flag_test_bool(ele, hflag) == value) {
387       count++;
388     }
389   }
390 
391   return count;
392 }
393 
394 /**
395  * Notes on iterator implementation:
396  *
397  * Iterators keep track of the next element in a sequence.
398  * When a step() callback is invoked the current value of 'next'
399  * is stored to be returned later and the next variable is incremented.
400  *
401  * When the end of a sequence is reached, next should always equal NULL
402  *
403  * The 'bmiter__' prefix is used because these are used in
404  * bmesh_iterators_inine.c but should otherwise be seen as
405  * private.
406  */
407 
408 /*
409  * VERT OF MESH CALLBACKS
410  */
411 
412 /* see bug T36923 for why we need this,
413  * allow adding but not removing, this isnt _totally_ safe since
414  * you could add/remove within the same loop, but catches common cases
415  */
416 #ifdef DEBUG
417 #  define USE_IMMUTABLE_ASSERT
418 #endif
419 
bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh * iter)420 void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter)
421 {
422 #ifdef USE_IMMUTABLE_ASSERT
423   ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool);
424 #endif
425   BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter);
426 }
427 
bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh * iter)428 void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter)
429 {
430 #ifdef USE_IMMUTABLE_ASSERT
431   BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool));
432 #endif
433   return BLI_mempool_iterstep(&iter->pooliter);
434 }
435 
436 #ifdef USE_IMMUTABLE_ASSERT
437 #  undef USE_IMMUTABLE_ASSERT
438 #endif
439 
440 /*
441  * EDGE OF VERT CALLBACKS
442  */
443 
bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert * iter)444 void bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert *iter)
445 {
446   if (iter->vdata->e) {
447     iter->e_first = iter->vdata->e;
448     iter->e_next = iter->vdata->e;
449   }
450   else {
451     iter->e_first = NULL;
452     iter->e_next = NULL;
453   }
454 }
455 
bmiter__edge_of_vert_step(struct BMIter__edge_of_vert * iter)456 void *bmiter__edge_of_vert_step(struct BMIter__edge_of_vert *iter)
457 {
458   BMEdge *e_curr = iter->e_next;
459 
460   if (iter->e_next) {
461     iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata);
462     if (iter->e_next == iter->e_first) {
463       iter->e_next = NULL;
464     }
465   }
466 
467   return e_curr;
468 }
469 
470 /*
471  * FACE OF VERT CALLBACKS
472  */
473 
bmiter__face_of_vert_begin(struct BMIter__face_of_vert * iter)474 void bmiter__face_of_vert_begin(struct BMIter__face_of_vert *iter)
475 {
476   ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
477   if (((BMIter *)iter)->count) {
478     iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
479     iter->e_first = iter->l_first->e;
480     iter->e_next = iter->e_first;
481     iter->l_next = iter->l_first;
482   }
483   else {
484     iter->l_first = iter->l_next = NULL;
485     iter->e_first = iter->e_next = NULL;
486   }
487 }
bmiter__face_of_vert_step(struct BMIter__face_of_vert * iter)488 void *bmiter__face_of_vert_step(struct BMIter__face_of_vert *iter)
489 {
490   BMLoop *l_curr = iter->l_next;
491 
492   if (((BMIter *)iter)->count && iter->l_next) {
493     ((BMIter *)iter)->count--;
494     iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
495     if (iter->l_next == iter->l_first) {
496       iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
497       iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
498       iter->l_next = iter->l_first;
499     }
500   }
501 
502   if (!((BMIter *)iter)->count) {
503     iter->l_next = NULL;
504   }
505 
506   return l_curr ? l_curr->f : NULL;
507 }
508 
509 /*
510  * LOOP OF VERT CALLBACKS
511  */
512 
bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert * iter)513 void bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert *iter)
514 {
515   ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
516   if (((BMIter *)iter)->count) {
517     iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
518     iter->e_first = iter->l_first->e;
519     iter->e_next = iter->e_first;
520     iter->l_next = iter->l_first;
521   }
522   else {
523     iter->l_first = iter->l_next = NULL;
524     iter->e_first = iter->e_next = NULL;
525   }
526 }
bmiter__loop_of_vert_step(struct BMIter__loop_of_vert * iter)527 void *bmiter__loop_of_vert_step(struct BMIter__loop_of_vert *iter)
528 {
529   BMLoop *l_curr = iter->l_next;
530 
531   if (((BMIter *)iter)->count) {
532     ((BMIter *)iter)->count--;
533     iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
534     if (iter->l_next == iter->l_first) {
535       iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
536       iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
537       iter->l_next = iter->l_first;
538     }
539   }
540 
541   if (!((BMIter *)iter)->count) {
542     iter->l_next = NULL;
543   }
544 
545   /* NULL on finish */
546   return l_curr;
547 }
548 
549 /*
550  * LOOP OF EDGE CALLBACKS
551  */
552 
bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge * iter)553 void bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge *iter)
554 {
555   iter->l_first = iter->l_next = iter->edata->l;
556 }
557 
bmiter__loop_of_edge_step(struct BMIter__loop_of_edge * iter)558 void *bmiter__loop_of_edge_step(struct BMIter__loop_of_edge *iter)
559 {
560   BMLoop *l_curr = iter->l_next;
561 
562   if (iter->l_next) {
563     iter->l_next = iter->l_next->radial_next;
564     if (iter->l_next == iter->l_first) {
565       iter->l_next = NULL;
566     }
567   }
568 
569   /* NULL on finish */
570   return l_curr;
571 }
572 
573 /*
574  * LOOP OF LOOP CALLBACKS
575  */
576 
bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop * iter)577 void bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop *iter)
578 {
579   iter->l_first = iter->ldata;
580   iter->l_next = iter->l_first->radial_next;
581 
582   if (iter->l_next == iter->l_first) {
583     iter->l_next = NULL;
584   }
585 }
586 
bmiter__loop_of_loop_step(struct BMIter__loop_of_loop * iter)587 void *bmiter__loop_of_loop_step(struct BMIter__loop_of_loop *iter)
588 {
589   BMLoop *l_curr = iter->l_next;
590 
591   if (iter->l_next) {
592     iter->l_next = iter->l_next->radial_next;
593     if (iter->l_next == iter->l_first) {
594       iter->l_next = NULL;
595     }
596   }
597 
598   /* NULL on finish */
599   return l_curr;
600 }
601 
602 /*
603  * FACE OF EDGE CALLBACKS
604  */
605 
bmiter__face_of_edge_begin(struct BMIter__face_of_edge * iter)606 void bmiter__face_of_edge_begin(struct BMIter__face_of_edge *iter)
607 {
608   iter->l_first = iter->l_next = iter->edata->l;
609 }
610 
bmiter__face_of_edge_step(struct BMIter__face_of_edge * iter)611 void *bmiter__face_of_edge_step(struct BMIter__face_of_edge *iter)
612 {
613   BMLoop *current = iter->l_next;
614 
615   if (iter->l_next) {
616     iter->l_next = iter->l_next->radial_next;
617     if (iter->l_next == iter->l_first) {
618       iter->l_next = NULL;
619     }
620   }
621 
622   return current ? current->f : NULL;
623 }
624 
625 /*
626  * VERTS OF EDGE CALLBACKS
627  */
628 
bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge * iter)629 void bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge *iter)
630 {
631   ((BMIter *)iter)->count = 0;
632 }
633 
bmiter__vert_of_edge_step(struct BMIter__vert_of_edge * iter)634 void *bmiter__vert_of_edge_step(struct BMIter__vert_of_edge *iter)
635 {
636   switch (((BMIter *)iter)->count++) {
637     case 0:
638       return iter->edata->v1;
639     case 1:
640       return iter->edata->v2;
641     default:
642       return NULL;
643   }
644 }
645 
646 /*
647  * VERT OF FACE CALLBACKS
648  */
649 
bmiter__vert_of_face_begin(struct BMIter__vert_of_face * iter)650 void bmiter__vert_of_face_begin(struct BMIter__vert_of_face *iter)
651 {
652   iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
653 }
654 
bmiter__vert_of_face_step(struct BMIter__vert_of_face * iter)655 void *bmiter__vert_of_face_step(struct BMIter__vert_of_face *iter)
656 {
657   BMLoop *l_curr = iter->l_next;
658 
659   if (iter->l_next) {
660     iter->l_next = iter->l_next->next;
661     if (iter->l_next == iter->l_first) {
662       iter->l_next = NULL;
663     }
664   }
665 
666   return l_curr ? l_curr->v : NULL;
667 }
668 
669 /*
670  * EDGE OF FACE CALLBACKS
671  */
672 
bmiter__edge_of_face_begin(struct BMIter__edge_of_face * iter)673 void bmiter__edge_of_face_begin(struct BMIter__edge_of_face *iter)
674 {
675   iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
676 }
677 
bmiter__edge_of_face_step(struct BMIter__edge_of_face * iter)678 void *bmiter__edge_of_face_step(struct BMIter__edge_of_face *iter)
679 {
680   BMLoop *l_curr = iter->l_next;
681 
682   if (iter->l_next) {
683     iter->l_next = iter->l_next->next;
684     if (iter->l_next == iter->l_first) {
685       iter->l_next = NULL;
686     }
687   }
688 
689   return l_curr ? l_curr->e : NULL;
690 }
691 
692 /*
693  * LOOP OF FACE CALLBACKS
694  */
695 
bmiter__loop_of_face_begin(struct BMIter__loop_of_face * iter)696 void bmiter__loop_of_face_begin(struct BMIter__loop_of_face *iter)
697 {
698   iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
699 }
700 
bmiter__loop_of_face_step(struct BMIter__loop_of_face * iter)701 void *bmiter__loop_of_face_step(struct BMIter__loop_of_face *iter)
702 {
703   BMLoop *l_curr = iter->l_next;
704 
705   if (iter->l_next) {
706     iter->l_next = iter->l_next->next;
707     if (iter->l_next == iter->l_first) {
708       iter->l_next = NULL;
709     }
710   }
711 
712   return l_curr;
713 }
714