Code Cleanup: style change only
[blender.git] / source / blender / bmesh / intern / bmesh_iterators.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_iterators.c
24  *  \ingroup bmesh
25  *
26  * Functions to abstract looping over bmesh data structures.
27  *
28  * See: bmesh_iterators_inlin.c too, some functions are here for speed reasons.
29  */
30
31 #include <string.h>
32
33 #include "bmesh.h"
34 #include "bmesh_private.h"
35
36 /*
37  * note, we have BM_Vert_AtIndex/BM_Edge_AtIndex/BM_Face_AtIndex for arrays
38  */
39 void *BMIter_AtIndex(struct BMesh *bm, const char itype, void *data, int index)
40 {
41         BMIter iter;
42         void *val;
43         int i;
44
45         /*sanity check*/
46         if (index < 0) return NULL;
47
48         val=BMIter_New(&iter, bm, itype, data);
49
50         i = 0;
51         while (i < index) {
52                 val=BMIter_Step(&iter);
53                 i++;
54         }
55
56         return val;
57 }
58
59
60 /*
61  * ITERATOR AS ARRAY
62  *
63  * Sometimes its convenient to get the iterator as an array
64  * to avoid multiple calls to BMIter_AtIndex.
65  */
66
67 int BMIter_AsArray(struct BMesh *bm, const char type, void *data, void **array, const int len)
68 {
69         int i= 0;
70
71         /*sanity check*/
72         if (len > 0) {
73
74                 BMIter iter;
75                 void *val;
76
77                 BM_ITER(val, &iter, bm, type, data) {
78                         array[i]= val;
79                         i++;
80                         if (i == len) {
81                                 return len;
82                         }
83                 }
84         }
85
86         return i;
87 }
88
89
90 /*
91  * INIT ITERATOR
92  *
93  * Clears the internal state of an iterator
94  * For begin() callbacks.
95  *
96 */
97
98 static void init_iterator(BMIter *iter)
99 {
100         iter->firstvert = iter->nextvert = NULL;
101         iter->firstedge = iter->nextedge = NULL;
102         iter->firstloop = iter->nextloop = NULL;
103         iter->firstpoly = iter->nextpoly = NULL;
104         iter->ldata = NULL;
105 }
106
107 /*
108  * Notes on iterator implementation:
109  *
110  * Iterators keep track of the next element
111  * in a sequence. When a step() callback is
112  * invoked the current value of 'next' is stored
113  * to be returned later and the next variable is
114  * incremented.
115  *
116  * When the end of a sequence is
117  * reached, next should always equal NULL
118  *
119  * The 'bmiter__' prefix is used because these are used in
120  * bmesh_iterators_inine.c but should otherwise be seen as
121  * private.
122  */
123
124 /*
125  * VERT OF MESH CALLBACKS
126  *
127 */
128
129 void bmiter__vert_of_mesh_begin(BMIter *iter)
130 {
131         BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter);
132 }
133
134 void  *bmiter__vert_of_mesh_step(BMIter *iter)
135 {
136         return BLI_mempool_iterstep(&iter->pooliter);
137
138 }
139
140 void  bmiter__edge_of_mesh_begin(BMIter *iter)
141 {
142         BLI_mempool_iternew(iter->bm->epool, &iter->pooliter);
143 }
144
145 void  *bmiter__edge_of_mesh_step(BMIter *iter)
146 {
147         return BLI_mempool_iterstep(&iter->pooliter);
148
149 }
150
151 void  bmiter__face_of_mesh_begin(BMIter *iter)
152 {
153         BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter);
154 }
155
156 void  *bmiter__face_of_mesh_step(BMIter *iter)
157 {
158         return BLI_mempool_iterstep(&iter->pooliter);
159
160 }
161
162 /*
163  * EDGE OF VERT CALLBACKS
164  *
165 */
166
167 void  bmiter__edge_of_vert_begin(BMIter *iter)
168 {
169         init_iterator(iter);
170         if (iter->vdata->e) {
171                 iter->firstedge = iter->vdata->e;
172                 iter->nextedge = iter->vdata->e;
173         }
174 }
175
176 void  *bmiter__edge_of_vert_step(BMIter *iter)
177 {
178         BMEdge *current = iter->nextedge;
179
180         if (iter->nextedge)
181                 iter->nextedge = bmesh_disk_nextedge(iter->nextedge, iter->vdata);
182         
183         if (iter->nextedge == iter->firstedge) iter->nextedge = NULL;
184
185         return current;
186 }
187
188 /*
189  * FACE OF VERT CALLBACKS
190  *
191 */
192
193 void  bmiter__face_of_vert_begin(BMIter *iter)
194 {
195         init_iterator(iter);
196         iter->count = 0;
197         if (iter->vdata->e)
198                 iter->count = bmesh_disk_count_facevert(iter->vdata);
199         if (iter->count) {
200                 iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->e, iter->vdata);
201                 iter->nextedge = iter->firstedge;
202                 iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->l, iter->vdata);
203                 iter->nextloop = iter->firstloop;
204         }
205 }
206 void  *bmiter__face_of_vert_step(BMIter *iter)
207 {
208         BMLoop *current = iter->nextloop;
209
210         if (iter->count && iter->nextloop) {
211                 iter->count--;
212                 iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
213                 if (iter->nextloop == iter->firstloop) {
214                         iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
215                         iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->l, iter->vdata);
216                         iter->nextloop = iter->firstloop;
217                 }
218         }
219         
220         if (!iter->count) iter->nextloop = NULL;
221
222         
223         if (current) return current->f;
224         return NULL;
225 }
226
227
228 /*
229  * LOOP OF VERT CALLBACKS
230  *
231 */
232
233 void  bmiter__loop_of_vert_begin(BMIter *iter)
234 {
235         init_iterator(iter);
236         iter->count = 0;
237         if (iter->vdata->e)
238                 iter->count = bmesh_disk_count_facevert(iter->vdata);
239         if (iter->count) {
240                 iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->e, iter->vdata);
241                 iter->nextedge = iter->firstedge;
242                 iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->l, iter->vdata);
243                 iter->nextloop = iter->firstloop;
244         }
245 }
246 void  *bmiter__loop_of_vert_step(BMIter *iter)
247 {
248         BMLoop *current = iter->nextloop;
249
250         if (iter->count) {
251                 iter->count--;
252                 iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
253                 if (iter->nextloop == iter->firstloop) {
254                         iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
255                         iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->l, iter->vdata);
256                         iter->nextloop = iter->firstloop;
257                 }
258         }
259         
260         if (!iter->count) iter->nextloop = NULL;
261
262         
263         if (current) return current;
264         return NULL;
265 }
266
267
268 void  bmiter__loops_of_edge_begin(BMIter *iter)
269 {
270         BMLoop *l;
271
272         l = iter->edata->l;
273
274         /*note sure why this sets ldata. . .*/
275         init_iterator(iter);
276         
277         iter->firstloop = iter->nextloop = l;
278 }
279
280 void  *bmiter__loops_of_edge_step(BMIter *iter)
281 {
282         BMLoop *current = iter->nextloop;
283
284         if (iter->nextloop)
285                 iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
286
287         if (iter->nextloop == iter->firstloop)
288                 iter->nextloop = NULL;
289
290         if (current) return current;
291         return NULL;
292 }
293
294 void  bmiter__loops_of_loop_begin(BMIter *iter)
295 {
296         BMLoop *l;
297
298         l = iter->ldata;
299
300         /*note sure why this sets ldata. . .*/
301         init_iterator(iter);
302
303         iter->firstloop = l;
304         iter->nextloop = bmesh_radial_nextloop(iter->firstloop);
305         
306         if (iter->nextloop == iter->firstloop)
307                 iter->nextloop = NULL;
308 }
309
310 void  *bmiter__loops_of_loop_step(BMIter *iter)
311 {
312         BMLoop *current = iter->nextloop;
313         
314         if (iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
315
316         if (iter->nextloop == iter->firstloop) iter->nextloop = NULL;
317         if (current) return current;
318         return NULL;
319 }
320
321 /*
322  * FACE OF EDGE CALLBACKS
323  *
324 */
325
326 void  bmiter__face_of_edge_begin(BMIter *iter)
327 {
328         init_iterator(iter);
329         
330         if (iter->edata->l) {
331                 iter->firstloop = iter->edata->l;
332                 iter->nextloop = iter->edata->l;
333         }
334 }
335
336 void  *bmiter__face_of_edge_step(BMIter *iter)
337 {
338         BMLoop *current = iter->nextloop;
339
340         if (iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
341
342         if (iter->nextloop == iter->firstloop) iter->nextloop = NULL;
343         if (current) return current->f;
344         return NULL;
345 }
346
347 /*
348  * VERT OF FACE CALLBACKS
349  *
350 */
351
352 void  bmiter__vert_of_face_begin(BMIter *iter)
353 {
354         init_iterator(iter);
355         iter->firstloop = iter->nextloop = ((BMLoopList*)iter->pdata->loops.first)->first;
356 }
357
358 void  *bmiter__vert_of_face_step(BMIter *iter)
359 {
360         BMLoop *current = iter->nextloop;
361
362         if (iter->nextloop) iter->nextloop = iter->nextloop->next;
363         if (iter->nextloop == iter->firstloop) iter->nextloop = NULL;
364
365         if (current) return current->v;
366         return NULL;
367 }
368
369 /*
370  * EDGE OF FACE CALLBACKS
371  *
372 */
373
374 void  bmiter__edge_of_face_begin(BMIter *iter)
375 {
376         init_iterator(iter);
377         iter->firstloop = iter->nextloop = ((BMLoopList*)iter->pdata->loops.first)->first;
378 }
379
380 void  *bmiter__edge_of_face_step(BMIter *iter)
381 {
382         BMLoop *current = iter->nextloop;
383
384         if (iter->nextloop) iter->nextloop = iter->nextloop->next;
385         if (iter->nextloop == iter->firstloop) iter->nextloop = NULL;
386         
387         if (current) return current->e;
388         return NULL;
389 }
390
391 /*
392  * LOOP OF FACE CALLBACKS
393  *
394 */
395
396 void  bmiter__loop_of_face_begin(BMIter *iter)
397 {
398         init_iterator(iter);
399         iter->firstloop = iter->nextloop = bm_firstfaceloop(iter->pdata);
400 }
401
402 void  *bmiter__loop_of_face_step(BMIter *iter)
403 {
404         BMLoop *current = iter->nextloop;
405
406         if (iter->nextloop) iter->nextloop = iter->nextloop->next;
407         if (iter->nextloop == iter->firstloop) iter->nextloop = NULL;
408
409         return current;
410 }