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