Blender  V3.3
bmesh_operators.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_listbase.h"
12 #include "BLI_math.h"
13 #include "BLI_memarena.h"
14 #include "BLI_mempool.h"
15 #include "BLI_string.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BLT_translation.h"
19 
20 #include "bmesh.h"
21 #include "intern/bmesh_private.h"
22 
23 /* forward declarations */
24 static void bmo_flag_layer_alloc(BMesh *bm);
25 static void bmo_flag_layer_free(BMesh *bm);
26 static void bmo_flag_layer_clear(BMesh *bm);
27 static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
29  const char *identifier);
30 
32  0, /* 0: BMO_OP_SLOT_SENTINEL */
33  sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
34  sizeof(int), /* 2: BMO_OP_SLOT_INT */
35  sizeof(float), /* 3: BMO_OP_SLOT_FLT */
36  sizeof(void *), /* 4: BMO_OP_SLOT_PNT */
37  sizeof(void *), /* 5: BMO_OP_SLOT_PNT */
38  0, /* 6: unused */
39  0, /* 7: unused */
40  sizeof(float[3]), /* 8: BMO_OP_SLOT_VEC */
41  sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
42  sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */
43 };
44 
45 /* Dummy slot so there is something to return when slot name lookup fails */
46 // static BMOpSlot BMOpEmptySlot = {0};
47 
48 void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
49 {
50  op->flag |= op_flag;
51 }
52 
53 void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
54 {
55  op->flag &= ~op_flag;
56 }
57 
59 {
60  bm->toolflag_index++;
61 
62  BLI_assert(bm->totflags > 0);
63 
64  /* add flag layer, if appropriate */
65  if (bm->toolflag_index > 0) {
67  }
68  else {
70  }
71 }
72 
74 {
75  if (bm->toolflag_index > 0) {
77  }
78 
79  bm->toolflag_index--;
80 }
81 
82 /* use for both slot_types_in and slot_types_out */
83 static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
84 {
85  BMOpSlot *slot;
86  uint i;
87  for (i = 0; slot_types[i].type; i++) {
88  slot = &slot_args[i];
89  slot->slot_name = slot_types[i].name;
90  slot->slot_type = slot_types[i].type;
91  slot->slot_subtype = slot_types[i].subtype;
92  // slot->index = i; // UNUSED
93 
94  switch (slot->slot_type) {
96  slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
97  break;
98  case BMO_OP_SLOT_INT:
99  if (ELEM(slot->slot_subtype.intg,
102  slot->data.enum_data.flags = slot_types[i].enum_flags;
103  /* Set the first value of the enum as the default value. */
104  slot->data.i = slot->data.enum_data.flags[0].value;
105  }
106  default:
107  break;
108  }
109  }
110 }
111 
112 static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
113 {
114  BMOpSlot *slot;
115  uint i;
116  for (i = 0; slot_types[i].type; i++) {
117  slot = &slot_args[i];
118  switch (slot->slot_type) {
119  case BMO_OP_SLOT_MAPPING:
120  BLI_ghash_free(slot->data.ghash, NULL, NULL);
121  break;
122  default:
123  break;
124  }
125  }
126 }
127 
128 void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
129 {
130  int opcode = BMO_opcode_from_opname(opname);
131 
132 #ifdef DEBUG
133  BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
134 #else
135  (void)bm;
136 #endif
137 
138  if (opcode == -1) {
139  opcode = 0; /* error!, already printed, have a better way to handle this? */
140  }
141 
142  memset(op, 0, sizeof(BMOperator));
143  op->type = opcode;
144  op->type_flag = bmo_opdefines[opcode]->type_flag;
145  op->flag = flag;
146 
147  /* initialize the operator slot types */
148  bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in);
149  bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out);
150 
151  /* callback */
152  op->exec = bmo_opdefines[opcode]->exec;
153 
154  /* memarena, used for operator's slot buffers */
157 }
158 
160 {
161  /* allocate tool flags on demand */
163 
164  BMO_push(bm, op);
165 
166  if (bm->toolflag_index == 1) {
168  }
169  op->exec(bm, op);
170 
171  if (bm->toolflag_index == 1) {
173  }
174 
175  BMO_pop(bm);
176 }
177 
179 {
182 
184 
185 #ifdef DEBUG
186  BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname);
187 
188  /* avoid accidental re-use */
189  memset(op, 0xff, sizeof(*op));
190 #else
191  (void)bm;
192 #endif
193 }
194 
195 bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
196 {
197  int slot_code = bmo_name_to_slotcode(slot_args, identifier);
198  return (slot_code >= 0);
199 }
200 
201 BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
202 {
203  int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
204 
205  if (UNLIKELY(slot_code < 0)) {
206  // return &BMOpEmptySlot;
207  BLI_assert(0);
208  return NULL; /* better crash */
209  }
210 
211  return &slot_args[slot_code];
212 }
213 
215  const char *slot_name_src,
216  BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
217  const char *slot_name_dst,
218  struct MemArena *arena_dst)
219 {
220  BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
221  BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
222 
223  if (slot_src == slot_dst) {
224  return;
225  }
226 
227  BLI_assert(slot_src->slot_type == slot_dst->slot_type);
228  if (slot_src->slot_type != slot_dst->slot_type) {
229  return;
230  }
231 
232  if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
233  /* do buffer copy */
234  slot_dst->data.buf = NULL;
235  slot_dst->len = slot_src->len;
236  if (slot_dst->len) {
237  /* check dest has all flags enabled that the source has */
238  const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP);
239  const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP);
240 
241  if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) {
242  /* pass */
243  }
244  else {
245  /* check types */
246  const uint tot = slot_src->len;
247  uint i;
248  uint out = 0;
249  BMElem **ele_src = (BMElem **)slot_src->data.buf;
250  for (i = 0; i < tot; i++, ele_src++) {
251  if ((*ele_src)->head.htype & dst_elem_flag) {
252  out++;
253  }
254  }
255  if (out != tot) {
256  slot_dst->len = out;
257  }
258  }
259 
260  if (slot_dst->len) {
261  const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len;
262  slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size);
263  if (slot_src->len == slot_dst->len) {
264  memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size);
265  }
266  else {
267  /* only copy compatible elements */
268  const uint tot = slot_src->len;
269  uint i;
270  BMElem **ele_src = (BMElem **)slot_src->data.buf;
271  BMElem **ele_dst = (BMElem **)slot_dst->data.buf;
272  for (i = 0; i < tot; i++, ele_src++) {
273  if ((*ele_src)->head.htype & dst_elem_flag) {
274  *ele_dst = *ele_src;
275  ele_dst++;
276  }
277  }
278  }
279  }
280  }
281  }
282  else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
283  GHashIterator gh_iter;
284  GHASH_ITER (gh_iter, slot_src->data.ghash) {
285  void *key = BLI_ghashIterator_getKey(&gh_iter);
286  void *val = BLI_ghashIterator_getValue(&gh_iter);
287  BLI_ghash_insert(slot_dst->data.ghash, key, val);
288  }
289  }
290  else {
291  slot_dst->data = slot_src->data;
292  }
293 }
294 
295 /*
296  * BMESH OPSTACK SET XXX
297  *
298  * Sets the value of a slot depending on its type
299  */
300 
301 void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f)
302 {
303  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
305  if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
306  return;
307  }
308 
309  slot->data.f = f;
310 }
311 
312 void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
313 {
314  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
316  if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
317  return;
318  }
319 
320  slot->data.i = i;
321 }
322 
323 void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i)
324 {
325  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
327  if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
328  return;
329  }
330 
331  slot->data.i = i;
332 }
333 
335  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
336  const char *slot_name,
337  const float *mat,
338  int size)
339 {
340  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
342  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
343  return;
344  }
345 
346  slot->len = 4;
347  slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float[4][4]));
348 
349  if (size == 4) {
350  copy_m4_m4(slot->data.p, (const float(*)[4])mat);
351  }
352  else if (size == 3) {
353  copy_m4_m3(slot->data.p, (const float(*)[3])mat);
354  }
355  else {
356  fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
357 
358  zero_m4(slot->data.p);
359  }
360 }
361 
363  const char *slot_name,
364  float r_mat[4][4])
365 {
366  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
368  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
369  return;
370  }
371 
372  if (slot->data.p) {
373  copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
374  }
375  else {
376  unit_m4(r_mat);
377  }
378 }
379 
381  const char *slot_name,
382  float r_mat[3][3])
383 {
384  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
386  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
387  return;
388  }
389 
390  if (slot->data.p) {
391  copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
392  }
393  else {
394  unit_m3(r_mat);
395  }
396 }
397 
398 void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p)
399 {
400  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
402  if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
403  return;
404  }
405 
406  slot->data.p = p;
407 }
408 
410  const char *slot_name,
411  const float vec[3])
412 {
413  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
415  if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
416  return;
417  }
418 
419  copy_v3_v3(slot->data.vec, vec);
420 }
421 
422 float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
423 {
424  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
426  if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
427  return 0.0f;
428  }
429 
430  return slot->data.f;
431 }
432 
433 int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
434 {
435  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
437  if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
438  return 0;
439  }
440 
441  return slot->data.i;
442 }
443 
444 bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
445 {
446  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
448  if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
449  return 0;
450  }
451 
452  return slot->data.i;
453 }
454 
455 void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
456 {
457  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
458  void **ret;
459 
460  /* could add support for mapping type */
462 
463  ret = MEM_mallocN(sizeof(void *) * slot->len, __func__);
464  memcpy(ret, slot->data.buf, sizeof(void *) * slot->len);
465  *len = slot->len;
466  return ret;
467 }
468 
469 void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
470 {
471  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
473  if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
474  return NULL;
475  }
476 
477  return slot->data.p;
478 }
479 
480 void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
481 {
482  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
484  if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
485  return;
486  }
487 
488  copy_v3_v3(r_vec, slot->data.vec);
489 }
490 
491 /*
492  * BMO_COUNTFLAG
493  *
494  * Counts the number of elements of a certain type that have a
495  * specific flag enabled (or disabled if test_for_enabled is false).
496  */
497 
499  const char htype,
500  const short oflag,
501  const bool test_for_enabled)
502 {
503  int count_vert = 0, count_edge = 0, count_face = 0;
504 
505  if (htype & BM_VERT) {
506  BMIter iter;
507  BMVert *ele;
508  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
509  if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
510  count_vert++;
511  }
512  }
513  }
514  if (htype & BM_EDGE) {
515  BMIter iter;
516  BMEdge *ele;
517  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
518  if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
519  count_edge++;
520  }
521  }
522  }
523  if (htype & BM_FACE) {
524  BMIter iter;
525  BMFace *ele;
526  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
527  if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
528  count_face++;
529  }
530  }
531  }
532 
533  return (count_vert + count_edge + count_face);
534 }
535 
536 int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
537 {
538  return bmo_mesh_flag_count(bm, htype, oflag, true);
539 }
540 
541 int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
542 {
543  return bmo_mesh_flag_count(bm, htype, oflag, false);
544 }
545 
547  BMOperator *UNUSED(op),
548  const char htype,
549  const short oflag)
550 {
551  if (htype & BM_VERT) {
552  BMIter iter;
553  BMVert *ele;
554  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
556  }
557  }
558  if (htype & BM_EDGE) {
559  BMIter iter;
560  BMEdge *ele;
561  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
563  }
564  }
565  if (htype & BM_FACE) {
566  BMIter iter;
567  BMFace *ele;
568  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
570  }
571  }
572 }
573 
575  BMOpSlot *slot_vert_map,
576  BMOpSlot *slot_edge_map,
577  BMOpSlot *slot_face_map,
578  const bool check_select)
579 {
580  if (bm->selected.first) {
581  BMEditSelection *ese, *ese_next;
582  BMOpSlot *slot_elem_map;
583 
584  for (ese = bm->selected.first; ese; ese = ese_next) {
585  ese_next = ese->next;
586 
587  switch (ese->htype) {
588  case BM_VERT:
589  slot_elem_map = slot_vert_map;
590  break;
591  case BM_EDGE:
592  slot_elem_map = slot_edge_map;
593  break;
594  default:
595  slot_elem_map = slot_face_map;
596  break;
597  }
598 
599  ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
600 
601  if (UNLIKELY((ese->ele == NULL) ||
602  (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) {
603  BLI_remlink(&bm->selected, ese);
604  MEM_freeN(ese);
605  }
606  }
607  }
608 
609  if (bm->act_face) {
610  BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face);
611  if (f) {
612  bm->act_face = f;
613  }
614  }
615 }
616 
617 int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
618 {
619  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
621 
622  /* check if its actually a buffer */
623  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
624  return 0;
625  }
626 
627  return slot->len;
628 }
629 
630 int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
631 {
632  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
634  return BLI_ghash_len(slot->data.ghash);
635 }
636 
637 void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data)
638 {
639  (void)op; /* Ignored in release builds. */
640 
642  BMO_ASSERT_SLOT_IN_OP(slot, op);
643 
644  BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data);
645 }
646 
647 #if 0
648 void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
649 {
650  BMOpSlot *slot = &op->slots[slot_code];
651  void *tmp;
652  ssize_t allocsize;
653 
654  BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
655 
656  /* check if its actually a buffer */
657  if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF) {
658  return NULL;
659  }
660 
661  if (slot->flag & BMOS_DYNAMIC_ARRAY) {
662  if (slot->len >= slot->size) {
663  slot->size = (slot->size + 1 + totadd) * 2;
664 
665  allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] *
666  slot->size;
667  slot->data.buf = MEM_recallocN_id(slot->data.buf, allocsize, "opslot dynamic array");
668  }
669 
670  slot->len += totadd;
671  }
672  else {
673  slot->flag |= BMOS_DYNAMIC_ARRAY;
674  slot->len += totadd;
675  slot->size = slot->len + 2;
676 
677  allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] *
678  slot->len;
679 
680  tmp = slot->data.buf;
681  slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
682  memcpy(slot->data.buf, tmp, allocsize);
683  }
684 
685  return slot->data.buf;
686 }
687 #endif
688 
690  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
691  const char *slot_name,
692  const char htype,
693  const short oflag)
694 {
695  GHashIterator gh_iter;
696  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
697  BMElemF *ele_f;
698 
700 
701  GHASH_ITER (gh_iter, slot->data.ghash) {
702  ele_f = BLI_ghashIterator_getKey(&gh_iter);
703  if (ele_f->head.htype & htype) {
704  BMO_elem_flag_enable(bm, ele_f, oflag);
705  }
706  }
707 }
708 
710  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
711  const char *slot_name,
712  const int len)
713 {
714  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
715 
716  /* check if its actually a buffer */
717  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
718  return NULL;
719  }
720 
721  slot->len = len;
722  if (len) {
724  }
725  else {
726  slot->data.buf = NULL;
727  }
728 
729  return slot->data.buf;
730 }
731 
733  BMOperator *op,
734  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
735  const char *slot_name,
736  const char htype)
737 {
738  BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
739  int totelement = 0, i = 0;
740 
742  BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
743 
744  if (htype & BM_VERT) {
745  totelement += bm->totvert;
746  }
747  if (htype & BM_EDGE) {
748  totelement += bm->totedge;
749  }
750  if (htype & BM_FACE) {
751  totelement += bm->totface;
752  }
753 
754  if (totelement) {
755  BMIter iter;
756  BMHeader *ele;
757 
758  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
759 
760  /* TODO: collapse these loops into one. */
761 
762  if (htype & BM_VERT) {
763  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
764  output->data.buf[i] = ele;
765  i++;
766  }
767  }
768 
769  if (htype & BM_EDGE) {
770  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
771  output->data.buf[i] = ele;
772  i++;
773  }
774  }
775 
776  if (htype & BM_FACE) {
777  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
778  output->data.buf[i] = ele;
779  i++;
780  }
781  }
782  }
783 }
784 
792  BMOperator *op,
793  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
794  const char *slot_name,
795  const char htype,
796  const char hflag,
797  const bool test_for_enabled)
798 {
799  BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
800  int totelement = 0, i = 0;
801  const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) &&
802  ((hflag & BM_ELEM_HIDDEN) == 0);
803 
805  BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
806  BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
807 
808  if (test_for_enabled) {
809  totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
810  }
811  else {
812  totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide);
813  }
814 
815  if (totelement) {
816  BMIter iter;
817  BMElem *ele;
818 
819  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
820 
821  /* TODO: collapse these loops into one. */
822 
823  if (htype & BM_VERT) {
824  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
825  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
826  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
827  output->data.buf[i] = ele;
828  i++;
829  }
830  }
831  }
832 
833  if (htype & BM_EDGE) {
834  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
835  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
836  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
837  output->data.buf[i] = ele;
838  i++;
839  }
840  }
841  }
842 
843  if (htype & BM_FACE) {
844  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
845  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
846  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
847  output->data.buf[i] = ele;
848  i++;
849  }
850  }
851  }
852  }
853  else {
854  output->len = 0;
855  }
856 }
857 
859  BMOperator *op,
860  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
861  const char *slot_name,
862  const char htype,
863  const char hflag)
864 {
865  bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
866 }
867 
869  BMOperator *op,
870  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
871  const char *slot_name,
872  const char htype,
873  const char hflag)
874 {
875  bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
876 }
877 
879 {
880  BMO_ASSERT_SLOT_IN_OP(slot, op);
883  BLI_assert(ELEM(slot->len, 0, 1));
884 
885  BLI_assert(slot->slot_subtype.elem & ele->htype);
886 
887  slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */
888  slot->len = 1;
889  *slot->data.buf = ele;
890 }
891 
893  BMOpSlot *slot,
894  BMHeader **ele_buffer,
895  int ele_buffer_len)
896 {
897  BMO_ASSERT_SLOT_IN_OP(slot, op);
899  BLI_assert(ELEM(slot->len, 0, ele_buffer_len));
900 
901  if (slot->data.buf == NULL) {
902  slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len);
903  }
904 
905  slot->len = ele_buffer_len;
906  memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf));
907 }
908 
910 {
913  BLI_assert(ELEM(slot->len, 0, 1));
914 
915  return slot->len ? (BMHeader *)slot->data.buf[0] : NULL;
916 }
917 
919  const char *slot_name_dst,
920  BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
921  const char *slot_name_src,
922  struct MemArena *arena_dst)
923 {
924  BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
925  BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
926 
928  slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
929 
930  if (slot_dst->len == 0) {
931  /* output slot is empty, copy rather than append */
932  _bmo_slot_copy(slot_args_src, slot_name_src, slot_args_dst, slot_name_dst, arena_dst);
933  }
934  else if (slot_src->len != 0) {
935  int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type];
936  int alloc_size = elem_size * (slot_dst->len + slot_src->len);
937  /* allocate new buffer */
938  void *buf = BLI_memarena_alloc(arena_dst, alloc_size);
939 
940  /* copy slot data */
941  memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len);
942  memcpy(
943  ((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len);
944 
945  slot_dst->data.buf = buf;
946  slot_dst->len += slot_src->len;
947  }
948 }
949 
957  BMOperator *op,
958  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
959  const char *slot_name,
960  const char htype,
961  const short oflag,
962  const bool test_for_enabled)
963 {
964  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
965  int totelement, i = 0;
966 
967  BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
968 
970  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
972 
973  if (test_for_enabled) {
974  totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
975  }
976  else {
977  totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
978  }
979 
980  if (totelement) {
981  BMIter iter;
982  BMHeader *ele;
983  BMHeader **ele_array;
984 
985  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
986 
987  ele_array = (BMHeader **)slot->data.buf;
988 
989  /* TODO: collapse these loops into one. */
990 
991  if (htype & BM_VERT) {
992  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
993  if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) {
994  ele_array[i] = ele;
995  i++;
996  }
997  }
998  }
999 
1000  if (htype & BM_EDGE) {
1001  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
1002  if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) {
1003  ele_array[i] = ele;
1004  i++;
1005  }
1006  }
1007  }
1008 
1009  if (htype & BM_FACE) {
1010  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
1011  if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) {
1012  ele_array[i] = ele;
1013  i++;
1014  }
1015  }
1016  }
1017  }
1018  else {
1019  slot->len = 0;
1020  }
1021 }
1022 
1024  BMOperator *op,
1025  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1026  const char *slot_name,
1027  const char htype,
1028  const short oflag)
1029 {
1030  bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
1031 }
1032 
1034  BMOperator *op,
1035  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1036  const char *slot_name,
1037  const char htype,
1038  const short oflag)
1039 {
1040  bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
1041 }
1042 
1044  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1045  const char *slot_name,
1046  const char htype,
1047  const char hflag,
1048  const bool do_flush)
1049 {
1050  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1051  BMElem **data = (BMElem **)slot->data.buf;
1052  int i;
1053  const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
1054  const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
1055 
1057  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1059 
1060  for (i = 0; i < slot->len; i++, data++) {
1061  if (!(htype & (*data)->head.htype)) {
1062  continue;
1063  }
1064 
1065  if (do_flush_select) {
1066  BM_elem_select_set(bm, *data, true);
1067  }
1068 
1069  if (do_flush_hide) {
1070  BM_elem_hide_set(bm, *data, false);
1071  }
1072 
1073  BM_elem_flag_enable(*data, hflag);
1074  }
1075 }
1076 
1078  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1079  const char *slot_name,
1080  const char htype,
1081  const char hflag,
1082  const bool do_flush)
1083 {
1084  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1085  BMElem **data = (BMElem **)slot->data.buf;
1086  int i;
1087  const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
1088  const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
1089 
1091  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1092 
1093  for (i = 0; i < slot->len; i++, data++) {
1094  if (!(htype & (*data)->head.htype)) {
1095  continue;
1096  }
1097 
1098  if (do_flush_select) {
1099  BM_elem_select_set(bm, *data, false);
1100  }
1101 
1102  if (do_flush_hide) {
1103  BM_elem_hide_set(bm, *data, false);
1104  }
1105 
1106  BM_elem_flag_disable(*data, hflag);
1107  }
1108 }
1109 
1111  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1112  const char *slot_name,
1113  const char htype,
1114  const short oflag)
1115 {
1116  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1117  BMHeader **data = slot->data.p;
1118  int i;
1119 
1121  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1122 
1123  for (i = 0; i < slot->len; i++) {
1124  if (!(htype & data[i]->htype)) {
1125  continue;
1126  }
1127 
1129  }
1130 }
1131 
1133  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1134  const char *slot_name,
1135  const char htype,
1136  const short oflag)
1137 {
1138  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1139  BMHeader **data = (BMHeader **)slot->data.buf;
1140  int i;
1141 
1143  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1144 
1145  for (i = 0; i < slot->len; i++) {
1146  if (!(htype & data[i]->htype)) {
1147  continue;
1148  }
1149 
1151  }
1152 }
1153 
1168 {
1169  /* set the index values since we are looping over all data anyway,
1170  * may save time later on */
1171 
1172  BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
1173  BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
1174  BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
1175 
1176  /* store memcpy size for reuse */
1177  const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
1178 
1179  bm->totflags++;
1180 
1182  sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP);
1184  sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
1186  sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
1187 
1188  /* now go through and memcpy all the flags. Loops don't get a flag layer at this time. */
1189  BMIter iter;
1190  int i;
1191 
1192  BMVert_OFlag *v_oflag;
1193  BLI_mempool *newpool = bm->vtoolflagpool;
1194  BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
1195  void *oldflags = v_oflag->oflags;
1196  v_oflag->oflags = BLI_mempool_calloc(newpool);
1197  memcpy(v_oflag->oflags, oldflags, old_totflags_size);
1198  BM_elem_index_set(&v_oflag->base, i); /* set_inline */
1199  BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
1200  }
1201 
1202  BMEdge_OFlag *e_oflag;
1203  newpool = bm->etoolflagpool;
1204  BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
1205  void *oldflags = e_oflag->oflags;
1206  e_oflag->oflags = BLI_mempool_calloc(newpool);
1207  memcpy(e_oflag->oflags, oldflags, old_totflags_size);
1208  BM_elem_index_set(&e_oflag->base, i); /* set_inline */
1209  BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
1210  }
1211 
1212  BMFace_OFlag *f_oflag;
1213  newpool = bm->ftoolflagpool;
1214  BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
1215  void *oldflags = f_oflag->oflags;
1216  f_oflag->oflags = BLI_mempool_calloc(newpool);
1217  memcpy(f_oflag->oflags, oldflags, old_totflags_size);
1218  BM_elem_index_set(&f_oflag->base, i); /* set_inline */
1219  BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
1220  }
1221 
1222  BLI_mempool_destroy(voldpool);
1223  BLI_mempool_destroy(eoldpool);
1224  BLI_mempool_destroy(foldpool);
1225 
1227 }
1228 
1230 {
1231  /* set the index values since we are looping over all data anyway,
1232  * may save time later on */
1233 
1234  BLI_mempool *voldpool = bm->vtoolflagpool;
1235  BLI_mempool *eoldpool = bm->etoolflagpool;
1236  BLI_mempool *foldpool = bm->ftoolflagpool;
1237 
1238  /* store memcpy size for reuse */
1239  const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
1240 
1241  /* de-increment the totflags first. */
1242  bm->totflags--;
1243 
1244  bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP);
1245  bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
1246  bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
1247 
1248  /* now go through and memcpy all the flag */
1249  BMIter iter;
1250  int i;
1251 
1252  BMVert_OFlag *v_oflag;
1253  BLI_mempool *newpool = bm->vtoolflagpool;
1254  BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
1255  void *oldflags = v_oflag->oflags;
1256  v_oflag->oflags = BLI_mempool_alloc(newpool);
1257  memcpy(v_oflag->oflags, oldflags, new_totflags_size);
1258  BM_elem_index_set(&v_oflag->base, i); /* set_inline */
1259  BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
1260  }
1261 
1262  BMEdge_OFlag *e_oflag;
1263  newpool = bm->etoolflagpool;
1264  BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
1265  void *oldflags = e_oflag->oflags;
1266  e_oflag->oflags = BLI_mempool_alloc(newpool);
1267  memcpy(e_oflag->oflags, oldflags, new_totflags_size);
1268  BM_elem_index_set(&e_oflag->base, i); /* set_inline */
1269  BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
1270  }
1271 
1272  BMFace_OFlag *f_oflag;
1273  newpool = bm->ftoolflagpool;
1274  BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
1275  void *oldflags = f_oflag->oflags;
1276  f_oflag->oflags = BLI_mempool_alloc(newpool);
1277  memcpy(f_oflag->oflags, oldflags, new_totflags_size);
1278  BM_elem_index_set(&f_oflag->base, i); /* set_inline */
1279  BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
1280  }
1281 
1282  BLI_mempool_destroy(voldpool);
1283  BLI_mempool_destroy(eoldpool);
1284  BLI_mempool_destroy(foldpool);
1285 
1287 }
1288 
1290 {
1291  /* set the index values since we are looping over all data anyway,
1292  * may save time later on */
1293  const BMFlagLayer zero_flag = {0};
1294 
1295  const int totflags_offset = bm->totflags - 1;
1296 
1297  /* now go through and memcpy all the flag */
1298  {
1299  BMIter iter;
1300  BMVert_OFlag *ele;
1301  int i;
1302  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
1303  ele->oflags[totflags_offset] = zero_flag;
1304  BM_elem_index_set(&ele->base, i); /* set_inline */
1305  }
1306  }
1307  {
1308  BMIter iter;
1309  BMEdge_OFlag *ele;
1310  int i;
1311  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
1312  ele->oflags[totflags_offset] = zero_flag;
1313  BM_elem_index_set(&ele->base, i); /* set_inline */
1314  }
1315  }
1316  {
1317  BMIter iter;
1318  BMFace_OFlag *ele;
1319  int i;
1320  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
1321  ele->oflags[totflags_offset] = zero_flag;
1322  BM_elem_index_set(&ele->base, i); /* set_inline */
1323  }
1324  }
1325 
1327 }
1328 
1329 void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
1330 {
1331  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1332 
1333  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
1334  return NULL;
1335  }
1336 
1337  return slot->data.buf ? *slot->data.buf : NULL;
1338 }
1339 
1340 void *BMO_iter_new(BMOIter *iter,
1341  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1342  const char *slot_name,
1343  const char restrictmask)
1344 {
1345  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1346 
1347  memset(iter, 0, sizeof(BMOIter));
1348 
1349  iter->slot = slot;
1350  iter->cur = 0;
1351  iter->restrictmask = restrictmask;
1352 
1353  if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) {
1354  BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
1355  }
1356  else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
1357  BLI_assert(restrictmask & slot->slot_subtype.elem);
1358  }
1359  else {
1360  BLI_assert(0);
1361  }
1362 
1363  return BMO_iter_step(iter);
1364 }
1365 
1367 {
1368  BMOpSlot *slot = iter->slot;
1369  if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
1370  BMHeader *ele;
1371 
1372  if (iter->cur >= slot->len) {
1373  return NULL;
1374  }
1375 
1376  ele = slot->data.buf[iter->cur++];
1377  while (!(iter->restrictmask & ele->htype)) {
1378  if (iter->cur >= slot->len) {
1379  return NULL;
1380  }
1381 
1382  ele = slot->data.buf[iter->cur++];
1383  BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
1384  }
1385 
1386  BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
1387 
1388  return ele;
1389  }
1390  if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
1391  void *ret;
1392 
1393  if (BLI_ghashIterator_done(&iter->giter) == false) {
1395  iter->val = BLI_ghashIterator_getValue_p(&iter->giter);
1396 
1397  BLI_ghashIterator_step(&iter->giter);
1398  }
1399  else {
1400  ret = NULL;
1401  iter->val = NULL;
1402  }
1403 
1404  return ret;
1405  }
1406  BLI_assert(0);
1407 
1408  return NULL;
1409 }
1410 
1411 /* used for iterating over mappings */
1412 
1414 {
1415  return iter->val;
1416 }
1417 
1419 {
1423  return iter->val ? *iter->val : NULL;
1424 }
1425 
1427 {
1429  return **((float **)iter->val);
1430 }
1431 
1433 {
1435  return **((int **)iter->val);
1436 }
1437 
1439 {
1441  return **((bool **)iter->val);
1442 }
1443 
1444 /* error system */
1445 typedef struct BMOpError {
1446  struct BMOpError *next, *prev;
1448  const char *msg;
1451 
1453 {
1454  while (BMO_error_pop(bm, NULL, NULL, NULL)) {
1455  /* pass */
1456  }
1457 }
1458 
1460 {
1461  BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
1462 
1463  err->msg = msg;
1464  err->op = owner;
1465  err->level = level;
1466 
1468 }
1469 
1471 {
1472  for (const BMOpError *err = bm->errorstack.first; err; err = err->next) {
1473  if (err->level == level) {
1474  return true;
1475  }
1476  }
1477  return false;
1478 }
1479 
1480 bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
1481 {
1483  if (err == NULL) {
1484  return false;
1485  }
1486 
1487  if (r_msg) {
1488  *r_msg = err->msg;
1489  }
1490  if (r_op) {
1491  *r_op = err->op;
1492  }
1493  if (r_level) {
1494  *r_level = err->level;
1495  }
1496 
1497  return true;
1498 }
1499 
1502  const char **r_msg,
1503  BMOperator **r_op)
1504 {
1505  for (BMOpError *err = bm->errorstack.first; err; err = err->next) {
1506  if (err->level >= level) {
1507  if (r_msg) {
1508  *r_msg = err->msg;
1509  }
1510  if (r_op) {
1511  *r_op = err->op;
1512  }
1513  return true;
1514  }
1515  }
1516 
1517  return false;
1518 }
1519 
1520 bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
1521 {
1522  bool result = BMO_error_get(bm, r_msg, r_op, r_level);
1523 
1524  if (result) {
1526 
1528  MEM_freeN(err);
1529  }
1530 
1531  return result;
1532 }
1533 
1534 #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
1535 
1536 static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
1537 {
1538  int i = 0;
1539 
1540  while (slot_args->slot_name) {
1541  if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) {
1542  return i;
1543  }
1544  slot_args++;
1545  i++;
1546  }
1547 
1548  return -1;
1549 }
1550 
1551 static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
1552 {
1553  int i = bmo_name_to_slotcode(slot_args, identifier);
1554  if (i < 0) {
1555  fprintf(stderr,
1556  "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n",
1557  __func__,
1558  identifier);
1559  }
1560 
1561  return i;
1562 }
1563 
1564 int BMO_opcode_from_opname(const char *opname)
1565 {
1566 
1567  const uint tot = bmo_opdefines_total;
1568  uint i;
1569  for (i = 0; i < tot; i++) {
1570  if (STREQ(bmo_opdefines[i]->opname, opname)) {
1571  return i;
1572  }
1573  }
1574  return -1;
1575 }
1576 
1577 static int BMO_opcode_from_opname_check(const char *opname)
1578 {
1579  int i = BMO_opcode_from_opname(opname);
1580  if (i == -1) {
1581  fprintf(stderr,
1582  "%s: could not find bmesh slot for name %s! (bmesh internal error)\n",
1583  __func__,
1584  opname);
1585  }
1586  return i;
1587 }
1588 
1589 bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
1590 {
1591  // BMOpDefine *def;
1592  char *opname, *ofmt, *fmt;
1593  char slot_name[64] = {0};
1594  int i, type;
1595  bool noslot, state;
1596 
1597  /* basic useful info to help find where bmop formatting strings fail */
1598  const char *err_reason = "Unknown";
1599  int lineno = -1;
1600 
1601 #define GOTO_ERROR(reason) \
1602  { \
1603  err_reason = reason; \
1604  lineno = __LINE__; \
1605  goto error; \
1606  } \
1607  (void)0
1608 
1609  /* we muck around in here, so dup it */
1610  fmt = ofmt = BLI_strdup(_fmt);
1611 
1612  /* find operator name */
1613  i = strcspn(fmt, " ");
1614 
1615  opname = fmt;
1616  noslot = (opname[i] == '\0');
1617  opname[i] = '\0';
1618 
1619  fmt += i + (noslot ? 0 : 1);
1620 
1621  i = BMO_opcode_from_opname_check(opname);
1622 
1623  if (i == -1) {
1624  MEM_freeN(ofmt);
1625  BLI_assert(0);
1626  return false;
1627  }
1628 
1629  BMO_op_init(bm, op, flag, opname);
1630  // def = bmo_opdefines[i];
1631 
1632  i = 0;
1633  state = true; /* false: not inside slot_code name, true: inside slot_code name */
1634 
1635  while (*fmt) {
1636  if (state) {
1637  /* Jump past leading white-space. */
1638  i = strspn(fmt, " ");
1639  fmt += i;
1640 
1641  /* Ignore trailing white-space. */
1642  if (!fmt[i]) {
1643  break;
1644  }
1645 
1646  /* find end of slot name, only "slot=%f", can be used */
1647  i = strcspn(fmt, "=");
1648  if (!fmt[i]) {
1649  GOTO_ERROR("could not match end of slot name");
1650  }
1651 
1652  fmt[i] = 0;
1653 
1654  if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) {
1655  GOTO_ERROR("name to slot code check failed");
1656  }
1657 
1658  BLI_strncpy(slot_name, fmt, sizeof(slot_name));
1659 
1660  state = false;
1661  fmt += i;
1662  }
1663  else {
1664  switch (*fmt) {
1665  case ' ':
1666  case '=':
1667  case '%':
1668  break;
1669  case 'm': {
1670  int size;
1671  const char c = NEXT_CHAR(fmt);
1672  fmt++;
1673 
1674  if (c == '3') {
1675  size = 3;
1676  }
1677  else if (c == '4') {
1678  size = 4;
1679  }
1680  else {
1681  GOTO_ERROR("matrix size was not 3 or 4");
1682  }
1683 
1684  BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
1685  state = true;
1686  break;
1687  }
1688  case 'v': {
1689  BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
1690  state = true;
1691  break;
1692  }
1693  case 'e': {
1694  BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
1695 
1696  if (NEXT_CHAR(fmt) == 'b') {
1697  BMHeader **ele_buffer = va_arg(vlist, void *);
1698  int ele_buffer_len = va_arg(vlist, int);
1699 
1700  BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len);
1701  fmt++;
1702  }
1703  else {
1704  /* single vert/edge/face */
1705  BMHeader *ele = va_arg(vlist, void *);
1706 
1707  BMO_slot_buffer_from_single(op, slot, ele);
1708  }
1709 
1710  state = true;
1711  break;
1712  }
1713  case 's':
1714  case 'S': {
1715  BMOperator *op_other = va_arg(vlist, void *);
1716  const char *slot_name_other = va_arg(vlist, char *);
1717 
1718  if (*fmt == 's') {
1719  BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1);
1720  BMO_slot_copy(op_other, slots_in, slot_name_other, op, slots_in, slot_name);
1721  }
1722  else {
1723  BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1);
1724  BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name);
1725  }
1726  state = true;
1727  break;
1728  }
1729  case 'i':
1730  BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
1731  state = true;
1732  break;
1733  case 'b':
1734  BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
1735  state = true;
1736  break;
1737  case 'p':
1738  BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
1739  state = true;
1740  break;
1741  case 'f':
1742  case 'F':
1743  case 'h':
1744  case 'H':
1745  case 'a':
1746  type = *fmt;
1747 
1748  if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
1749  BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
1750  }
1751  else {
1752  char htype = 0;
1753 
1754  while (1) {
1755  char htype_set;
1756  const char c = NEXT_CHAR(fmt);
1757  if (c == 'f') {
1758  htype_set = BM_FACE;
1759  }
1760  else if (c == 'e') {
1761  htype_set = BM_EDGE;
1762  }
1763  else if (c == 'v') {
1764  htype_set = BM_VERT;
1765  }
1766  else {
1767  break;
1768  }
1769 
1770  if (UNLIKELY(htype & htype_set)) {
1771  GOTO_ERROR("htype duplicated");
1772  }
1773 
1774  htype |= htype_set;
1775  fmt++;
1776  }
1777 
1778  if (type == 'h') {
1780  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1781  }
1782  else if (type == 'H') {
1784  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1785  }
1786  else if (type == 'a') {
1787  if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) {
1788  BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype);
1789  }
1790  else {
1792  bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN);
1793  }
1794  }
1795  else if (type == 'f') {
1797  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1798  }
1799  else if (type == 'F') {
1801  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1802  }
1803  }
1804 
1805  state = true;
1806  break;
1807  default:
1808  fprintf(stderr,
1809  "%s: unrecognized bmop format char: '%c', %d in '%s'\n",
1810  __func__,
1811  *fmt,
1812  (int)(fmt - ofmt),
1813  ofmt);
1814  break;
1815  }
1816  }
1817  fmt++;
1818  }
1819 
1820  MEM_freeN(ofmt);
1821  return true;
1822 error:
1823 
1824  /* TODO: explain exactly what is failing (not urgent). */
1825  fprintf(stderr, "%s: error parsing formatting string\n", __func__);
1826 
1827  fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
1828  fprintf(stderr, " ");
1829  {
1830  int pos = (int)(fmt - ofmt);
1831  for (i = 0; i < pos; i++) {
1832  fprintf(stderr, " ");
1833  }
1834  fprintf(stderr, "^\n");
1835  }
1836 
1837  fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno);
1838 
1839  fprintf(stderr, "reason: %s\n", err_reason);
1840 
1841  MEM_freeN(ofmt);
1842 
1843  BMO_op_finish(bm, op);
1844  return false;
1845 
1846 #undef GOTO_ERROR
1847 }
1848 
1849 bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...)
1850 {
1851  va_list list;
1852 
1853  va_start(list, fmt);
1854  if (!BMO_op_vinitf(bm, op, flag, fmt, list)) {
1855  printf("%s: failed\n", __func__);
1856  va_end(list);
1857  return false;
1858  }
1859  va_end(list);
1860 
1861  return true;
1862 }
1863 
1864 bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
1865 {
1866  va_list list;
1867  BMOperator op;
1868 
1869  va_start(list, fmt);
1870  if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) {
1871  printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
1872  va_end(list);
1873  return false;
1874  }
1875 
1876  BMO_op_exec(bm, &op);
1877  BMO_op_finish(bm, &op);
1878 
1879  va_end(list);
1880  return true;
1881 }
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:298
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition: BLI_ghash.c:914
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
BLI_INLINE void ** BLI_ghashIterator_getValue_p(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:306
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:705
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
Definition: BLI_ghash.c:898
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:310
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void zero_m4(float m[4][4])
Definition: math_matrix.c:28
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
MINLINE void copy_v3_v3(float r[3], const float a[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:20
void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:76
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:116
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:99
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition: BLI_mempool.c:253
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition: BLI_mempool.c:319
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
void * BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition: BLI_mempool.c:347
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned int uint
Definition: BLI_sys_types.h:67
#define STREQLEN(a, b, n)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
SSIZE_T ssize_t
Definition: BLI_winstuff.h:71
_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
Read Guarded memory(de)allocation.
#define BM_ALL_NOLOOP
Definition: bmesh_class.h:411
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
struct BMFlagLayer BMFlagLayer
eBMOpErrorLevel
Definition: bmesh_error.h:16
#define BM_ELEM_INDEX_VALIDATE(_bm, _msg_a, _msg_b)
Definition: bmesh_error.h:66
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:15
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_test_bool(ele, hflag)
Definition: bmesh_inline.h:13
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
#define BM_elem_hide_set(bm, ele, hide)
Definition: bmesh_marking.h:27
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
Definition: bmesh_mesh.cc:75
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
Definition: bmesh_mesh.cc:272
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BMesh End Edit.
Definition: bmesh_mesh.cc:292
const int bmo_opdefines_total
const BMOpDefine * bmo_opdefines[]
#define BMO_elem_flag_disable(bm, ele, oflag)
#define BMO_edge_flag_test_bool(bm, e, oflag)
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_face_flag_test_bool(bm, e, oflag)
eBMOpSlotSubType_Elem
@ BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE
@ BMO_OP_SLOT_ELEMENT_BUF
@ BMO_OP_SLOT_PTR
@ BMO_OP_SLOT_BOOL
@ BMO_OP_SLOT_FLT
@ BMO_OP_SLOT_INT
@ BMO_OP_SLOT_VEC
@ BMO_OP_SLOT_MAPPING
@ BMO_OP_SLOT_MAT
#define MAX_SLOTNAME
@ BMO_OP_SLOT_SUBTYPE_MAP_ELEM
@ BMO_OP_SLOT_SUBTYPE_MAP_BOOL
@ BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL
@ BMO_OP_SLOT_SUBTYPE_MAP_INT
@ BMO_OP_SLOT_SUBTYPE_MAP_FLT
@ BMO_FLAG_RESPECT_HIDE
#define BMO_ASSERT_SLOT_IN_OP(slot, op)
#define BMO_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst)
@ BMO_OP_SLOT_SUBTYPE_INT_FLAG
@ BMO_OP_SLOT_SUBTYPE_INT_ENUM
#define BMO_OP_MAX_SLOTS
#define BMO_SLOT_AS_MATRIX(slot)
#define BMO_elem_flag_enable(bm, ele, oflag)
#define BMO_OP_SLOT_TOTAL_TYPES
#define BMO_vert_flag_test_bool(bm, e, oflag)
#define BMO_face_flag_disable(bm, e, oflag)
#define BMO_edge_flag_disable(bm, e, oflag)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4])
void * BMO_iter_new(BMOIter *iter, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask)
New Iterator.
void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const bool do_flush)
BMO_FLAG_BUFFER.
void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, struct MemArena *arena_dst)
BMESH OPSTACK COPY SLOT.
void * BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_buffer_flag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
BMO_FLAG_BUFFER.
static void bmo_flag_layer_alloc(BMesh *bm)
ALLOC/FREE FLAG LAYER.
void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3])
void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype)
BMO_ALL_TO_SLOT.
int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i)
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag)
void * BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len)
bool BMO_iter_map_value_bool(BMOIter *iter)
void BMO_mesh_selected_remap(BMesh *bm, BMOpSlot *slot_vert_map, BMOpSlot *slot_edge_map, BMOpSlot *slot_face_map, const bool check_select)
void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size)
static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
void BMO_error_clear(BMesh *bm)
void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag)
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
void * BMO_iter_step(BMOIter *iter)
bool BMO_error_get_at_level(BMesh *bm, eBMOpErrorLevel level, const char **r_msg, BMOperator **r_op)
int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void * BMO_slot_buffer_get_single(BMOpSlot *slot)
static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele)
void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, struct MemArena *arena_dst)
static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const bool test_for_enabled)
BMO_HEADERFLAG_TO_SLOT.
int BMO_iter_map_value_int(BMOIter *iter)
void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const bool do_flush)
BMO_FLAG_BUFFER.
static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag, const bool test_for_enabled)
BMO_FLAG_TO_SLOT.
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
void BMO_pop(BMesh *bm)
BMESH OPSTACK POP.
struct BMOpError BMOpError
bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt,...)
static void bmo_flag_layer_clear(BMesh *bm)
void * BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
int BMO_opcode_from_opname(const char *opname)
bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
void ** BMO_iter_map_value_p(BMOIter *iter)
static int BMO_opcode_from_opname_check(const char *opname)
const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]
float BMO_iter_map_value_float(BMOIter *iter)
void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3])
void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f)
bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level)
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, const bool test_for_enabled)
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data)
int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define NEXT_CHAR(fmt)
#define GOTO_ERROR(reason)
void * BMO_iter_map_value_ptr(BMOIter *iter)
void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg)
void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p)
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
void * BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
void BMO_slot_buffer_flag_disable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
BMO_FLAG_BUFFER.
static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
static void bmo_flag_layer_free(BMesh *bm)
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK HAS SLOT.
bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
BMESH OPSTACK INIT OP.
bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt,...)
#define BM_ELEM_API_FLAG_CLEAR(element)
Definition: bmesh_private.h:77
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
uint pos
ccl_global KernelShaderEvalInput ccl_global float * output
const int state
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_recallocN_id)(void *vmemh, size_t len, const char *str)
Definition: mallocn.c:30
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static void error(const char *str)
Definition: meshlaplacian.c:51
static unsigned c
Definition: RandGen.cpp:83
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
return ret
struct BMFlagLayer * oflags
Definition: bmesh_class.h:141
struct BMEditSelection * next
Definition: bmesh_marking.h:10
BMHeader head
Definition: bmesh_class.h:238
struct BMFlagLayer * oflags
Definition: bmesh_class.h:287
char htype
Definition: bmesh_class.h:64
BMOpSlot * slot
GHashIterator giter
BMO_FlagSet * enum_flags
eBMOpSlotSubType_Union subtype
eBMOpSlotType type
char name[MAX_SLOTNAME]
BMOpTypeFlag type_flag
const char * opname
BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]
BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]
void(* exec)(BMesh *bm, BMOperator *op)
BMOperator * op
struct BMOpError * next
const char * msg
struct BMOpError * prev
eBMOpErrorLevel level
eBMOpSlotSubType_Union slot_subtype
eBMOpSlotType slot_type
struct BMOpSlot::@145::@146 enum_data
union BMOpSlot::@145 data
const char * slot_name
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct MemArena * arena
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
void(* exec)(BMesh *bm, struct BMOperator *op)
BMOpTypeFlag type_flag
struct BMFlagLayer * oflags
Definition: bmesh_class.h:102
int totvert
Definition: bmesh_class.h:297
int totflags
Definition: bmesh_class.h:355
char elem_index_dirty
Definition: bmesh_class.h:305
int totedge
Definition: bmesh_class.h:297
struct BLI_mempool * vtoolflagpool
Definition: bmesh_class.h:331
ListBase selected
Definition: bmesh_class.h:356
struct BLI_mempool * etoolflagpool
Definition: bmesh_class.h:331
BMFace * act_face
Definition: bmesh_class.h:366
struct BLI_mempool * ftoolflagpool
Definition: bmesh_class.h:331
int totface
Definition: bmesh_class.h:297
int toolflag_index
Definition: bmesh_class.h:335
ListBase errorstack
Definition: bmesh_class.h:369
void * first
Definition: DNA_listBase.h:31
eBMOpSlotSubType_Int intg
eBMOpSlotSubType_Elem elem
eBMOpSlotSubType_Map map
static FT_Error err