Blender  V2.93
bmesh_walkers.c
Go to the documentation of this file.
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 
23 #include <stdlib.h>
24 #include <string.h> /* for memcpy */
25 
26 #include "BLI_listbase.h"
27 #include "BLI_utildefines.h"
28 
29 #include "bmesh.h"
30 
31 #include "bmesh_walkers_private.h"
32 
55 void *BMW_begin(BMWalker *walker, void *start)
56 {
57  BLI_assert(((BMHeader *)start)->htype & walker->begin_htype);
58 
59  walker->begin(walker, start);
60 
61  return BMW_current_state(walker) ? walker->step(walker) : NULL;
62 }
63 
70 void BMW_init(BMWalker *walker,
71  BMesh *bm,
72  int type,
73  short mask_vert,
74  short mask_edge,
75  short mask_face,
76  BMWFlag flag,
77  int layer)
78 {
79  memset(walker, 0, sizeof(BMWalker));
80 
81  walker->layer = layer;
82  walker->flag = flag;
83  walker->bm = bm;
84 
85  walker->mask_vert = mask_vert;
86  walker->mask_edge = mask_edge;
87  walker->mask_face = mask_face;
88 
89  walker->visit_set = BLI_gset_ptr_new("bmesh walkers");
90  walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec");
91 
92  if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) {
93  fprintf(stderr,
94  "%s: Invalid walker type in BMW_init; type: %d, "
95  "searchmask: (v:%d, e:%d, f:%d), flag: %u, layer: %d\n",
96  __func__,
97  type,
98  mask_vert,
99  mask_edge,
100  mask_face,
101  flag,
102  layer);
103  BLI_assert(0);
104  return;
105  }
106 
107  if (type != BMW_CUSTOM) {
109  walker->begin = bm_walker_types[type]->begin;
110  walker->yield = bm_walker_types[type]->yield;
111  walker->step = bm_walker_types[type]->step;
113  walker->order = bm_walker_types[type]->order;
115 
116  /* safety checks */
117  /* if this raises an error either the caller is wrong or
118  * 'bm_walker_types' needs updating */
119  BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT));
120  BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE));
121  BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE));
122  }
123 
124  walker->worklist = BLI_mempool_create(walker->structsize, 0, 128, BLI_MEMPOOL_NOP);
125  BLI_listbase_clear(&walker->states);
126 }
127 
133 void BMW_end(BMWalker *walker)
134 {
135  BLI_mempool_destroy(walker->worklist);
136  BLI_gset_free(walker->visit_set, NULL);
137  BLI_gset_free(walker->visit_set_alt, NULL);
138 }
139 
143 void *BMW_step(BMWalker *walker)
144 {
145  BMHeader *head;
146 
147  head = BMW_walk(walker);
148 
149  return head;
150 }
151 
159 {
160  return walker->depth;
161 }
162 
168 void *BMW_walk(BMWalker *walker)
169 {
170  void *current = NULL;
171 
172  while (BMW_current_state(walker)) {
173  current = walker->step(walker);
174  if (current) {
175  return current;
176  }
177  }
178  return NULL;
179 }
180 
189 {
190  BMwGenericWalker *currentstate = walker->states.first;
191  if (currentstate) {
192  /* Automatic update of depth. For most walkers that
193  * follow the standard "Step" pattern of:
194  * - read current state
195  * - remove current state
196  * - push new states
197  * - return walk result from just-removed current state
198  * this simple automatic update should keep track of depth
199  * just fine. Walkers that deviate from that pattern may
200  * need to manually update the depth if they care about
201  * keeping it correct. */
202  walker->depth = currentstate->depth + 1;
203  }
204  return currentstate;
205 }
206 
214 {
215  void *oldstate;
216  oldstate = BMW_current_state(walker);
217  BLI_remlink(&walker->states, oldstate);
218  BLI_mempool_free(walker->worklist, oldstate);
219 }
220 
230 void *BMW_state_add(BMWalker *walker)
231 {
232  BMwGenericWalker *newstate;
233  newstate = BLI_mempool_alloc(walker->worklist);
234  newstate->depth = walker->depth;
235  switch (walker->order) {
236  case BMW_DEPTH_FIRST:
237  BLI_addhead(&walker->states, newstate);
238  break;
239  case BMW_BREADTH_FIRST:
240  BLI_addtail(&walker->states, newstate);
241  break;
242  default:
243  BLI_assert(0);
244  break;
245  }
246  return newstate;
247 }
248 
255 void BMW_reset(BMWalker *walker)
256 {
257  while (BMW_current_state(walker)) {
258  BMW_state_remove(walker);
259  }
260  walker->depth = 0;
261  BLI_gset_clear(walker->visit_set, NULL);
263 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
GSet * BLI_gset_ptr_new(const char *info)
void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1248
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:77
void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int totelem, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mempool.c:268
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:334
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
#define UNLIKELY(x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Init Walker.
Definition: bmesh_walkers.c:70
void BMW_end(BMWalker *walker)
End Walker.
void BMW_reset(BMWalker *walker)
Reset Walker.
int BMW_current_depth(BMWalker *walker)
Walker Current Depth.
void * BMW_begin(BMWalker *walker, void *start)
Definition: bmesh_walkers.c:55
void * BMW_current_state(BMWalker *walker)
Current Walker State.
void * BMW_step(BMWalker *walker)
Step Walker.
void * BMW_walk(BMWalker *walker)
Main Walking Function.
void * BMW_state_add(BMWalker *walker)
Add a new Walker State.
void BMW_state_remove(BMWalker *walker)
Remove Current Walker State.
@ BMW_DEPTH_FIRST
Definition: bmesh_walkers.h:28
@ BMW_BREADTH_FIRST
Definition: bmesh_walkers.h:29
BMWFlag
Definition: bmesh_walkers.h:32
@ BMW_CUSTOM
@ BMW_MAXWALKERS
BMWalker * bm_walker_types[]
int structsize
Definition: bmesh_walkers.h:43
struct GSet * visit_set_alt
Definition: bmesh_walkers.h:63
ListBase states
Definition: bmesh_walkers.h:52
BMWOrder order
Definition: bmesh_walkers.h:44
BMWFlag flag
Definition: bmesh_walkers.h:60
short mask_face
Definition: bmesh_walkers.h:58
int valid_mask
Definition: bmesh_walkers.h:45
struct GSet * visit_set
Definition: bmesh_walkers.h:62
BMesh * bm
Definition: bmesh_walkers.h:50
short mask_edge
Definition: bmesh_walkers.h:57
short mask_vert
Definition: bmesh_walkers.h:56
char begin_htype
Definition: bmesh_walkers.h:39
BLI_mempool * worklist
Definition: bmesh_walkers.h:51
void *(* yield)(struct BMWalker *walker)
Definition: bmesh_walkers.h:42
void(* begin)(struct BMWalker *walker, void *start)
Definition: bmesh_walkers.h:40
void *(* step)(struct BMWalker *walker)
Definition: bmesh_walkers.h:41
void * first
Definition: DNA_listBase.h:47