Blender V5.0
bmesh_log.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
19
20#include "MEM_guardedalloc.h"
21
22#include "BLI_listbase.h"
23#include "BLI_map.hh"
24#include "BLI_math_vector.h"
25#include "BLI_pool.hh"
26#include "BLI_utildefines.h"
27
28#include "BKE_customdata.hh"
29
30#include "bmesh.hh"
31#include "bmesh_log.hh"
32
33#include "range_tree.h"
34
35#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
36
37struct BMLogFace;
38struct BMLogVert;
39
73
105
112
113struct BMLogFace {
114 std::array<uint, 3> v_ids;
115 char hflag;
116};
117
118/************************* Get/set element IDs ************************/
119
120/* Get the vertex's unique ID from the log */
122{
123 return log->elem_to_id.lookup(reinterpret_cast<BMElem *>(v));
124}
125
126/* Set the vertex's unique ID in the log */
127static void bm_log_vert_id_set(BMLog *log, BMVert *v, const uint id)
128{
129 log->id_to_elem.add_overwrite(id, reinterpret_cast<BMElem *>(v));
130 log->elem_to_id.add_overwrite(reinterpret_cast<BMElem *>(v), id);
131}
132
133/* Get a vertex from its unique ID */
135{
136 return reinterpret_cast<BMVert *>(log->id_to_elem.lookup(id));
137}
138
139/* Get the face's unique ID from the log */
141{
142 return log->elem_to_id.lookup(reinterpret_cast<BMElem *>(f));
143}
144
145/* Set the face's unique ID in the log */
146static void bm_log_face_id_set(BMLog *log, BMFace *f, const uint id)
147{
148 log->id_to_elem.add_overwrite(id, reinterpret_cast<BMElem *>(f));
149 log->elem_to_id.add_overwrite(reinterpret_cast<BMElem *>(f), id);
150}
151
152/* Get a face from its unique ID */
154{
155 return reinterpret_cast<BMFace *>(log->id_to_elem.lookup(id));
156}
157
158/************************ BMLogVert / BMLogFace ***********************/
159
160/* Get a vertex's paint-mask value
161 *
162 * Returns zero if no paint-mask layer is present */
163static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset)
164{
165 if (cd_vert_mask_offset != -1) {
166 return BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
167 }
168 return 0.0f;
169}
170
171/* Set a vertex's paint-mask value
172 *
173 * Has no effect is no paint-mask layer is present */
174static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mask_offset)
175{
176 if (cd_vert_mask_offset != -1) {
177 BM_ELEM_CD_SET_FLOAT(v, cd_vert_mask_offset, new_mask);
178 }
179}
180
181/* Update a BMLogVert with data from a BMVert */
182static void bm_log_vert_bmvert_copy(BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset)
183{
184 copy_v3_v3(lv->position, v->co);
185 copy_v3_v3(lv->normal, v->no);
186 lv->mask = vert_mask_get(v, cd_vert_mask_offset);
187 lv->hflag = v->head.hflag;
188}
189
190/* Allocate and initialize a BMLogVert */
191static BMLogVert *bm_log_vert_alloc(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
192{
193 BMLogEntry *entry = log->current_entry;
194 BMLogVert *lv = &entry->vert_pool.construct();
195 entry->allocated_verts.append(lv);
196
197 bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
198
199 return lv;
200}
201
202/* Allocate and initialize a BMLogFace */
204{
205 BMLogEntry *entry = log->current_entry;
206 BMLogFace *lf = &entry->face_pool.construct();
207 entry->allocated_faces.append(lf);
208 BMVert *v[3];
209
210 BLI_assert(f->len == 3);
211
212 // BM_iter_as_array(nullptr, BM_VERTS_OF_FACE, f, (void **)v, 3);
214
215 lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
216 lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
217 lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
218
219 lf->hflag = f->head.hflag;
220 return lf;
221}
222
223/************************ Helpers for undo/redo ***********************/
224
226 BMLog *log,
228{
229 const int cd_vert_mask_offset = CustomData_get_offset_named(
230 &bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
231
232 for (const auto item : verts.items()) {
233 BMVert *v = bm_log_vert_from_id(log, item.key);
234
235 /* Ensure the log has the final values of the vertex before
236 * deleting it */
237 bm_log_vert_bmvert_copy(item.value, v, cd_vert_mask_offset);
238
239 BM_vert_kill(bm, v);
240 }
241}
242
244 BMLog *log,
246{
247 for (const uint id : faces.keys()) {
249 std::array<BMEdge *, 3> e_tri;
250
251 BMLoop *l_iter = BM_FACE_FIRST_LOOP(f);
252 for (uint i = 0; i < e_tri.size(); i++, l_iter = l_iter->next) {
253 e_tri[i] = l_iter->e;
254 }
255
256 /* Remove any unused edges */
257 BM_face_kill(bm, f);
258 for (uint i = 0; i < e_tri.size(); i++) {
259 if (BM_edge_is_wire(e_tri[i])) {
260 BM_edge_kill(bm, e_tri[i]);
261 }
262 }
263 }
264}
265
267 BMLog *log,
269{
270 const int cd_vert_mask_offset = CustomData_get_offset_named(
271 &bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
272
273 for (const auto item : verts.items()) {
274 BMLogVert *lv = item.value;
275 BMVert *v = BM_vert_create(bm, lv->position, nullptr, BM_CREATE_NOP);
276 vert_mask_set(v, lv->mask, cd_vert_mask_offset);
277 v->head.hflag = lv->hflag;
278 copy_v3_v3(v->no, lv->normal);
279 bm_log_vert_id_set(log, v, item.key);
280 }
281}
282
284 BMLog *log,
286{
287 const int cd_face_sets = CustomData_get_offset_named(
288 &bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
289
290 for (const auto item : faces.items()) {
291 BMLogFace *lf = item.value;
292 BMVert *v[3] = {
293 bm_log_vert_from_id(log, lf->v_ids[0]),
294 bm_log_vert_from_id(log, lf->v_ids[1]),
295 bm_log_vert_from_id(log, lf->v_ids[2]),
296 };
297
298 BMFace *f = BM_face_create_verts(bm, v, 3, nullptr, BM_CREATE_NOP, true);
299 f->head.hflag = lf->hflag;
300 bm_log_face_id_set(log, f, item.key);
301
302 /* Ensure face sets have valid values. Fixes #80174. */
303 if (cd_face_sets != -1) {
304 BM_ELEM_CD_SET_INT(f, cd_face_sets, 1);
305 }
306 }
307}
308
310 BMLog *log,
312{
313 const int cd_vert_mask_offset = CustomData_get_offset_named(
314 &bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
315
316 for (const auto item : verts.items()) {
317 BMLogVert *lv = item.value;
318 BMVert *v = bm_log_vert_from_id(log, item.key);
319
320 swap_v3_v3(v->co, lv->position);
321 swap_v3_v3(v->no, lv->normal);
322 std::swap(v->head.hflag, lv->hflag);
323 float mask = lv->mask;
324 lv->mask = vert_mask_get(v, cd_vert_mask_offset);
325 vert_mask_set(v, mask, cd_vert_mask_offset);
326 }
327}
328
330{
331
332 for (const auto item : faces.items()) {
333 BMLogFace *lf = item.value;
334 BMFace *f = bm_log_face_from_id(log, item.key);
335
336 std::swap(f->head.hflag, lf->hflag);
337 }
338}
339
340/**********************************************************************/
341
342/* Assign unique IDs to all vertices and faces already in the BMesh */
344{
345 BMIter iter;
346
347 BMVert *v;
348 /* Generate vertex IDs */
349 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
350 uint id = range_tree_uint_take_any(log->unused_ids);
352 }
353
354 BMFace *f;
355 /* Generate face IDs */
356 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
357 uint id = range_tree_uint_take_any(log->unused_ids);
358 bm_log_face_id_set(log, f, id);
359 }
360}
361
362/* Allocate an empty log entry */
364{
365 BMLogEntry *entry = MEM_new<BMLogEntry>(__func__);
366
367 return entry;
368}
369
370/* Free the data in a log entry
371 *
372 * NOTE: does not free the log entry itself. */
373static void bm_log_entry_free(BMLogEntry *entry)
374{
375 BLI_assert(entry->vert_pool.size() == entry->allocated_verts.size());
376 BLI_assert(entry->face_pool.size() == entry->allocated_faces.size());
377
378 for (BMLogVert *log_vert : entry->allocated_verts) {
379 entry->vert_pool.destruct(*log_vert);
380 }
381
382 for (BMLogFace *log_face : entry->allocated_faces) {
383 entry->face_pool.destruct(*log_face);
384 }
385
386 BLI_assert(entry->vert_pool.is_empty());
387 BLI_assert(entry->face_pool.is_empty());
388}
389
390/***************************** Public API *****************************/
391
393{
394 BMLog *log = MEM_new<BMLog>(__func__);
395 const uint reserve_num = uint(bm->totvert + bm->totface);
396
397 log->unused_ids = range_tree_uint_alloc(0, uint(-1));
398 log->id_to_elem.reserve(reserve_num);
399 log->elem_to_id.reserve(reserve_num);
400
401 /* Assign IDs to all existing vertices and faces */
403
404 return log;
405}
406
408{
409 BMLog *log = entry->log;
410
411 if (log) {
412 /* Take all used IDs */
413 for (const uint id : entry->deleted_verts.keys()) {
414 range_tree_uint_retake(log->unused_ids, id);
415 }
416 for (const uint id : entry->deleted_faces.keys()) {
417 range_tree_uint_retake(log->unused_ids, id);
418 }
419 for (const uint id : entry->added_verts.keys()) {
420 range_tree_uint_retake(log->unused_ids, id);
421 }
422 for (const uint id : entry->added_faces.keys()) {
423 range_tree_uint_retake(log->unused_ids, id);
424 }
425 for (const uint id : entry->modified_verts.keys()) {
426 range_tree_uint_retake(log->unused_ids, id);
427 }
428 for (const uint id : entry->modified_faces.keys()) {
429 range_tree_uint_retake(log->unused_ids, id);
430 }
431
432 /* delete entries to avoid releasing ids in node cleanup */
433 entry->deleted_verts.clear();
434 entry->deleted_faces.clear();
435 entry->added_verts.clear();
436 entry->added_faces.clear();
437 entry->modified_verts.clear();
438
439 /* Is this last one needed? */
440 entry->modified_faces.clear();
441 }
442}
443
445{
447
448 if (entry->prev) {
449 log->current_entry = entry;
450 }
451 else {
452 log->current_entry = nullptr;
453 }
454
455 /* Let BMLog manage the entry list again */
456 log->entries.first = log->entries.last = entry;
457
458 {
459 while (entry->prev) {
460 entry = entry->prev;
461 log->entries.first = entry;
462 }
463 entry = static_cast<BMLogEntry *>(log->entries.last);
464 while (entry->next) {
465 entry = entry->next;
466 log->entries.last = entry;
467 }
468 }
469
470 for (entry = static_cast<BMLogEntry *>(log->entries.first); entry; entry = entry->next) {
471 entry->log = log;
472
473 /* Take all used IDs */
474 for (const uint id : entry->deleted_verts.keys()) {
475 range_tree_uint_retake(log->unused_ids, id);
476 }
477 for (const uint id : entry->deleted_faces.keys()) {
478 range_tree_uint_retake(log->unused_ids, id);
479 }
480 for (const uint id : entry->added_verts.keys()) {
481 range_tree_uint_retake(log->unused_ids, id);
482 }
483 for (const uint id : entry->added_faces.keys()) {
484 range_tree_uint_retake(log->unused_ids, id);
485 }
486 for (const uint id : entry->modified_verts.keys()) {
487 range_tree_uint_retake(log->unused_ids, id);
488 }
489 for (const uint id : entry->modified_faces.keys()) {
490 range_tree_uint_retake(log->unused_ids, id);
491 }
492 }
493
494 return log;
495}
496
498{
499 if (log->unused_ids) {
500 range_tree_uint_free(log->unused_ids);
501 }
502
503 /* Clear the BMLog references within each entry, but do not free
504 * the entries themselves */
505 LISTBASE_FOREACH (BMLogEntry *, entry, &log->entries) {
506 entry->log = nullptr;
507 }
508
509 MEM_delete(log);
510}
511
513{
514 /* WARNING: Deleting any entries after the current one is now handled by the
515 * UndoSystem: BKE_UNDOSYS_TYPE_SCULPT freeing here causes unnecessary complications. */
516
517 /* Create and append the new entry */
519 BLI_addtail(&log->entries, entry);
520 entry->log = log;
521 log->current_entry = entry;
522
523 return entry;
524}
525
527{
528 BMLog *log = entry->log;
529
530 if (!log) {
531 /* Unlink */
532 BLI_assert(!(entry->prev && entry->next));
533 if (entry->prev) {
534 entry->prev->next = nullptr;
535 }
536 else if (entry->next) {
537 entry->next->prev = nullptr;
538 }
539
540 bm_log_entry_free(entry);
541 MEM_delete(entry);
542 return;
543 }
544
545 if (!entry->prev) {
546 /* Release IDs of elements that are deleted by this
547 * entry. Since the entry is at the beginning of the undo
548 * stack, and it's being deleted, those elements can never be
549 * restored. Their IDs can go back into the pool. */
550
551 /* This would never happen usually since first entry of log is
552 * usually dyntopo enable, which, when reverted will free the log
553 * completely. However, it is possible have a stroke instead of
554 * dyntopo enable as first entry if nodes have been cleaned up
555 * after sculpting on a different object than A, B.
556 *
557 * The steps are:
558 * A dyntopo enable - sculpt
559 * B dyntopo enable - sculpt - undo (A objects operators get cleaned up)
560 * A sculpt (now A's log has a sculpt operator as first entry)
561 *
562 * Causing a cleanup at this point will call the code below, however
563 * this will invalidate the state of the log since the deleted vertices
564 * have been reclaimed already on step 2 (see BM_log_cleanup_entry)
565 *
566 * Also, design wise, a first entry should not have any deleted vertices since it
567 * should not have anything to delete them -from-
568 */
569 // bm_log_id_ghash_release(log, entry->deleted_faces);
570 // bm_log_id_ghash_release(log, entry->deleted_verts);
571 }
572 else if (!entry->next) {
573 /* Release IDs of elements that are added by this entry. Since
574 * the entry is at the end of the undo stack, and it's being
575 * deleted, those elements can never be restored. Their IDs
576 * can go back into the pool. */
577 for (const uint id : entry->added_faces.keys()) {
578 range_tree_uint_release(log->unused_ids, id);
579 }
580 for (const uint id : entry->added_verts.keys()) {
581 range_tree_uint_release(log->unused_ids, id);
582 }
583 }
584 else {
585 BLI_assert_msg(0, "Cannot drop BMLogEntry from middle");
586 }
587
588 if (log->current_entry == entry) {
589 log->current_entry = entry->prev;
590 }
591
592 bm_log_entry_free(entry);
593 BLI_remlink(&log->entries, entry);
594 MEM_delete(entry);
595}
596
598{
599 BMLogEntry *entry = log->current_entry;
600
601 if (entry) {
602 log->current_entry = entry->prev;
603
604 /* Delete added faces and verts */
607
608 /* Restore deleted verts and faces */
611
612 /* Restore vertex coordinates, mask, and hflag */
615 }
616}
617
619{
620 BMLogEntry *entry = log->current_entry;
621
622 if (!entry) {
623 /* Currently at the beginning of the undo stack, move to first entry */
624 entry = static_cast<BMLogEntry *>(log->entries.first);
625 }
626 else if (entry->next) {
627 /* Move to next undo entry */
628 entry = entry->next;
629 }
630 else {
631 /* Currently at the end of the undo stack, nothing left to redo */
632 return;
633 }
634
635 log->current_entry = entry;
636
637 if (entry) {
638 /* Re-delete previously deleted faces and verts */
641
642 /* Restore previously added verts and faces */
645
646 /* Restore vertex coordinates, mask, and hflag */
649 }
650}
651
652void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
653{
654 BMLogEntry *entry = log->current_entry;
655 const uint v_id = bm_log_vert_id_get(log, v);
656
657 /* Find or create the BMLogVert entry */
658 if (entry->added_verts.contains(v_id)) {
659 bm_log_vert_bmvert_copy(entry->added_verts.lookup(v_id), v, cd_vert_mask_offset);
660 }
661 else {
663 v_id, [&] { return bm_log_vert_alloc(log, v, cd_vert_mask_offset); });
664 }
665}
666
667void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
668{
669 const uint v_id = range_tree_uint_take_any(log->unused_ids);
670
671 bm_log_vert_id_set(log, v, v_id);
672 BMLogVert *lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
673 log->current_entry->added_verts.add(v_id, lv);
674}
675
677{
678 const uint f_id = bm_log_face_id_get(log, f);
679
681 log->current_entry->modified_faces.add(f_id, lf);
682}
683
685{
686 const uint f_id = range_tree_uint_take_any(log->unused_ids);
687
688 /* Only triangles are supported for now */
689 BLI_assert(f->len == 3);
690
691 bm_log_face_id_set(log, f, f_id);
693 log->current_entry->added_faces.add(f_id, lf);
694}
695
696void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
697{
698 BMLogEntry *entry = log->current_entry;
699 const uint v_id = bm_log_vert_id_get(log, v);
700
701 BLI_assert(!entry->added_verts.contains(v_id) ||
702 (entry->added_verts.contains(v_id) && entry->added_verts.lookup(v_id) != nullptr));
703
704 if (entry->added_verts.remove(v_id)) {
705 range_tree_uint_release(log->unused_ids, v_id);
706 }
707 else {
708 BMLogVert *lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
709 entry->deleted_verts.add(v_id, lv);
710
711 /* If the vertex was modified before deletion, ensure that the
712 * original vertex values are stored */
713 if (std::optional<BMLogVert *> lv_mod = entry->modified_verts.lookup_try(v_id)) {
714 *lv = *lv_mod.value();
715 entry->modified_verts.remove(v_id);
716 }
717 }
718}
719
721{
722 BMLogEntry *entry = log->current_entry;
723 const uint f_id = bm_log_face_id_get(log, f);
724
725 BLI_assert(!entry->added_faces.contains(f_id) ||
726 (entry->added_faces.contains(f_id) && entry->added_faces.lookup(f_id) != nullptr));
727
728 if (entry->added_faces.remove(f_id)) {
729 range_tree_uint_release(log->unused_ids, f_id);
730 }
731 else {
733 entry->deleted_faces.add(f_id, lf);
734 }
735}
736
738{
739 const int cd_vert_mask_offset = CustomData_get_offset_named(
740 &bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
741
742 /* avoid unnecessary resizing on initialization */
743 if (log->current_entry->added_verts.is_empty()) {
744 log->current_entry->added_verts.reserve(bm->totvert);
745 }
746
747 if (log->current_entry->added_faces.is_empty()) {
748 log->current_entry->added_faces.reserve(bm->totface);
749 }
750
751 BMIter bm_iter;
752 BMVert *v;
753 /* Log all vertices as newly created */
754 BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
755 BM_log_vert_added(log, v, cd_vert_mask_offset);
756 }
757
758 BMFace *f;
759 /* Log all faces as newly created */
760 BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
762 }
763}
764
766{
767 const int cd_vert_mask_offset = CustomData_get_offset_named(
768 &bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
769
770 BMIter bm_iter;
771 BMFace *f;
772 /* Log deletion of all faces */
773 BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
775 }
776
777 BMVert *v;
778 /* Log deletion of all vertices */
779 BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
780 BM_log_vert_removed(log, v, cd_vert_mask_offset);
781 }
782}
783
785{
786 BMLogEntry *entry = log->current_entry;
787 const uint v_id = bm_log_vert_id_get(log, v);
788
789 if (std::optional<BMLogVert *> log_vert = entry->modified_verts.lookup_try(v_id)) {
790 return log_vert.value()->position;
791 }
792 return nullptr;
793}
794
796{
797 BMLogEntry *entry = log->current_entry;
798 const uint v_id = bm_log_vert_id_get(log, v);
799
800 if (std::optional<BMLogVert *> log_vert = entry->modified_verts.lookup_try(v_id)) {
801 return &log_vert.value()->mask;
802 }
803 return nullptr;
804}
805
806void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const float **r_no)
807{
808 BMLogEntry *entry = log->current_entry;
809 BLI_assert(entry);
810
811 const uint v_id = bm_log_vert_id_get(log, v);
812
813 BLI_assert(entry->modified_verts.contains(v_id));
814
815 const BMLogVert *lv = entry->modified_verts.lookup(v_id);
816 *r_co = lv->position;
817 *r_no = lv->normal;
818}
819
820/************************ Debugging and Testing ***********************/
821
822#ifndef NDEBUG
824{
825 return log->current_entry;
826}
827
829{
830 return log->unused_ids;
831}
832
833/* Print the list of entries, marking the current one
834 *
835 * Keep around for debugging */
836void BM_log_print(const BMLog *log, const char *description)
837{
838 const BMLogEntry *entry;
839 const char *current = " <-- current";
840 int i;
841
842 printf("%s:\n", description);
843 printf(" % 2d: [ initial ]%s\n", 0, (!log->current_entry) ? current : "");
844 for (entry = static_cast<const BMLogEntry *>(log->entries.first), i = 1; entry;
845 entry = entry->next, i++)
846 {
847 printf(" % 2d: [%p]%s\n", i, entry, (entry == log->current_entry) ? current : "");
848 }
849}
850
852{
853 if (bm) {
854 printf("BM { totvert=%d totedge=%d totloop=%d faces_num=%d\n",
855 bm->totvert,
856 bm->totedge,
857 bm->totloop,
858 bm->totface);
859
860 if (!bm->totvert) {
861 printf("%s: Warning: empty bmesh\n", __func__);
862 }
863 }
864 else {
865 printf("BM { totvert=unknown totedge=unknown totloop=unknown faces_num=unknown\n");
866 }
867
868 printf("v | added: %d, removed: %d, modified: %d\n",
869 int(entry->added_verts.size()),
870 int(entry->deleted_verts.size()),
871 int(entry->modified_verts.size()));
872 printf("f | added: %d, removed: %d, modified: %d\n",
873 int(entry->added_faces.size()),
874 int(entry->deleted_faces.size()),
875 int(entry->modified_faces.size()));
876 printf("}\n");
877}
878#endif
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void swap_v3_v3(float a[3], float b[3])
unsigned int uint
@ CD_PROP_FLOAT
@ CD_PROP_INT32
Read Guarded memory(de)allocation.
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f)
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
#define BM_ELEM_CD_SET_INT(ele, offset, f)
#define BM_FACE_FIRST_LOOP(p)
void BM_vert_kill(BMesh *bm, BMVert *v)
void BM_face_kill(BMesh *bm, BMFace *f)
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
void BM_edge_kill(BMesh *bm, BMEdge *e)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition bmesh_core.cc:41
@ BM_CREATE_NOP
Definition bmesh_core.hh:28
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
BMesh * bm
static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mask_offset)
Definition bmesh_log.cc:174
static BMLogEntry * bm_log_entry_create()
Definition bmesh_log.cc:363
void BM_log_all_added(BMesh *bm, BMLog *log)
Definition bmesh_log.cc:737
static void bm_log_faces_unmake(BMesh *bm, BMLog *log, const blender::Map< uint, BMLogFace *, 0 > &faces)
Definition bmesh_log.cc:243
void BM_log_face_added(BMLog *log, BMFace *f)
Definition bmesh_log.cc:684
const float * BM_log_find_original_vert_mask(BMLog *log, BMVert *v)
Definition bmesh_log.cc:795
static void bm_log_face_id_set(BMLog *log, BMFace *f, const uint id)
Definition bmesh_log.cc:146
void BM_log_face_removed(BMLog *log, BMFace *f)
Definition bmesh_log.cc:720
RangeTreeUInt * BM_log_unused_ids(BMLog *log)
Definition bmesh_log.cc:828
static void bm_log_face_values_swap(BMLog *log, const blender::Map< uint, BMLogFace *, 0 > &faces)
Definition bmesh_log.cc:329
static void bm_log_faces_restore(BMesh *bm, BMLog *log, const blender::Map< uint, BMLogFace *, 0 > &faces)
Definition bmesh_log.cc:283
static void bm_log_assign_ids(BMesh *bm, BMLog *log)
Definition bmesh_log.cc:343
void BM_log_free(BMLog *log)
Definition bmesh_log.cc:497
void BM_log_cleanup_entry(BMLogEntry *entry)
Definition bmesh_log.cc:407
static BMLogFace * bm_log_face_alloc(BMLog *log, BMFace *f)
Definition bmesh_log.cc:203
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const float **r_no)
Definition bmesh_log.cc:806
static BMVert * bm_log_vert_from_id(BMLog *log, const uint id)
Definition bmesh_log.cc:134
static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, const blender::Map< uint, BMLogVert *, 0 > &verts)
Definition bmesh_log.cc:309
void BM_log_print(const BMLog *log, const char *description)
Definition bmesh_log.cc:836
BMLogEntry * BM_log_current_entry(BMLog *log)
Definition bmesh_log.cc:823
const float * BM_log_find_original_vert_co(BMLog *log, BMVert *v)
Definition bmesh_log.cc:784
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:667
static void bm_log_verts_restore(BMesh *bm, BMLog *log, const blender::Map< uint, BMLogVert *, 0 > &verts)
Definition bmesh_log.cc:266
static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:163
void BM_log_face_modified(BMLog *log, BMFace *f)
Definition bmesh_log.cc:676
static void bm_log_vert_id_set(BMLog *log, BMVert *v, const uint id)
Definition bmesh_log.cc:127
static void bm_log_verts_unmake(BMesh *bm, BMLog *log, const blender::Map< uint, BMLogVert *, 0 > &verts)
Definition bmesh_log.cc:225
void BM_log_redo(BMesh *bm, BMLog *log)
Definition bmesh_log.cc:618
static BMLogVert * bm_log_vert_alloc(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:191
void BM_log_print_entry(BMesh *bm, BMLogEntry *entry)
Definition bmesh_log.cc:851
static void bm_log_entry_free(BMLogEntry *entry)
Definition bmesh_log.cc:373
static void bm_log_vert_bmvert_copy(BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:182
static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
Definition bmesh_log.cc:121
static uint bm_log_face_id_get(BMLog *log, BMFace *f)
Definition bmesh_log.cc:140
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:696
void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
Definition bmesh_log.cc:652
void BM_log_entry_drop(BMLogEntry *entry)
Definition bmesh_log.cc:526
BMLog * BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
Definition bmesh_log.cc:444
BMLog * BM_log_create(BMesh *bm)
Definition bmesh_log.cc:392
static BMFace * bm_log_face_from_id(BMLog *log, const uint id)
Definition bmesh_log.cc:153
void BM_log_undo(BMesh *bm, BMLog *log)
Definition bmesh_log.cc:597
void BM_log_before_all_removed(BMesh *bm, BMLog *log)
Definition bmesh_log.cc:765
BMLogEntry * BM_log_entry_add(BMLog *log)
Definition bmesh_log.cc:512
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v
void clear()
Definition BLI_map.hh:1038
std::optional< Value > lookup_try(const Key &key) const
Definition BLI_map.hh:531
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
bool remove(const Key &key)
Definition BLI_map.hh:368
int64_t size() const
Definition BLI_map.hh:976
KeyIterator keys() const &
Definition BLI_map.hh:875
bool contains(const Key &key) const
Definition BLI_map.hh:353
int64_t size() const
void append(const T &value)
void destruct(T &value)
Definition BLI_pool.hh:63
int64_t size() const
Definition BLI_pool.hh:72
T & construct(ForwardT &&...value)
Definition BLI_pool.hh:45
bool is_empty() const
Definition BLI_pool.hh:80
static float verts[][3]
#define printf(...)
#define log
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static char faces[256]
VecBase< float, 3 > float3
BMHeader head
blender::Pool< BMLogFace > face_pool
Definition bmesh_log.cc:58
BMLog * log
Definition bmesh_log.cc:71
BMLogEntry * next
Definition bmesh_log.cc:41
blender::Map< uint, BMLogFace *, 0 > modified_faces
Definition bmesh_log.cc:55
blender::Map< uint, BMLogVert *, 0 > added_verts
Definition bmesh_log.cc:50
blender::Map< uint, BMLogFace *, 0 > deleted_faces
Definition bmesh_log.cc:47
BMLogEntry * prev
Definition bmesh_log.cc:41
blender::Vector< BMLogVert *, 0 > allocated_verts
Definition bmesh_log.cc:60
blender::Pool< BMLogVert > vert_pool
Definition bmesh_log.cc:57
blender::Map< uint, BMLogVert *, 0 > deleted_verts
Definition bmesh_log.cc:46
blender::Vector< BMLogFace *, 0 > allocated_faces
Definition bmesh_log.cc:61
blender::Map< uint, BMLogFace *, 0 > added_faces
Definition bmesh_log.cc:51
blender::Map< uint, BMLogVert *, 0 > modified_verts
Definition bmesh_log.cc:54
std::array< uint, 3 > v_ids
Definition bmesh_log.cc:114
float mask
Definition bmesh_log.cc:110
blender::float3 position
Definition bmesh_log.cc:107
blender::float3 normal
Definition bmesh_log.cc:108
ListBase entries
Definition bmesh_log.cc:92
blender::Map< uint, BMElem *, 0 > id_to_elem
Definition bmesh_log.cc:88
RangeTreeUInt * unused_ids
Definition bmesh_log.cc:76
blender::Map< BMElem *, uint, 0 > elem_to_id
Definition bmesh_log.cc:89
BMLogEntry * current_entry
Definition bmesh_log.cc:103
struct BMEdge * e
struct BMLoop * next
i
Definition text_draw.cc:230