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