Blender  V2.93
bmesh_operators.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 "MEM_guardedalloc.h"
24 
25 #include "BLI_listbase.h"
26 #include "BLI_math.h"
27 #include "BLI_memarena.h"
28 #include "BLI_mempool.h"
29 #include "BLI_string.h"
30 #include "BLI_utildefines.h"
31 
32 #include "BLT_translation.h"
33 
34 #include "bmesh.h"
35 #include "intern/bmesh_private.h"
36 
37 /* forward declarations */
38 static void bmo_flag_layer_alloc(BMesh *bm);
39 static void bmo_flag_layer_free(BMesh *bm);
40 static void bmo_flag_layer_clear(BMesh *bm);
41 static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
43  const char *identifier);
44 
45 static const char *bmo_error_messages[] = {
46  NULL,
47  N_("Could not connect vertices"),
48  N_("Could not dissolve faces"),
49  N_("Invalid selection"),
50  N_("Internal mesh error"),
51  N_("Convex hull failed"),
52 };
53 
55 
56 /* operator slot type information - size of one element of the type given. */
58  0, /* 0: BMO_OP_SLOT_SENTINEL */
59  sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
60  sizeof(int), /* 2: BMO_OP_SLOT_INT */
61  sizeof(float), /* 3: BMO_OP_SLOT_FLT */
62  sizeof(void *), /* 4: BMO_OP_SLOT_PNT */
63  sizeof(void *), /* 5: BMO_OP_SLOT_PNT */
64  0, /* 6: unused */
65  0, /* 7: unused */
66  sizeof(float[3]), /* 8: BMO_OP_SLOT_VEC */
67  sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
68  sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */
69 };
70 
71 /* Dummy slot so there is something to return when slot name lookup fails */
72 // static BMOpSlot BMOpEmptySlot = {0};
73 
74 void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
75 {
76  op->flag |= op_flag;
77 }
78 
79 void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
80 {
81  op->flag &= ~op_flag;
82 }
83 
90 {
91  bm->toolflag_index++;
92 
93  BLI_assert(bm->totflags > 0);
94 
95  /* add flag layer, if appropriate */
96  if (bm->toolflag_index > 0) {
98  }
99  else {
101  }
102 }
103 
112 {
113  if (bm->toolflag_index > 0) {
115  }
116 
117  bm->toolflag_index--;
118 }
119 
120 /* use for both slot_types_in and slot_types_out */
121 static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
122 {
123  BMOpSlot *slot;
124  uint i;
125  for (i = 0; slot_types[i].type; i++) {
126  slot = &slot_args[i];
127  slot->slot_name = slot_types[i].name;
128  slot->slot_type = slot_types[i].type;
129  slot->slot_subtype = slot_types[i].subtype;
130  // slot->index = i; // UNUSED
131 
132  switch (slot->slot_type) {
133  case BMO_OP_SLOT_MAPPING:
134  slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
135  break;
136  case BMO_OP_SLOT_INT:
137  if (ELEM(slot->slot_subtype.intg,
140  slot->data.enum_data.flags = slot_types[i].enum_flags;
141  /* Set the first value of the enum as the default value. */
142  slot->data.i = slot->data.enum_data.flags[0].value;
143  }
144  default:
145  break;
146  }
147  }
148 }
149 
150 static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
151 {
152  BMOpSlot *slot;
153  uint i;
154  for (i = 0; slot_types[i].type; i++) {
155  slot = &slot_args[i];
156  switch (slot->slot_type) {
157  case BMO_OP_SLOT_MAPPING:
158  BLI_ghash_free(slot->data.ghash, NULL, NULL);
159  break;
160  default:
161  break;
162  }
163  }
164 }
165 
171 void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
172 {
173  int opcode = BMO_opcode_from_opname(opname);
174 
175 #ifdef DEBUG
176  BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
177 #else
178  (void)bm;
179 #endif
180 
181  if (opcode == -1) {
182  opcode = 0; /* error!, already printed, have a better way to handle this? */
183  }
184 
185  memset(op, 0, sizeof(BMOperator));
186  op->type = opcode;
187  op->type_flag = bmo_opdefines[opcode]->type_flag;
188  op->flag = flag;
189 
190  /* initialize the operator slot types */
191  bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in);
192  bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out);
193 
194  /* callback */
195  op->exec = bmo_opdefines[opcode]->exec;
196 
197  /* memarena, used for operator's slot buffers */
200 }
201 
212 {
213  /* allocate tool flags on demand */
215 
216  BMO_push(bm, op);
217 
218  if (bm->toolflag_index == 1) {
220  }
221  op->exec(bm, op);
222 
223  if (bm->toolflag_index == 1) {
225  }
226 
227  BMO_pop(bm);
228 }
229 
236 {
239 
241 
242 #ifdef DEBUG
243  BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname);
244 
245  /* avoid accidental re-use */
246  memset(op, 0xff, sizeof(*op));
247 #else
248  (void)bm;
249 #endif
250 }
251 
257 bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
258 {
259  int slot_code = bmo_name_to_slotcode(slot_args, identifier);
260  return (slot_code >= 0);
261 }
262 
268 BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
269 {
270  int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
271 
272  if (UNLIKELY(slot_code < 0)) {
273  // return &BMOpEmptySlot;
274  BLI_assert(0);
275  return NULL; /* better crash */
276  }
277 
278  return &slot_args[slot_code];
279 }
280 
288  const char *slot_name_src,
289  BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
290  const char *slot_name_dst,
291  struct MemArena *arena_dst)
292 {
293  BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
294  BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
295 
296  if (slot_src == slot_dst) {
297  return;
298  }
299 
300  BLI_assert(slot_src->slot_type == slot_dst->slot_type);
301  if (slot_src->slot_type != slot_dst->slot_type) {
302  return;
303  }
304 
305  if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
306  /* do buffer copy */
307  slot_dst->data.buf = NULL;
308  slot_dst->len = slot_src->len;
309  if (slot_dst->len) {
310  /* check dest has all flags enabled that the source has */
311  const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP);
312  const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP);
313 
314  if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) {
315  /* pass */
316  }
317  else {
318  /* check types */
319  const uint tot = slot_src->len;
320  uint i;
321  uint out = 0;
322  BMElem **ele_src = (BMElem **)slot_src->data.buf;
323  for (i = 0; i < tot; i++, ele_src++) {
324  if ((*ele_src)->head.htype & dst_elem_flag) {
325  out++;
326  }
327  }
328  if (out != tot) {
329  slot_dst->len = out;
330  }
331  }
332 
333  if (slot_dst->len) {
334  const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len;
335  slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size);
336  if (slot_src->len == slot_dst->len) {
337  memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size);
338  }
339  else {
340  /* only copy compatible elements */
341  const uint tot = slot_src->len;
342  uint i;
343  BMElem **ele_src = (BMElem **)slot_src->data.buf;
344  BMElem **ele_dst = (BMElem **)slot_dst->data.buf;
345  for (i = 0; i < tot; i++, ele_src++) {
346  if ((*ele_src)->head.htype & dst_elem_flag) {
347  *ele_dst = *ele_src;
348  ele_dst++;
349  }
350  }
351  }
352  }
353  }
354  }
355  else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
356  GHashIterator gh_iter;
357  GHASH_ITER (gh_iter, slot_src->data.ghash) {
358  void *key = BLI_ghashIterator_getKey(&gh_iter);
359  void *val = BLI_ghashIterator_getValue(&gh_iter);
360  BLI_ghash_insert(slot_dst->data.ghash, key, val);
361  }
362  }
363  else {
364  slot_dst->data = slot_src->data;
365  }
366 }
367 
368 /*
369  * BMESH OPSTACK SET XXX
370  *
371  * Sets the value of a slot depending on its type
372  */
373 
374 void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f)
375 {
376  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
378  if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
379  return;
380  }
381 
382  slot->data.f = f;
383 }
384 
385 void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
386 {
387  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
389  if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
390  return;
391  }
392 
393  slot->data.i = i;
394 }
395 
396 void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i)
397 {
398  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
400  if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
401  return;
402  }
403 
404  slot->data.i = i;
405 }
406 
407 /* only supports square mats */
409  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
410  const char *slot_name,
411  const float *mat,
412  int size)
413 {
414  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
416  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
417  return;
418  }
419 
420  slot->len = 4;
421  slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float[4][4]));
422 
423  if (size == 4) {
424  copy_m4_m4(slot->data.p, (float(*)[4])mat);
425  }
426  else if (size == 3) {
427  copy_m4_m3(slot->data.p, (float(*)[3])mat);
428  }
429  else {
430  fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
431 
432  zero_m4(slot->data.p);
433  }
434 }
435 
437  const char *slot_name,
438  float r_mat[4][4])
439 {
440  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
442  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
443  return;
444  }
445 
446  if (slot->data.p) {
447  copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
448  }
449  else {
450  unit_m4(r_mat);
451  }
452 }
453 
455  const char *slot_name,
456  float r_mat[3][3])
457 {
458  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
460  if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
461  return;
462  }
463 
464  if (slot->data.p) {
465  copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
466  }
467  else {
468  unit_m3(r_mat);
469  }
470 }
471 
472 void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p)
473 {
474  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
476  if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
477  return;
478  }
479 
480  slot->data.p = p;
481 }
482 
484  const char *slot_name,
485  const float vec[3])
486 {
487  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
489  if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
490  return;
491  }
492 
493  copy_v3_v3(slot->data.vec, vec);
494 }
495 
496 float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
497 {
498  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
500  if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
501  return 0.0f;
502  }
503 
504  return slot->data.f;
505 }
506 
507 int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
508 {
509  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
511  if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
512  return 0;
513  }
514 
515  return slot->data.i;
516 }
517 
518 bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
519 {
520  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
522  if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
523  return 0;
524  }
525 
526  return slot->data.i;
527 }
528 
529 /* if you want a copy of the elem buffer */
530 void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
531 {
532  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
533  void **ret;
534 
535  /* could add support for mapping type */
537 
538  ret = MEM_mallocN(sizeof(void *) * slot->len, __func__);
539  memcpy(ret, slot->data.buf, sizeof(void *) * slot->len);
540  *len = slot->len;
541  return ret;
542 }
543 
544 void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
545 {
546  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
548  if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
549  return NULL;
550  }
551 
552  return slot->data.p;
553 }
554 
555 void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
556 {
557  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
559  if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
560  return;
561  }
562 
563  copy_v3_v3(r_vec, slot->data.vec);
564 }
565 
566 /*
567  * BMO_COUNTFLAG
568  *
569  * Counts the number of elements of a certain type that have a
570  * specific flag enabled (or disabled if test_for_enabled is false).
571  */
572 
574  const char htype,
575  const short oflag,
576  const bool test_for_enabled)
577 {
578  int count_vert = 0, count_edge = 0, count_face = 0;
579 
580  if (htype & BM_VERT) {
581  BMIter iter;
582  BMVert *ele;
583  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
584  if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
585  count_vert++;
586  }
587  }
588  }
589  if (htype & BM_EDGE) {
590  BMIter iter;
591  BMEdge *ele;
592  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
593  if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
594  count_edge++;
595  }
596  }
597  }
598  if (htype & BM_FACE) {
599  BMIter iter;
600  BMFace *ele;
601  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
602  if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
603  count_face++;
604  }
605  }
606  }
607 
608  return (count_vert + count_edge + count_face);
609 }
610 
611 int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
612 {
613  return bmo_mesh_flag_count(bm, htype, oflag, true);
614 }
615 
616 int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
617 {
618  return bmo_mesh_flag_count(bm, htype, oflag, false);
619 }
620 
622  BMOperator *UNUSED(op),
623  const char htype,
624  const short oflag)
625 {
626  if (htype & BM_VERT) {
627  BMIter iter;
628  BMVert *ele;
629  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
631  }
632  }
633  if (htype & BM_EDGE) {
634  BMIter iter;
635  BMEdge *ele;
636  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
638  }
639  }
640  if (htype & BM_FACE) {
641  BMIter iter;
642  BMFace *ele;
643  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
645  }
646  }
647 }
648 
650  BMOpSlot *slot_vert_map,
651  BMOpSlot *slot_edge_map,
652  BMOpSlot *slot_face_map,
653  const bool check_select)
654 {
655  if (bm->selected.first) {
656  BMEditSelection *ese, *ese_next;
657  BMOpSlot *slot_elem_map;
658 
659  for (ese = bm->selected.first; ese; ese = ese_next) {
660  ese_next = ese->next;
661 
662  switch (ese->htype) {
663  case BM_VERT:
664  slot_elem_map = slot_vert_map;
665  break;
666  case BM_EDGE:
667  slot_elem_map = slot_edge_map;
668  break;
669  default:
670  slot_elem_map = slot_face_map;
671  break;
672  }
673 
674  ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
675 
676  if (UNLIKELY((ese->ele == NULL) ||
677  (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) {
678  BLI_remlink(&bm->selected, ese);
679  MEM_freeN(ese);
680  }
681  }
682  }
683 
684  if (bm->act_face) {
685  BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face);
686  if (f) {
687  bm->act_face = f;
688  }
689  }
690 }
691 
692 int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
693 {
694  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
696 
697  /* check if its actually a buffer */
698  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
699  return 0;
700  }
701 
702  return slot->len;
703 }
704 
705 int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
706 {
707  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
709  return BLI_ghash_len(slot->data.ghash);
710 }
711 
712 /* inserts a key/value mapping into a mapping slot. note that it copies the
713  * value, it doesn't store a reference to it. */
714 
715 void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data)
716 {
717  (void)op; /* Ignored in release builds. */
718 
720  BMO_ASSERT_SLOT_IN_OP(slot, op);
721 
722  BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data);
723 }
724 
725 #if 0
726 void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
727 {
728  BMOpSlot *slot = &op->slots[slot_code];
729  void *tmp;
730  ssize_t allocsize;
731 
732  BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
733 
734  /* check if its actually a buffer */
735  if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF) {
736  return NULL;
737  }
738 
739  if (slot->flag & BMOS_DYNAMIC_ARRAY) {
740  if (slot->len >= slot->size) {
741  slot->size = (slot->size + 1 + totadd) * 2;
742 
743  allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] *
744  slot->size;
745  slot->data.buf = MEM_recallocN_id(slot->data.buf, allocsize, "opslot dynamic array");
746  }
747 
748  slot->len += totadd;
749  }
750  else {
751  slot->flag |= BMOS_DYNAMIC_ARRAY;
752  slot->len += totadd;
753  slot->size = slot->len + 2;
754 
755  allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] *
756  slot->len;
757 
758  tmp = slot->data.buf;
759  slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
760  memcpy(slot->data.buf, tmp, allocsize);
761  }
762 
763  return slot->data.buf;
764 }
765 #endif
766 
768  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
769  const char *slot_name,
770  const char htype,
771  const short oflag)
772 {
773  GHashIterator gh_iter;
774  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
775  BMElemF *ele_f;
776 
778 
779  GHASH_ITER (gh_iter, slot->data.ghash) {
780  ele_f = BLI_ghashIterator_getKey(&gh_iter);
781  if (ele_f->head.htype & htype) {
782  BMO_elem_flag_enable(bm, ele_f, oflag);
783  }
784  }
785 }
786 
788  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
789  const char *slot_name,
790  const int len)
791 {
792  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
793 
794  /* check if its actually a buffer */
795  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
796  return NULL;
797  }
798 
799  slot->len = len;
800  if (len) {
802  }
803  else {
804  slot->data.buf = NULL;
805  }
806 
807  return slot->data.buf;
808 }
809 
816  BMOperator *op,
817  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
818  const char *slot_name,
819  const char htype)
820 {
821  BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
822  int totelement = 0, i = 0;
823 
825  BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
826 
827  if (htype & BM_VERT) {
828  totelement += bm->totvert;
829  }
830  if (htype & BM_EDGE) {
831  totelement += bm->totedge;
832  }
833  if (htype & BM_FACE) {
834  totelement += bm->totface;
835  }
836 
837  if (totelement) {
838  BMIter iter;
839  BMHeader *ele;
840 
841  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
842 
843  /* TODO - collapse these loops into one */
844 
845  if (htype & BM_VERT) {
846  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
847  output->data.buf[i] = ele;
848  i++;
849  }
850  }
851 
852  if (htype & BM_EDGE) {
853  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
854  output->data.buf[i] = ele;
855  i++;
856  }
857  }
858 
859  if (htype & BM_FACE) {
860  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
861  output->data.buf[i] = ele;
862  i++;
863  }
864  }
865  }
866 }
867 
875  BMOperator *op,
876  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
877  const char *slot_name,
878  const char htype,
879  const char hflag,
880  const bool test_for_enabled)
881 {
882  BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
883  int totelement = 0, i = 0;
884  const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) &&
885  ((hflag & BM_ELEM_HIDDEN) == 0);
886 
888  BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
889  BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
890 
891  if (test_for_enabled) {
892  totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
893  }
894  else {
895  totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide);
896  }
897 
898  if (totelement) {
899  BMIter iter;
900  BMElem *ele;
901 
902  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
903 
904  /* TODO - collapse these loops into one */
905 
906  if (htype & BM_VERT) {
907  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
908  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
909  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
910  output->data.buf[i] = ele;
911  i++;
912  }
913  }
914  }
915 
916  if (htype & BM_EDGE) {
917  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
918  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
919  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
920  output->data.buf[i] = ele;
921  i++;
922  }
923  }
924  }
925 
926  if (htype & BM_FACE) {
927  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
928  if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
929  BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
930  output->data.buf[i] = ele;
931  i++;
932  }
933  }
934  }
935  }
936  else {
937  output->len = 0;
938  }
939 }
940 
942  BMOperator *op,
943  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
944  const char *slot_name,
945  const char htype,
946  const char hflag)
947 {
948  bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
949 }
950 
952  BMOperator *op,
953  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
954  const char *slot_name,
955  const char htype,
956  const char hflag)
957 {
958  bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
959 }
960 
962 {
963  BMO_ASSERT_SLOT_IN_OP(slot, op);
966  BLI_assert(ELEM(slot->len, 0, 1));
967 
968  BLI_assert(slot->slot_subtype.elem & ele->htype);
969 
970  slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */
971  slot->len = 1;
972  *slot->data.buf = ele;
973 }
974 
976  BMOpSlot *slot,
977  BMHeader **ele_buffer,
978  int ele_buffer_len)
979 {
980  BMO_ASSERT_SLOT_IN_OP(slot, op);
982  BLI_assert(ELEM(slot->len, 0, ele_buffer_len));
983 
984  if (slot->data.buf == NULL) {
985  slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len);
986  }
987 
988  slot->len = ele_buffer_len;
989  memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf));
990 }
991 
993 {
996  BLI_assert(ELEM(slot->len, 0, 1));
997 
998  return slot->len ? (BMHeader *)slot->data.buf[0] : NULL;
999 }
1000 
1005  const char *slot_name_dst,
1006  BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
1007  const char *slot_name_src,
1008  struct MemArena *arena_dst)
1009 {
1010  BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
1011  BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
1012 
1014  slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
1015 
1016  if (slot_dst->len == 0) {
1017  /* output slot is empty, copy rather than append */
1018  _bmo_slot_copy(slot_args_src, slot_name_src, slot_args_dst, slot_name_dst, arena_dst);
1019  }
1020  else if (slot_src->len != 0) {
1021  int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type];
1022  int alloc_size = elem_size * (slot_dst->len + slot_src->len);
1023  /* allocate new buffer */
1024  void *buf = BLI_memarena_alloc(arena_dst, alloc_size);
1025 
1026  /* copy slot data */
1027  memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len);
1028  memcpy(
1029  ((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len);
1030 
1031  slot_dst->data.buf = buf;
1032  slot_dst->len += slot_src->len;
1033  }
1034 }
1035 
1043  BMOperator *op,
1044  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1045  const char *slot_name,
1046  const char htype,
1047  const short oflag,
1048  const bool test_for_enabled)
1049 {
1050  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1051  int totelement, i = 0;
1052 
1053  BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
1054 
1056  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1058 
1059  if (test_for_enabled) {
1060  totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
1061  }
1062  else {
1063  totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
1064  }
1065 
1066  if (totelement) {
1067  BMIter iter;
1068  BMHeader *ele;
1069  BMHeader **ele_array;
1070 
1071  BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
1072 
1073  ele_array = (BMHeader **)slot->data.buf;
1074 
1075  /* TODO - collapse these loops into one */
1076 
1077  if (htype & BM_VERT) {
1078  BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
1079  if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) {
1080  ele_array[i] = ele;
1081  i++;
1082  }
1083  }
1084  }
1085 
1086  if (htype & BM_EDGE) {
1087  BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
1088  if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) {
1089  ele_array[i] = ele;
1090  i++;
1091  }
1092  }
1093  }
1094 
1095  if (htype & BM_FACE) {
1096  BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
1097  if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) {
1098  ele_array[i] = ele;
1099  i++;
1100  }
1101  }
1102  }
1103  }
1104  else {
1105  slot->len = 0;
1106  }
1107 }
1108 
1110  BMOperator *op,
1111  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1112  const char *slot_name,
1113  const char htype,
1114  const short oflag)
1115 {
1116  bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
1117 }
1118 
1120  BMOperator *op,
1121  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1122  const char *slot_name,
1123  const char htype,
1124  const short oflag)
1125 {
1126  bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
1127 }
1128 
1136  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1137  const char *slot_name,
1138  const char htype,
1139  const char hflag,
1140  const bool do_flush)
1141 {
1142  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1143  BMElem **data = (BMElem **)slot->data.buf;
1144  int i;
1145  const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
1146  const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
1147 
1149  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1151 
1152  for (i = 0; i < slot->len; i++, data++) {
1153  if (!(htype & (*data)->head.htype)) {
1154  continue;
1155  }
1156 
1157  if (do_flush_select) {
1158  BM_elem_select_set(bm, *data, true);
1159  }
1160 
1161  if (do_flush_hide) {
1162  BM_elem_hide_set(bm, *data, false);
1163  }
1164 
1165  BM_elem_flag_enable(*data, hflag);
1166  }
1167 }
1168 
1176  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1177  const char *slot_name,
1178  const char htype,
1179  const char hflag,
1180  const bool do_flush)
1181 {
1182  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1183  BMElem **data = (BMElem **)slot->data.buf;
1184  int i;
1185  const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
1186  const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
1187 
1189  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1190 
1191  for (i = 0; i < slot->len; i++, data++) {
1192  if (!(htype & (*data)->head.htype)) {
1193  continue;
1194  }
1195 
1196  if (do_flush_select) {
1197  BM_elem_select_set(bm, *data, false);
1198  }
1199 
1200  if (do_flush_hide) {
1201  BM_elem_hide_set(bm, *data, false);
1202  }
1203 
1204  BM_elem_flag_disable(*data, hflag);
1205  }
1206 }
1207 
1214  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1215  const char *slot_name,
1216  const char htype,
1217  const short oflag)
1218 {
1219  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1220  BMHeader **data = slot->data.p;
1221  int i;
1222 
1224  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1225 
1226  for (i = 0; i < slot->len; i++) {
1227  if (!(htype & data[i]->htype)) {
1228  continue;
1229  }
1230 
1232  }
1233 }
1234 
1241  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1242  const char *slot_name,
1243  const char htype,
1244  const short oflag)
1245 {
1246  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1247  BMHeader **data = (BMHeader **)slot->data.buf;
1248  int i;
1249 
1251  BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
1252 
1253  for (i = 0; i < slot->len; i++) {
1254  if (!(htype & data[i]->htype)) {
1255  continue;
1256  }
1257 
1259  }
1260 }
1261 
1276 {
1277  /* set the index values since we are looping over all data anyway,
1278  * may save time later on */
1279 
1280  BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
1281  BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
1282  BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
1283 
1284  /* store memcpy size for reuse */
1285  const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
1286 
1287  bm->totflags++;
1288 
1290  sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP);
1292  sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
1294  sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
1295 
1296  /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
1297  BMIter iter;
1298  int i;
1299 
1300  BMVert_OFlag *v_oflag;
1301  BLI_mempool *newpool = bm->vtoolflagpool;
1302  BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
1303  void *oldflags = v_oflag->oflags;
1304  v_oflag->oflags = BLI_mempool_calloc(newpool);
1305  memcpy(v_oflag->oflags, oldflags, old_totflags_size);
1306  BM_elem_index_set(&v_oflag->base, i); /* set_inline */
1307  BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
1308  }
1309 
1310  BMEdge_OFlag *e_oflag;
1311  newpool = bm->etoolflagpool;
1312  BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
1313  void *oldflags = e_oflag->oflags;
1314  e_oflag->oflags = BLI_mempool_calloc(newpool);
1315  memcpy(e_oflag->oflags, oldflags, old_totflags_size);
1316  BM_elem_index_set(&e_oflag->base, i); /* set_inline */
1317  BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
1318  }
1319 
1320  BMFace_OFlag *f_oflag;
1321  newpool = bm->ftoolflagpool;
1322  BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
1323  void *oldflags = f_oflag->oflags;
1324  f_oflag->oflags = BLI_mempool_calloc(newpool);
1325  memcpy(f_oflag->oflags, oldflags, old_totflags_size);
1326  BM_elem_index_set(&f_oflag->base, i); /* set_inline */
1327  BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
1328  }
1329 
1330  BLI_mempool_destroy(voldpool);
1331  BLI_mempool_destroy(eoldpool);
1332  BLI_mempool_destroy(foldpool);
1333 
1335 }
1336 
1338 {
1339  /* set the index values since we are looping over all data anyway,
1340  * may save time later on */
1341 
1342  BLI_mempool *voldpool = bm->vtoolflagpool;
1343  BLI_mempool *eoldpool = bm->etoolflagpool;
1344  BLI_mempool *foldpool = bm->ftoolflagpool;
1345 
1346  /* store memcpy size for reuse */
1347  const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
1348 
1349  /* de-increment the totflags first.. */
1350  bm->totflags--;
1351 
1352  bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP);
1353  bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
1354  bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
1355 
1356  /* now go through and memcpy all the flag */
1357  BMIter iter;
1358  int i;
1359 
1360  BMVert_OFlag *v_oflag;
1361  BLI_mempool *newpool = bm->vtoolflagpool;
1362  BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
1363  void *oldflags = v_oflag->oflags;
1364  v_oflag->oflags = BLI_mempool_alloc(newpool);
1365  memcpy(v_oflag->oflags, oldflags, new_totflags_size);
1366  BM_elem_index_set(&v_oflag->base, i); /* set_inline */
1367  BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
1368  }
1369 
1370  BMEdge_OFlag *e_oflag;
1371  newpool = bm->etoolflagpool;
1372  BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
1373  void *oldflags = e_oflag->oflags;
1374  e_oflag->oflags = BLI_mempool_alloc(newpool);
1375  memcpy(e_oflag->oflags, oldflags, new_totflags_size);
1376  BM_elem_index_set(&e_oflag->base, i); /* set_inline */
1377  BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
1378  }
1379 
1380  BMFace_OFlag *f_oflag;
1381  newpool = bm->ftoolflagpool;
1382  BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
1383  void *oldflags = f_oflag->oflags;
1384  f_oflag->oflags = BLI_mempool_alloc(newpool);
1385  memcpy(f_oflag->oflags, oldflags, new_totflags_size);
1386  BM_elem_index_set(&f_oflag->base, i); /* set_inline */
1387  BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
1388  }
1389 
1390  BLI_mempool_destroy(voldpool);
1391  BLI_mempool_destroy(eoldpool);
1392  BLI_mempool_destroy(foldpool);
1393 
1395 }
1396 
1398 {
1399  /* set the index values since we are looping over all data anyway,
1400  * may save time later on */
1401  const BMFlagLayer zero_flag = {0};
1402 
1403  const int totflags_offset = bm->totflags - 1;
1404 
1405  /* now go through and memcpy all the flag */
1406  {
1407  BMIter iter;
1408  BMVert_OFlag *ele;
1409  int i;
1410  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
1411  ele->oflags[totflags_offset] = zero_flag;
1412  BM_elem_index_set(&ele->base, i); /* set_inline */
1413  }
1414  }
1415  {
1416  BMIter iter;
1417  BMEdge_OFlag *ele;
1418  int i;
1419  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
1420  ele->oflags[totflags_offset] = zero_flag;
1421  BM_elem_index_set(&ele->base, i); /* set_inline */
1422  }
1423  }
1424  {
1425  BMIter iter;
1426  BMFace_OFlag *ele;
1427  int i;
1428  BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
1429  ele->oflags[totflags_offset] = zero_flag;
1430  BM_elem_index_set(&ele->base, i); /* set_inline */
1431  }
1432  }
1433 
1435 }
1436 
1437 void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
1438 {
1439  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1440 
1441  if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
1442  return NULL;
1443  }
1444 
1445  return slot->data.buf ? *slot->data.buf : NULL;
1446 }
1447 
1454 void *BMO_iter_new(BMOIter *iter,
1455  BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
1456  const char *slot_name,
1457  const char restrictmask)
1458 {
1459  BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
1460 
1461  memset(iter, 0, sizeof(BMOIter));
1462 
1463  iter->slot = slot;
1464  iter->cur = 0;
1465  iter->restrictmask = restrictmask;
1466 
1467  if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) {
1468  BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
1469  }
1470  else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
1471  BLI_assert(restrictmask & slot->slot_subtype.elem);
1472  }
1473  else {
1474  BLI_assert(0);
1475  }
1476 
1477  return BMO_iter_step(iter);
1478 }
1479 
1481 {
1482  BMOpSlot *slot = iter->slot;
1483  if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
1484  BMHeader *ele;
1485 
1486  if (iter->cur >= slot->len) {
1487  return NULL;
1488  }
1489 
1490  ele = slot->data.buf[iter->cur++];
1491  while (!(iter->restrictmask & ele->htype)) {
1492  if (iter->cur >= slot->len) {
1493  return NULL;
1494  }
1495 
1496  ele = slot->data.buf[iter->cur++];
1497  BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
1498  }
1499 
1500  BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
1501 
1502  return ele;
1503  }
1504  if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
1505  void *ret;
1506 
1507  if (BLI_ghashIterator_done(&iter->giter) == false) {
1509  iter->val = BLI_ghashIterator_getValue_p(&iter->giter);
1510 
1511  BLI_ghashIterator_step(&iter->giter);
1512  }
1513  else {
1514  ret = NULL;
1515  iter->val = NULL;
1516  }
1517 
1518  return ret;
1519  }
1520  BLI_assert(0);
1521 
1522  return NULL;
1523 }
1524 
1525 /* used for iterating over mappings */
1526 
1532 {
1533  return iter->val;
1534 }
1535 
1537 {
1541  return iter->val ? *iter->val : NULL;
1542 }
1543 
1545 {
1547  return **((float **)iter->val);
1548 }
1549 
1551 {
1553  return **((int **)iter->val);
1554 }
1555 
1557 {
1559  return **((bool **)iter->val);
1560 }
1561 
1562 /* error system */
1563 typedef struct BMOpError {
1564  struct BMOpError *next, *prev;
1567  const char *msg;
1569 
1571 {
1572  while (BMO_error_pop(bm, NULL, NULL)) {
1573  /* pass */
1574  }
1575 }
1576 
1577 void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
1578 {
1579  BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
1580 
1581  err->errorcode = errcode;
1582  if (!msg) {
1583  msg = bmo_error_messages[errcode];
1584  }
1585  err->msg = msg;
1586  err->op = owner;
1587 
1589 }
1590 
1592 {
1593  return (BLI_listbase_is_empty(&bm->errorstack) == false);
1594 }
1595 
1596 /* returns error code or 0 if no error */
1597 int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op)
1598 {
1600  if (!err) {
1601  return 0;
1602  }
1603 
1604  if (msg) {
1605  *msg = err->msg;
1606  }
1607  if (op) {
1608  *op = err->op;
1609  }
1610 
1611  return err->errorcode;
1612 }
1613 
1614 int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
1615 {
1616  int errorcode = BMO_error_get(bm, msg, op);
1617 
1618  if (errorcode) {
1620 
1622  MEM_freeN(err);
1623  }
1624 
1625  return errorcode;
1626 }
1627 
1628 #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
1629 
1630 static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
1631 {
1632  int i = 0;
1633 
1634  while (slot_args->slot_name) {
1635  if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) {
1636  return i;
1637  }
1638  slot_args++;
1639  i++;
1640  }
1641 
1642  return -1;
1643 }
1644 
1645 static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
1646 {
1647  int i = bmo_name_to_slotcode(slot_args, identifier);
1648  if (i < 0) {
1649  fprintf(stderr,
1650  "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n",
1651  __func__,
1652  identifier);
1653  }
1654 
1655  return i;
1656 }
1657 
1658 int BMO_opcode_from_opname(const char *opname)
1659 {
1660 
1661  const uint tot = bmo_opdefines_total;
1662  uint i;
1663  for (i = 0; i < tot; i++) {
1664  if (STREQ(bmo_opdefines[i]->opname, opname)) {
1665  return i;
1666  }
1667  }
1668  return -1;
1669 }
1670 
1671 static int BMO_opcode_from_opname_check(const char *opname)
1672 {
1673  int i = BMO_opcode_from_opname(opname);
1674  if (i == -1) {
1675  fprintf(stderr,
1676  "%s: could not find bmesh slot for name %s! (bmesh internal error)\n",
1677  __func__,
1678  opname);
1679  }
1680  return i;
1681 }
1682 
1737 bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
1738 {
1739  // BMOpDefine *def;
1740  char *opname, *ofmt, *fmt;
1741  char slot_name[64] = {0};
1742  int i, type;
1743  bool noslot, state;
1744 
1745  /* basic useful info to help find where bmop formatting strings fail */
1746  const char *err_reason = "Unknown";
1747  int lineno = -1;
1748 
1749 #define GOTO_ERROR(reason) \
1750  { \
1751  err_reason = reason; \
1752  lineno = __LINE__; \
1753  goto error; \
1754  } \
1755  (void)0
1756 
1757  /* we muck around in here, so dup it */
1758  fmt = ofmt = BLI_strdup(_fmt);
1759 
1760  /* find operator name */
1761  i = strcspn(fmt, " ");
1762 
1763  opname = fmt;
1764  noslot = (opname[i] == '\0');
1765  opname[i] = '\0';
1766 
1767  fmt += i + (noslot ? 0 : 1);
1768 
1769  i = BMO_opcode_from_opname_check(opname);
1770 
1771  if (i == -1) {
1772  MEM_freeN(ofmt);
1773  BLI_assert(0);
1774  return false;
1775  }
1776 
1777  BMO_op_init(bm, op, flag, opname);
1778  // def = bmo_opdefines[i];
1779 
1780  i = 0;
1781  state = true; /* false: not inside slot_code name, true: inside slot_code name */
1782 
1783  while (*fmt) {
1784  if (state) {
1785  /* jump past leading whitespace */
1786  i = strspn(fmt, " ");
1787  fmt += i;
1788 
1789  /* ignore trailing whitespace */
1790  if (!fmt[i]) {
1791  break;
1792  }
1793 
1794  /* find end of slot name, only "slot=%f", can be used */
1795  i = strcspn(fmt, "=");
1796  if (!fmt[i]) {
1797  GOTO_ERROR("could not match end of slot name");
1798  }
1799 
1800  fmt[i] = 0;
1801 
1802  if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) {
1803  GOTO_ERROR("name to slot code check failed");
1804  }
1805 
1806  BLI_strncpy(slot_name, fmt, sizeof(slot_name));
1807 
1808  state = false;
1809  fmt += i;
1810  }
1811  else {
1812  switch (*fmt) {
1813  case ' ':
1814  case '=':
1815  case '%':
1816  break;
1817  case 'm': {
1818  int size;
1819  const char c = NEXT_CHAR(fmt);
1820  fmt++;
1821 
1822  if (c == '3') {
1823  size = 3;
1824  }
1825  else if (c == '4') {
1826  size = 4;
1827  }
1828  else {
1829  GOTO_ERROR("matrix size was not 3 or 4");
1830  }
1831 
1832  BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
1833  state = true;
1834  break;
1835  }
1836  case 'v': {
1837  BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
1838  state = true;
1839  break;
1840  }
1841  case 'e': {
1842  BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
1843 
1844  if (NEXT_CHAR(fmt) == 'b') {
1845  BMHeader **ele_buffer = va_arg(vlist, void *);
1846  int ele_buffer_len = va_arg(vlist, int);
1847 
1848  BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len);
1849  fmt++;
1850  }
1851  else {
1852  /* single vert/edge/face */
1853  BMHeader *ele = va_arg(vlist, void *);
1854 
1855  BMO_slot_buffer_from_single(op, slot, ele);
1856  }
1857 
1858  state = true;
1859  break;
1860  }
1861  case 's':
1862  case 'S': {
1863  BMOperator *op_other = va_arg(vlist, void *);
1864  const char *slot_name_other = va_arg(vlist, char *);
1865 
1866  if (*fmt == 's') {
1867  BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1);
1868  BMO_slot_copy(op_other, slots_in, slot_name_other, op, slots_in, slot_name);
1869  }
1870  else {
1871  BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1);
1872  BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name);
1873  }
1874  state = true;
1875  break;
1876  }
1877  case 'i':
1878  BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
1879  state = true;
1880  break;
1881  case 'b':
1882  BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
1883  state = true;
1884  break;
1885  case 'p':
1886  BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
1887  state = true;
1888  break;
1889  case 'f':
1890  case 'F':
1891  case 'h':
1892  case 'H':
1893  case 'a':
1894  type = *fmt;
1895 
1896  if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
1897  BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
1898  }
1899  else {
1900  char htype = 0;
1901 
1902  while (1) {
1903  char htype_set;
1904  const char c = NEXT_CHAR(fmt);
1905  if (c == 'f') {
1906  htype_set = BM_FACE;
1907  }
1908  else if (c == 'e') {
1909  htype_set = BM_EDGE;
1910  }
1911  else if (c == 'v') {
1912  htype_set = BM_VERT;
1913  }
1914  else {
1915  break;
1916  }
1917 
1918  if (UNLIKELY(htype & htype_set)) {
1919  GOTO_ERROR("htype duplicated");
1920  }
1921 
1922  htype |= htype_set;
1923  fmt++;
1924  }
1925 
1926  if (type == 'h') {
1928  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1929  }
1930  else if (type == 'H') {
1932  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1933  }
1934  else if (type == 'a') {
1935  if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) {
1936  BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype);
1937  }
1938  else {
1940  bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN);
1941  }
1942  }
1943  else if (type == 'f') {
1945  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1946  }
1947  else if (type == 'F') {
1949  bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
1950  }
1951  }
1952 
1953  state = true;
1954  break;
1955  default:
1956  fprintf(stderr,
1957  "%s: unrecognized bmop format char: '%c', %d in '%s'\n",
1958  __func__,
1959  *fmt,
1960  (int)(fmt - ofmt),
1961  ofmt);
1962  break;
1963  }
1964  }
1965  fmt++;
1966  }
1967 
1968  MEM_freeN(ofmt);
1969  return true;
1970 error:
1971 
1972  /* non urgent todo - explain exactly what is failing */
1973  fprintf(stderr, "%s: error parsing formatting string\n", __func__);
1974 
1975  fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
1976  fprintf(stderr, " ");
1977  {
1978  int pos = (int)(fmt - ofmt);
1979  for (i = 0; i < pos; i++) {
1980  fprintf(stderr, " ");
1981  }
1982  fprintf(stderr, "^\n");
1983  }
1984 
1985  fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno);
1986 
1987  fprintf(stderr, "reason: %s\n", err_reason);
1988 
1989  MEM_freeN(ofmt);
1990 
1991  BMO_op_finish(bm, op);
1992  return false;
1993 
1994 #undef GOTO_ERROR
1995 }
1996 
1997 bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...)
1998 {
1999  va_list list;
2000 
2001  va_start(list, fmt);
2002  if (!BMO_op_vinitf(bm, op, flag, fmt, list)) {
2003  printf("%s: failed\n", __func__);
2004  va_end(list);
2005  return false;
2006  }
2007  va_end(list);
2008 
2009  return true;
2010 }
2011 
2012 bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
2013 {
2014  va_list list;
2015  BMOperator op;
2016 
2017  va_start(list, fmt);
2018  if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) {
2019  printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
2020  va_end(list);
2021  return false;
2022  }
2023 
2024  BMO_op_exec(bm, &op);
2025  BMO_op_finish(bm, &op);
2026 
2027  va_end(list);
2028  return true;
2029 }
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:146
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition: BLI_ghash.c:1086
BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:158
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:150
BLI_INLINE void ** BLI_ghashIterator_getValue_p(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:154
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:169
unsigned int BLI_ghash_len(GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:744
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
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:1065
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void zero_m4(float m[4][4])
Definition: math_matrix.c:46
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
void unit_m4(float m[4][4])
Definition: rct.c:1140
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:120
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
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:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:91
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:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void * BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:362
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:77
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
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define ARRAY_SIZE(arr)
#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:87
#define N_(msgid)
_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
@ BMERR_TOTAL
Definition: bmesh_error.h:64
#define BM_ELEM_INDEX_VALIDATE(_bm, _msg_a, _msg_b)
Definition: bmesh_error.h:51
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_test_bool(ele, hflag)
Definition: bmesh_inline.h:27
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
#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:30
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
Definition: bmesh_mesh.c:98
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
BMesh Begin Edit.
Definition: bmesh_mesh.c:1975
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BMesh End Edit.
Definition: bmesh_mesh.c:1998
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
#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)
@ BMO_FLAG_RESPECT_HIDE
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
bool BMO_error_occurred(BMesh *bm)
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))
BMESH OPSTACK PUSH.
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)
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)
int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
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.
BLI_STATIC_ASSERT(ARRAY_SIZE(bmo_error_messages)==BMERR_TOTAL, "message mismatch")
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)
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)
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3])
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
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)
Format Strings for BMOperator Initialization.
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)
#define NEXT_CHAR(fmt)
#define GOTO_ERROR(reason)
void * BMO_iter_map_value_ptr(BMOIter *iter)
static const char * bmo_error_messages[]
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_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
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.
int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op)
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.
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:82
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define output
static FT_Error err
Definition: freetypefont.c:52
uint pos
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_recallocN_id)(void *vmemh, size_t len, const char *str)
Definition: mallocn.c:44
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong state[N]
static void error(const char *str)
Definition: meshlaplacian.c:65
static unsigned c
Definition: RandGen.cpp:97
return ret
struct BMFlagLayer * oflags
Definition: bmesh_class.h:153
struct BMEditSelection * next
Definition: bmesh_marking.h:24
BMHeader head
Definition: bmesh_class.h:250
struct BMFlagLayer * oflags
Definition: bmesh_class.h:287
char htype
Definition: bmesh_class.h:76
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
eBMOpSlotSubType_Union slot_subtype
eBMOpSlotType slot_type
union BMOpSlot::@139 data
struct BMOpSlot::@139::@140 enum_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:114
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:47
eBMOpSlotSubType_Int intg
eBMOpSlotSubType_Elem elem
eBMOpSlotSubType_Map map
uint len