Blender V4.3
customdata.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include "MEM_guardedalloc.h"
13
14/* Since we have versioning code here (CustomData_verify_versions()). */
15#define DNA_DEPRECATED_ALLOW
16
17#include "DNA_ID.h"
19#include "DNA_meshdata_types.h"
20
21#include "BLI_bit_vector.hh"
22#include "BLI_bitmap.h"
23#include "BLI_color.hh"
24#include "BLI_endian_switch.h"
25#include "BLI_index_range.hh"
27#include "BLI_math_matrix.hh"
29#include "BLI_math_vector.hh"
30#include "BLI_memory_counter.hh"
31#include "BLI_mempool.h"
32#include "BLI_path_utils.hh"
33#include "BLI_set.hh"
34#include "BLI_span.hh"
35#include "BLI_string.h"
36#include "BLI_string_ref.hh"
37#include "BLI_string_utf8.h"
38#include "BLI_string_utils.hh"
39#include "BLI_utildefines.h"
40
41#ifndef NDEBUG
42# include "BLI_dynstr.h"
43#endif
44
45#include "BLT_translation.hh"
46
48#include "BKE_attribute_math.hh"
49#include "BKE_customdata.hh"
50#include "BKE_customdata_file.h"
51#include "BKE_deform.hh"
52#include "BKE_main.hh"
53#include "BKE_mesh_mapping.hh"
54#include "BKE_mesh_remap.hh"
55#include "BKE_multires.hh"
56#include "BKE_subsurf.hh"
57
58#include "BLO_read_write.hh"
59
60#include "bmesh.hh"
61
62#include "CLG_log.h"
63
64/* only for customdata_data_transfer_interp_normal_normals */
66
67using blender::Array;
69using blender::float2;
73using blender::Set;
74using blender::Span;
76using blender::Vector;
77
78/* number of layers to add when growing a CustomData object */
79#define CUSTOMDATA_GROW 5
80
81/* ensure typemap size is ok */
82BLI_STATIC_ASSERT(BOUNDED_ARRAY_TYPE_SIZE<decltype(CustomData::typemap)>() == CD_NUMTYPES,
83 "size mismatch");
84
85static CLG_LogRef LOG = {"bke.customdata"};
86
87/* -------------------------------------------------------------------- */
92 const CustomData_MeshMasks *mask_src)
93{
94 mask_dst->vmask |= mask_src->vmask;
95 mask_dst->emask |= mask_src->emask;
96 mask_dst->fmask |= mask_src->fmask;
97 mask_dst->pmask |= mask_src->pmask;
98 mask_dst->lmask |= mask_src->lmask;
99}
100
102 const CustomData_MeshMasks *mask_required)
103{
104 return (((mask_required->vmask & mask_ref->vmask) == mask_required->vmask) &&
105 ((mask_required->emask & mask_ref->emask) == mask_required->emask) &&
106 ((mask_required->fmask & mask_ref->fmask) == mask_required->fmask) &&
107 ((mask_required->pmask & mask_ref->pmask) == mask_required->pmask) &&
108 ((mask_required->lmask & mask_ref->lmask) == mask_required->lmask));
109}
110
113/* -------------------------------------------------------------------- */
118 int size; /* the memory size of one element of this layer's data */
120
122 const char *structname;
125
132 const char *defaultname;
133
140
148
163
165 void (*swap)(void *data, const int *corner_indices);
166
176 void (*construct)(void *data, int count);
177
180
182 bool (*equal)(const void *data1, const void *data2);
183 void (*multiply)(void *data, float fac);
184 void (*initminmax)(void *min, void *max);
185 void (*add)(void *data1, const void *data2);
186 void (*dominmax)(const void *data1, void *min, void *max);
187 void (*copyvalue)(const void *source, void *dest, int mixmode, const float mixfactor);
188
190 bool (*read)(CDataFile *cdf, void *data, int count);
191
193 bool (*write)(CDataFile *cdf, const void *data, int count);
194
196 size_t (*filesize)(CDataFile *cdf, const void *data, int count);
197
201};
202
205/* -------------------------------------------------------------------- */
209static void layerCopy_mdeformvert(const void *source, void *dest, const int count)
210{
211 int i, size = sizeof(MDeformVert);
212
213 memcpy(dest, source, count * size);
214
215 for (i = 0; i < count; i++) {
216 MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(dest, i * size));
217
218 if (dvert->totweight) {
219 MDeformWeight *dw = static_cast<MDeformWeight *>(
220 MEM_malloc_arrayN(dvert->totweight, sizeof(*dw), __func__));
221
222 memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
223 dvert->dw = dw;
224 }
225 else {
226 dvert->dw = nullptr;
227 }
228 }
229}
230
231static void layerFree_mdeformvert(void *data, const int count)
232{
233 for (MDeformVert &dvert : MutableSpan(static_cast<MDeformVert *>(data), count)) {
234 if (dvert.dw) {
235 MEM_freeN(dvert.dw);
236 dvert.dw = nullptr;
237 dvert.totweight = 0;
238 }
239 }
240}
241
242static void layerInterp_mdeformvert(const void **sources,
243 const float *weights,
244 const float * /*sub_weights*/,
245 const int count,
246 void *dest)
247{
248 /* A single linked list of #MDeformWeight's.
249 * use this to avoid double allocations (which #LinkNode would do). */
250 struct MDeformWeight_Link {
251 MDeformWeight_Link *next;
252 MDeformWeight dw;
253 };
254
255 MDeformVert *dvert = static_cast<MDeformVert *>(dest);
256 MDeformWeight_Link *dest_dwlink = nullptr;
257 MDeformWeight_Link *node;
258
259 /* build a list of unique def_nrs for dest */
260 int totweight = 0;
261 for (int i = 0; i < count; i++) {
262 const MDeformVert *source = static_cast<const MDeformVert *>(sources[i]);
263 float interp_weight = weights[i];
264
265 for (int j = 0; j < source->totweight; j++) {
266 MDeformWeight *dw = &source->dw[j];
267 float weight = dw->weight * interp_weight;
268
269 if (weight == 0.0f) {
270 continue;
271 }
272
273 for (node = dest_dwlink; node; node = node->next) {
274 MDeformWeight *tmp_dw = &node->dw;
275
276 if (tmp_dw->def_nr == dw->def_nr) {
277 tmp_dw->weight += weight;
278 break;
279 }
280 }
281
282 /* if this def_nr is not in the list, add it */
283 if (!node) {
284 MDeformWeight_Link *tmp_dwlink = static_cast<MDeformWeight_Link *>(
285 alloca(sizeof(*tmp_dwlink)));
286 tmp_dwlink->dw.def_nr = dw->def_nr;
287 tmp_dwlink->dw.weight = weight;
288
289 /* Inline linked-list. */
290 tmp_dwlink->next = dest_dwlink;
291 dest_dwlink = tmp_dwlink;
292
293 totweight++;
294 }
295 }
296 }
297
298 /* Delay writing to the destination in case dest is in sources. */
299
300 /* now we know how many unique deform weights there are, so realloc */
301 if (dvert->dw && (dvert->totweight == totweight)) {
302 /* pass (fast-path if we don't need to realloc). */
303 }
304 else {
305 if (dvert->dw) {
306 MEM_freeN(dvert->dw);
307 }
308
309 if (totweight) {
310 dvert->dw = static_cast<MDeformWeight *>(
311 MEM_malloc_arrayN(totweight, sizeof(*dvert->dw), __func__));
312 }
313 }
314
315 if (totweight) {
316 dvert->totweight = totweight;
317 int i = 0;
318 for (node = dest_dwlink; node; node = node->next, i++) {
319 if (node->dw.weight > 1.0f) {
320 node->dw.weight = 1.0f;
321 }
322 dvert->dw[i] = node->dw;
323 }
324 }
325 else {
326 memset(dvert, 0, sizeof(*dvert));
327 }
328}
329
330static void layerConstruct_mdeformvert(void *data, const int count)
331{
332 memset(data, 0, sizeof(MDeformVert) * count);
333}
334
337/* -------------------------------------------------------------------- */
341static void layerInterp_normal(const void **sources,
342 const float *weights,
343 const float * /*sub_weights*/,
344 const int count,
345 void *dest)
346{
347 /* NOTE: This is linear interpolation, which is not optimal for vectors.
348 * Unfortunately, spherical interpolation of more than two values is hairy,
349 * so for now it will do... */
350 float no[3] = {0.0f};
351
352 for (const int i : IndexRange(count)) {
353 madd_v3_v3fl(no, (const float *)sources[i], weights[i]);
354 }
355
356 /* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */
357 normalize_v3_v3((float *)dest, no);
358}
359
360static void layerCopyValue_normal(const void *source,
361 void *dest,
362 const int mixmode,
363 const float mixfactor)
364{
365 const float *no_src = (const float *)source;
366 float *no_dst = (float *)dest;
367 float no_tmp[3];
368
369 if (ELEM(mixmode,
373 {
374 /* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
375 copy_v3_v3(no_dst, no_src);
376 }
377 else { /* Modes that support 'real' mix factor. */
378 /* Since we normalize in the end, MIX and ADD are the same op here. */
379 if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
380 add_v3_v3v3(no_tmp, no_dst, no_src);
381 normalize_v3(no_tmp);
382 }
383 else if (mixmode == CDT_MIX_SUB) {
384 sub_v3_v3v3(no_tmp, no_dst, no_src);
385 normalize_v3(no_tmp);
386 }
387 else if (mixmode == CDT_MIX_MUL) {
388 mul_v3_v3v3(no_tmp, no_dst, no_src);
389 normalize_v3(no_tmp);
390 }
391 else {
392 copy_v3_v3(no_tmp, no_src);
393 }
394 interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
395 }
396}
397
400/* -------------------------------------------------------------------- */
404static void layerCopy_tface(const void *source, void *dest, const int count)
405{
406 const MTFace *source_tf = (const MTFace *)source;
407 MTFace *dest_tf = (MTFace *)dest;
408 for (int i = 0; i < count; i++) {
409 dest_tf[i] = source_tf[i];
410 }
411}
412
413static void layerInterp_tface(const void **sources,
414 const float *weights,
415 const float *sub_weights,
416 const int count,
417 void *dest)
418{
419 MTFace *tf = static_cast<MTFace *>(dest);
420 float uv[4][2] = {{0.0f}};
421
422 const float *sub_weight = sub_weights;
423 for (int i = 0; i < count; i++) {
424 const float interp_weight = weights[i];
425 const MTFace *src = static_cast<const MTFace *>(sources[i]);
426
427 for (int j = 0; j < 4; j++) {
428 if (sub_weights) {
429 for (int k = 0; k < 4; k++, sub_weight++) {
430 madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
431 }
432 }
433 else {
434 madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
435 }
436 }
437 }
438
439 /* Delay writing to the destination in case dest is in sources. */
440 *tf = *(MTFace *)(*sources);
441 memcpy(tf->uv, uv, sizeof(tf->uv));
442}
443
444static void layerSwap_tface(void *data, const int *corner_indices)
445{
446 MTFace *tf = static_cast<MTFace *>(data);
447 float uv[4][2];
448
449 for (int j = 0; j < 4; j++) {
450 const int source_index = corner_indices[j];
451 copy_v2_v2(uv[j], tf->uv[source_index]);
452 }
453
454 memcpy(tf->uv, uv, sizeof(tf->uv));
455}
456
457static void layerDefault_tface(void *data, const int count)
458{
459 static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
460 MTFace *tf = (MTFace *)data;
461
462 for (int i = 0; i < count; i++) {
463 tf[i] = default_tf;
464 }
465}
466
468{
469 return MAX_MTFACE;
470}
471
474/* -------------------------------------------------------------------- */
478static void layerCopy_propFloat(const void *source, void *dest, const int count)
479{
480 memcpy(dest, source, sizeof(MFloatProperty) * count);
481}
482
483static void layerInterp_propFloat(const void **sources,
484 const float *weights,
485 const float * /*sub_weights*/,
486 const int count,
487 void *dest)
488{
489 float result = 0.0f;
490 for (int i = 0; i < count; i++) {
491 const float interp_weight = weights[i];
492 const float src = *(const float *)sources[i];
493 result += src * interp_weight;
494 }
495 *(float *)dest = result;
496}
497
498static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
499{
500 MFloatProperty *fp = static_cast<MFloatProperty *>(data);
501 bool has_errors = false;
502
503 for (int i = 0; i < totitems; i++, fp++) {
504 if (!isfinite(fp->f)) {
505 if (do_fixes) {
506 fp->f = 0.0f;
507 }
508 has_errors = true;
509 }
510 }
511
512 return has_errors;
513}
514
517/* -------------------------------------------------------------------- */
521static void layerInterp_propInt(const void **sources,
522 const float *weights,
523 const float * /*sub_weights*/,
524 const int count,
525 void *dest)
526{
527 float result = 0.0f;
528 for (const int i : IndexRange(count)) {
529 const float weight = weights[i];
530 const float src = *static_cast<const int *>(sources[i]);
531 result += src * weight;
532 }
533 const int rounded_result = int(round(result));
534 *static_cast<int *>(dest) = rounded_result;
535}
536
539/* -------------------------------------------------------------------- */
543static void layerCopy_propString(const void *source, void *dest, const int count)
544{
545 memcpy(dest, source, sizeof(MStringProperty) * count);
546}
547
550/* -------------------------------------------------------------------- */
554static void layerCopy_origspace_face(const void *source, void *dest, const int count)
555{
556 const OrigSpaceFace *source_tf = (const OrigSpaceFace *)source;
557 OrigSpaceFace *dest_tf = (OrigSpaceFace *)dest;
558
559 for (int i = 0; i < count; i++) {
560 dest_tf[i] = source_tf[i];
561 }
562}
563
564static void layerInterp_origspace_face(const void **sources,
565 const float *weights,
566 const float *sub_weights,
567 const int count,
568 void *dest)
569{
570 OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(dest);
571 float uv[4][2] = {{0.0f}};
572
573 const float *sub_weight = sub_weights;
574 for (int i = 0; i < count; i++) {
575 const float interp_weight = weights[i];
576 const OrigSpaceFace *src = static_cast<const OrigSpaceFace *>(sources[i]);
577
578 for (int j = 0; j < 4; j++) {
579 if (sub_weights) {
580 for (int k = 0; k < 4; k++, sub_weight++) {
581 madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
582 }
583 }
584 else {
585 madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
586 }
587 }
588 }
589
590 /* Delay writing to the destination in case dest is in sources. */
591 memcpy(osf->uv, uv, sizeof(osf->uv));
592}
593
594static void layerSwap_origspace_face(void *data, const int *corner_indices)
595{
596 OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(data);
597 float uv[4][2];
598
599 for (int j = 0; j < 4; j++) {
600 copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
601 }
602 memcpy(osf->uv, uv, sizeof(osf->uv));
603}
604
605static void layerDefault_origspace_face(void *data, const int count)
606{
607 static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
608 OrigSpaceFace *osf = (OrigSpaceFace *)data;
609
610 for (int i = 0; i < count; i++) {
611 osf[i] = default_osf;
612 }
613}
614
617/* -------------------------------------------------------------------- */
621static void layerSwap_mdisps(void *data, const int *ci)
622{
623 MDisps *s = static_cast<MDisps *>(data);
624
625 if (s->disps) {
626 int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
627 int corners = multires_mdisp_corners(s);
628 int cornersize = s->totdisp / corners;
629
630 if (corners != nverts) {
631 /* happens when face changed vertex count in edit mode
632 * if it happened, just forgot displacement */
633
634 MEM_freeN(s->disps);
635 s->totdisp = (s->totdisp / corners) * nverts;
636 s->disps = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisp swap");
637 return;
638 }
639
640 float(*d)[3] = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
641
642 for (int S = 0; S < corners; S++) {
643 memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize);
644 }
645
646 MEM_freeN(s->disps);
647 s->disps = d;
648 }
649}
650
651static void layerCopy_mdisps(const void *source, void *dest, const int count)
652{
653 const MDisps *s = static_cast<const MDisps *>(source);
654 MDisps *d = static_cast<MDisps *>(dest);
655
656 for (int i = 0; i < count; i++) {
657 if (s[i].disps) {
658 d[i].disps = static_cast<float(*)[3]>(MEM_dupallocN(s[i].disps));
659 d[i].hidden = static_cast<uint *>(MEM_dupallocN(s[i].hidden));
660 }
661 else {
662 d[i].disps = nullptr;
663 d[i].hidden = nullptr;
664 }
665
666 /* still copy even if not in memory, displacement can be external */
667 d[i].totdisp = s[i].totdisp;
668 d[i].level = s[i].level;
669 }
670}
671
672static void layerFree_mdisps(void *data, const int count)
673{
674 for (MDisps &d : MutableSpan(static_cast<MDisps *>(data), count)) {
675 MEM_SAFE_FREE(d.disps);
676 MEM_SAFE_FREE(d.hidden);
677 d.totdisp = 0;
678 d.level = 0;
679 }
680}
681
682static void layerConstruct_mdisps(void *data, const int count)
683{
684 memset(data, 0, sizeof(MDisps) * count);
685}
686
687static bool layerRead_mdisps(CDataFile *cdf, void *data, const int count)
688{
689 MDisps *d = static_cast<MDisps *>(data);
690
691 for (int i = 0; i < count; i++) {
692 if (!d[i].disps) {
693 d[i].disps = (float(*)[3])MEM_calloc_arrayN(d[i].totdisp, sizeof(float[3]), "mdisps read");
694 }
695
696 if (!cdf_read_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
697 CLOG_ERROR(&LOG, "failed to read multires displacement %d/%d %d", i, count, d[i].totdisp);
698 return false;
699 }
700 }
701
702 return true;
703}
704
705static bool layerWrite_mdisps(CDataFile *cdf, const void *data, const int count)
706{
707 const MDisps *d = static_cast<const MDisps *>(data);
708
709 for (int i = 0; i < count; i++) {
710 if (!cdf_write_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
711 CLOG_ERROR(&LOG, "failed to write multires displacement %d/%d %d", i, count, d[i].totdisp);
712 return false;
713 }
714 }
715
716 return true;
717}
718
719static size_t layerFilesize_mdisps(CDataFile * /*cdf*/, const void *data, const int count)
720{
721 const MDisps *d = static_cast<const MDisps *>(data);
722 size_t size = 0;
723
724 for (int i = 0; i < count; i++) {
725 size += sizeof(float[3]) * d[i].totdisp;
726 }
727
728 return size;
729}
730
733/* -------------------------------------------------------------------- */
737/* copy just zeros in this case */
738static void layerCopy_bmesh_elem_py_ptr(const void * /*source*/, void *dest, const int count)
739{
740 const int size = sizeof(void *);
741
742 for (int i = 0; i < count; i++) {
743 void **ptr = (void **)POINTER_OFFSET(dest, i * size);
744 *ptr = nullptr;
745 }
746}
747
748#ifndef WITH_PYTHON
750{
751 /* dummy */
752}
753#endif
754
755static void layerFree_bmesh_elem_py_ptr(void *data, const int count)
756{
757 for (int i = 0; i < count; i++) {
758 void **ptr = (void **)POINTER_OFFSET(data, i * sizeof(void *));
759 if (*ptr) {
761 }
762 }
763}
764
767/* -------------------------------------------------------------------- */
771static void layerCopy_grid_paint_mask(const void *source, void *dest, const int count)
772{
773 const GridPaintMask *s = static_cast<const GridPaintMask *>(source);
774 GridPaintMask *d = static_cast<GridPaintMask *>(dest);
775
776 for (int i = 0; i < count; i++) {
777 if (s[i].data) {
778 d[i].data = static_cast<float *>(MEM_dupallocN(s[i].data));
779 d[i].level = s[i].level;
780 }
781 else {
782 d[i].data = nullptr;
783 d[i].level = 0;
784 }
785 }
786}
787
788static void layerFree_grid_paint_mask(void *data, const int count)
789{
790 for (GridPaintMask &gpm : MutableSpan(static_cast<GridPaintMask *>(data), count)) {
791 MEM_SAFE_FREE(gpm.data);
792 gpm.level = 0;
793 }
794}
795
796static void layerConstruct_grid_paint_mask(void *data, const int count)
797{
798 memset(data, 0, sizeof(GridPaintMask) * count);
799}
800
803/* -------------------------------------------------------------------- */
807static void layerCopyValue_mloopcol(const void *source,
808 void *dest,
809 const int mixmode,
810 const float mixfactor)
811{
812 const MLoopCol *m1 = static_cast<const MLoopCol *>(source);
813 MLoopCol *m2 = static_cast<MLoopCol *>(dest);
814 uchar tmp_col[4];
815
816 if (ELEM(mixmode,
820 {
821 /* Modes that do a full copy or nothing. */
823 /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
824 const float f = (float(m2->r) + float(m2->g) + float(m2->b)) / 3.0f;
825 if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
826 return; /* Do Nothing! */
827 }
828 if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
829 return; /* Do Nothing! */
830 }
831 }
832 m2->r = m1->r;
833 m2->g = m1->g;
834 m2->b = m1->b;
835 m2->a = m1->a;
836 }
837 else { /* Modes that support 'real' mix factor. */
838 uchar src[4] = {m1->r, m1->g, m1->b, m1->a};
839 uchar dst[4] = {m2->r, m2->g, m2->b, m2->a};
840
841 if (mixmode == CDT_MIX_MIX) {
842 blend_color_mix_byte(tmp_col, dst, src);
843 }
844 else if (mixmode == CDT_MIX_ADD) {
845 blend_color_add_byte(tmp_col, dst, src);
846 }
847 else if (mixmode == CDT_MIX_SUB) {
848 blend_color_sub_byte(tmp_col, dst, src);
849 }
850 else if (mixmode == CDT_MIX_MUL) {
851 blend_color_mul_byte(tmp_col, dst, src);
852 }
853 else {
854 memcpy(tmp_col, src, sizeof(tmp_col));
855 }
856
857 blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
858
859 m2->r = char(dst[0]);
860 m2->g = char(dst[1]);
861 m2->b = char(dst[2]);
862 m2->a = char(dst[3]);
863 }
864}
865
866static bool layerEqual_mloopcol(const void *data1, const void *data2)
867{
868 const MLoopCol *m1 = static_cast<const MLoopCol *>(data1);
869 const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
870 float r, g, b, a;
871
872 r = m1->r - m2->r;
873 g = m1->g - m2->g;
874 b = m1->b - m2->b;
875 a = m1->a - m2->a;
876
877 return r * r + g * g + b * b + a * a < 0.001f;
878}
879
880static void layerMultiply_mloopcol(void *data, const float fac)
881{
882 MLoopCol *m = static_cast<MLoopCol *>(data);
883
884 m->r = float(m->r) * fac;
885 m->g = float(m->g) * fac;
886 m->b = float(m->b) * fac;
887 m->a = float(m->a) * fac;
888}
889
890static void layerAdd_mloopcol(void *data1, const void *data2)
891{
892 MLoopCol *m = static_cast<MLoopCol *>(data1);
893 const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
894
895 m->r += m2->r;
896 m->g += m2->g;
897 m->b += m2->b;
898 m->a += m2->a;
899}
900
901static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
902{
903 const MLoopCol *m = static_cast<const MLoopCol *>(data);
904 MLoopCol *min = static_cast<MLoopCol *>(vmin);
905 MLoopCol *max = static_cast<MLoopCol *>(vmax);
906
907 if (m->r < min->r) {
908 min->r = m->r;
909 }
910 if (m->g < min->g) {
911 min->g = m->g;
912 }
913 if (m->b < min->b) {
914 min->b = m->b;
915 }
916 if (m->a < min->a) {
917 min->a = m->a;
918 }
919 if (m->r > max->r) {
920 max->r = m->r;
921 }
922 if (m->g > max->g) {
923 max->g = m->g;
924 }
925 if (m->b > max->b) {
926 max->b = m->b;
927 }
928 if (m->a > max->a) {
929 max->a = m->a;
930 }
931}
932
933static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
934{
935 MLoopCol *min = static_cast<MLoopCol *>(vmin);
936 MLoopCol *max = static_cast<MLoopCol *>(vmax);
937
938 min->r = 255;
939 min->g = 255;
940 min->b = 255;
941 min->a = 255;
942
943 max->r = 0;
944 max->g = 0;
945 max->b = 0;
946 max->a = 0;
947}
948
949static void layerDefault_mloopcol(void *data, const int count)
950{
951 MLoopCol default_mloopcol = {255, 255, 255, 255};
952 MLoopCol *mlcol = (MLoopCol *)data;
953 for (int i = 0; i < count; i++) {
954 mlcol[i] = default_mloopcol;
955 }
956}
957
958static void layerInterp_mloopcol(const void **sources,
959 const float *weights,
960 const float * /*sub_weights*/,
961 int count,
962 void *dest)
963{
964 MLoopCol *mc = static_cast<MLoopCol *>(dest);
965 struct {
966 float a;
967 float r;
968 float g;
969 float b;
970 } col = {0};
971
972 for (int i = 0; i < count; i++) {
973 const float interp_weight = weights[i];
974 const MLoopCol *src = static_cast<const MLoopCol *>(sources[i]);
975 col.r += src->r * interp_weight;
976 col.g += src->g * interp_weight;
977 col.b += src->b * interp_weight;
978 col.a += src->a * interp_weight;
979 }
980
981 /* Subdivide smooth or fractal can cause problems without clamping
982 * although weights should also not cause this situation */
983
984 /* Also delay writing to the destination in case dest is in sources. */
989}
990
993/* -------------------------------------------------------------------- */
997/* origspace is almost exact copy of #MLoopUV, keep in sync. */
998static void layerCopyValue_mloop_origspace(const void *source,
999 void *dest,
1000 const int /*mixmode*/,
1001 const float /*mixfactor*/)
1002{
1003 const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source);
1004 OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest);
1005
1006 copy_v2_v2(luv2->uv, luv1->uv);
1007}
1008
1009static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
1010{
1011 const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(data1);
1012 const OrigSpaceLoop *luv2 = static_cast<const OrigSpaceLoop *>(data2);
1013
1014 return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
1015}
1016
1017static void layerMultiply_mloop_origspace(void *data, const float fac)
1018{
1019 OrigSpaceLoop *luv = static_cast<OrigSpaceLoop *>(data);
1020
1021 mul_v2_fl(luv->uv, fac);
1022}
1023
1024static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
1025{
1026 OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
1027 OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
1028
1029 INIT_MINMAX2(min->uv, max->uv);
1030}
1031
1032static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
1033{
1034 const OrigSpaceLoop *luv = static_cast<const OrigSpaceLoop *>(data);
1035 OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
1036 OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
1037
1038 minmax_v2v2_v2(min->uv, max->uv, luv->uv);
1039}
1040
1041static void layerAdd_mloop_origspace(void *data1, const void *data2)
1042{
1043 OrigSpaceLoop *l1 = static_cast<OrigSpaceLoop *>(data1);
1044 const OrigSpaceLoop *l2 = static_cast<const OrigSpaceLoop *>(data2);
1045
1046 add_v2_v2(l1->uv, l2->uv);
1047}
1048
1049static void layerInterp_mloop_origspace(const void **sources,
1050 const float *weights,
1051 const float * /*sub_weights*/,
1052 int count,
1053 void *dest)
1054{
1055 float uv[2];
1056 zero_v2(uv);
1057
1058 for (int i = 0; i < count; i++) {
1059 const float interp_weight = weights[i];
1060 const OrigSpaceLoop *src = static_cast<const OrigSpaceLoop *>(sources[i]);
1061 madd_v2_v2fl(uv, src->uv, interp_weight);
1062 }
1063
1064 /* Delay writing to the destination in case dest is in sources. */
1065 copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
1066}
1067/* --- end copy */
1068
1069static void layerInterp_mcol(const void **sources,
1070 const float *weights,
1071 const float *sub_weights,
1072 const int count,
1073 void *dest)
1074{
1075 MCol *mc = static_cast<MCol *>(dest);
1076 struct {
1077 float a;
1078 float r;
1079 float g;
1080 float b;
1081 } col[4] = {{0.0f}};
1082
1083 const float *sub_weight = sub_weights;
1084 for (int i = 0; i < count; i++) {
1085 const float interp_weight = weights[i];
1086
1087 for (int j = 0; j < 4; j++) {
1088 if (sub_weights) {
1089 const MCol *src = static_cast<const MCol *>(sources[i]);
1090 for (int k = 0; k < 4; k++, sub_weight++, src++) {
1091 const float w = (*sub_weight) * interp_weight;
1092 col[j].a += src->a * w;
1093 col[j].r += src->r * w;
1094 col[j].g += src->g * w;
1095 col[j].b += src->b * w;
1096 }
1097 }
1098 else {
1099 const MCol *src = static_cast<const MCol *>(sources[i]);
1100 col[j].a += src[j].a * interp_weight;
1101 col[j].r += src[j].r * interp_weight;
1102 col[j].g += src[j].g * interp_weight;
1103 col[j].b += src[j].b * interp_weight;
1104 }
1105 }
1106 }
1107
1108 /* Delay writing to the destination in case dest is in sources. */
1109 for (int j = 0; j < 4; j++) {
1110
1111 /* Subdivide smooth or fractal can cause problems without clamping
1112 * although weights should also not cause this situation */
1113 mc[j].a = round_fl_to_uchar_clamp(col[j].a);
1114 mc[j].r = round_fl_to_uchar_clamp(col[j].r);
1115 mc[j].g = round_fl_to_uchar_clamp(col[j].g);
1116 mc[j].b = round_fl_to_uchar_clamp(col[j].b);
1117 }
1118}
1119
1120static void layerSwap_mcol(void *data, const int *corner_indices)
1121{
1122 MCol *mcol = static_cast<MCol *>(data);
1123 MCol col[4];
1124
1125 for (int j = 0; j < 4; j++) {
1126 col[j] = mcol[corner_indices[j]];
1127 }
1128
1129 memcpy(mcol, col, sizeof(col));
1130}
1131
1132static void layerDefault_mcol(void *data, const int count)
1133{
1134 static MCol default_mcol = {255, 255, 255, 255};
1135 MCol *mcol = (MCol *)data;
1136
1137 for (int i = 0; i < 4 * count; i++) {
1138 mcol[i] = default_mcol;
1139 }
1140}
1141
1142static void layerDefault_origindex(void *data, const int count)
1143{
1144 copy_vn_i((int *)data, count, ORIGINDEX_NONE);
1145}
1146
1147static void layerInterp_shapekey(const void **sources,
1148 const float *weights,
1149 const float * /*sub_weights*/,
1150 int count,
1151 void *dest)
1152{
1153 float **in = (float **)sources;
1154
1155 if (count <= 0) {
1156 return;
1157 }
1158
1159 float co[3];
1160 zero_v3(co);
1161
1162 for (int i = 0; i < count; i++) {
1163 const float interp_weight = weights[i];
1164 madd_v3_v3fl(co, in[i], interp_weight);
1165 }
1166
1167 /* Delay writing to the destination in case dest is in sources. */
1168 copy_v3_v3((float *)dest, co);
1169}
1170
1173/* -------------------------------------------------------------------- */
1177static void layerDefault_mvert_skin(void *data, const int count)
1178{
1179 MVertSkin *vs = static_cast<MVertSkin *>(data);
1180
1181 for (int i = 0; i < count; i++) {
1182 copy_v3_fl(vs[i].radius, 0.25f);
1183 vs[i].flag = 0;
1184 }
1185}
1186
1187static void layerCopy_mvert_skin(const void *source, void *dest, const int count)
1188{
1189 memcpy(dest, source, sizeof(MVertSkin) * count);
1190}
1191
1192static void layerInterp_mvert_skin(const void **sources,
1193 const float *weights,
1194 const float * /*sub_weights*/,
1195 int count,
1196 void *dest)
1197{
1198 float radius[3];
1199 zero_v3(radius);
1200
1201 for (int i = 0; i < count; i++) {
1202 const float interp_weight = weights[i];
1203 const MVertSkin *vs_src = static_cast<const MVertSkin *>(sources[i]);
1204
1205 madd_v3_v3fl(radius, vs_src->radius, interp_weight);
1206 }
1207
1208 /* Delay writing to the destination in case dest is in sources. */
1209 MVertSkin *vs_dst = static_cast<MVertSkin *>(dest);
1210 copy_v3_v3(vs_dst->radius, radius);
1211 vs_dst->flag &= ~MVERT_SKIN_ROOT;
1212}
1213
1216/* -------------------------------------------------------------------- */
1220static void layerSwap_flnor(void *data, const int *corner_indices)
1221{
1222 short(*flnors)[4][3] = static_cast<short(*)[4][3]>(data);
1223 short nors[4][3];
1224 int i = 4;
1225
1226 while (i--) {
1227 copy_v3_v3_short(nors[i], (*flnors)[corner_indices[i]]);
1228 }
1229
1230 memcpy(flnors, nors, sizeof(nors));
1231}
1232
1235/* -------------------------------------------------------------------- */
1239static void layerCopyValue_propcol(const void *source,
1240 void *dest,
1241 const int mixmode,
1242 const float mixfactor)
1243{
1244 const MPropCol *m1 = static_cast<const MPropCol *>(source);
1245 MPropCol *m2 = static_cast<MPropCol *>(dest);
1246 float tmp_col[4];
1247
1248 if (ELEM(mixmode,
1252 {
1253 /* Modes that do a full copy or nothing. */
1255 /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
1256 const float f = (m2->color[0] + m2->color[1] + m2->color[2]) / 3.0f;
1257 if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
1258 return; /* Do Nothing! */
1259 }
1260 if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
1261 return; /* Do Nothing! */
1262 }
1263 }
1264 copy_v4_v4(m2->color, m1->color);
1265 }
1266 else { /* Modes that support 'real' mix factor. */
1267 if (mixmode == CDT_MIX_MIX) {
1268 blend_color_mix_float(tmp_col, m2->color, m1->color);
1269 }
1270 else if (mixmode == CDT_MIX_ADD) {
1271 blend_color_add_float(tmp_col, m2->color, m1->color);
1272 }
1273 else if (mixmode == CDT_MIX_SUB) {
1274 blend_color_sub_float(tmp_col, m2->color, m1->color);
1275 }
1276 else if (mixmode == CDT_MIX_MUL) {
1277 blend_color_mul_float(tmp_col, m2->color, m1->color);
1278 }
1279 else {
1280 memcpy(tmp_col, m1->color, sizeof(tmp_col));
1281 }
1282 blend_color_interpolate_float(m2->color, m2->color, tmp_col, mixfactor);
1283 }
1284}
1285
1286static bool layerEqual_propcol(const void *data1, const void *data2)
1287{
1288 const MPropCol *m1 = static_cast<const MPropCol *>(data1);
1289 const MPropCol *m2 = static_cast<const MPropCol *>(data2);
1290 float tot = 0;
1291
1292 for (int i = 0; i < 4; i++) {
1293 float c = (m1->color[i] - m2->color[i]);
1294 tot += c * c;
1295 }
1296
1297 return tot < 0.001f;
1298}
1299
1300static void layerMultiply_propcol(void *data, const float fac)
1301{
1302 MPropCol *m = static_cast<MPropCol *>(data);
1303 mul_v4_fl(m->color, fac);
1304}
1305
1306static void layerAdd_propcol(void *data1, const void *data2)
1307{
1308 MPropCol *m = static_cast<MPropCol *>(data1);
1309 const MPropCol *m2 = static_cast<const MPropCol *>(data2);
1310 add_v4_v4(m->color, m2->color);
1311}
1312
1313static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
1314{
1315 const MPropCol *m = static_cast<const MPropCol *>(data);
1316 MPropCol *min = static_cast<MPropCol *>(vmin);
1317 MPropCol *max = static_cast<MPropCol *>(vmax);
1318 minmax_v4v4_v4(min->color, max->color, m->color);
1319}
1320
1321static void layerInitMinMax_propcol(void *vmin, void *vmax)
1322{
1323 MPropCol *min = static_cast<MPropCol *>(vmin);
1324 MPropCol *max = static_cast<MPropCol *>(vmax);
1325
1326 copy_v4_fl(min->color, FLT_MAX);
1327 copy_v4_fl(max->color, FLT_MIN);
1328}
1329
1330static void layerDefault_propcol(void *data, const int count)
1331{
1332 /* Default to white, full alpha. */
1333 MPropCol default_propcol = {{1.0f, 1.0f, 1.0f, 1.0f}};
1334 MPropCol *pcol = (MPropCol *)data;
1335 for (int i = 0; i < count; i++) {
1336 copy_v4_v4(pcol[i].color, default_propcol.color);
1337 }
1338}
1339
1340static void layerInterp_propcol(const void **sources,
1341 const float *weights,
1342 const float * /*sub_weights*/,
1343 int count,
1344 void *dest)
1345{
1346 MPropCol *mc = static_cast<MPropCol *>(dest);
1347 float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1348 for (int i = 0; i < count; i++) {
1349 const float interp_weight = weights[i];
1350 const MPropCol *src = static_cast<const MPropCol *>(sources[i]);
1351 madd_v4_v4fl(col, src->color, interp_weight);
1352 }
1353 copy_v4_v4(mc->color, col);
1354}
1355
1358/* -------------------------------------------------------------------- */
1362static void layerInterp_propfloat3(const void **sources,
1363 const float *weights,
1364 const float * /*sub_weights*/,
1365 int count,
1366 void *dest)
1367{
1368 vec3f result = {0.0f, 0.0f, 0.0f};
1369 for (int i = 0; i < count; i++) {
1370 const float interp_weight = weights[i];
1371 const vec3f *src = static_cast<const vec3f *>(sources[i]);
1372 madd_v3_v3fl(&result.x, &src->x, interp_weight);
1373 }
1374 copy_v3_v3((float *)dest, &result.x);
1375}
1376
1377static void layerMultiply_propfloat3(void *data, const float fac)
1378{
1379 vec3f *vec = static_cast<vec3f *>(data);
1380 vec->x *= fac;
1381 vec->y *= fac;
1382 vec->z *= fac;
1383}
1384
1385static void layerAdd_propfloat3(void *data1, const void *data2)
1386{
1387 vec3f *vec1 = static_cast<vec3f *>(data1);
1388 const vec3f *vec2 = static_cast<const vec3f *>(data2);
1389 vec1->x += vec2->x;
1390 vec1->y += vec2->y;
1391 vec1->z += vec2->z;
1392}
1393
1394static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
1395{
1396 float *values = static_cast<float *>(data);
1397 bool has_errors = false;
1398 for (int i = 0; i < totitems * 3; i++) {
1399 if (!isfinite(values[i])) {
1400 if (do_fixes) {
1401 values[i] = 0.0f;
1402 }
1403 has_errors = true;
1404 }
1405 }
1406 return has_errors;
1407}
1408
1411/* -------------------------------------------------------------------- */
1415static void layerInterp_propfloat2(const void **sources,
1416 const float *weights,
1417 const float * /*sub_weights*/,
1418 int count,
1419 void *dest)
1420{
1421 vec2f result = {0.0f, 0.0f};
1422 for (int i = 0; i < count; i++) {
1423 const float interp_weight = weights[i];
1424 const vec2f *src = static_cast<const vec2f *>(sources[i]);
1425 madd_v2_v2fl(&result.x, &src->x, interp_weight);
1426 }
1427 copy_v2_v2((float *)dest, &result.x);
1428}
1429
1430static void layerMultiply_propfloat2(void *data, const float fac)
1431{
1432 vec2f *vec = static_cast<vec2f *>(data);
1433 vec->x *= fac;
1434 vec->y *= fac;
1435}
1436
1437static void layerAdd_propfloat2(void *data1, const void *data2)
1438{
1439 vec2f *vec1 = static_cast<vec2f *>(data1);
1440 const vec2f *vec2 = static_cast<const vec2f *>(data2);
1441 vec1->x += vec2->x;
1442 vec1->y += vec2->y;
1443}
1444
1445static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
1446{
1447 float *values = static_cast<float *>(data);
1448 bool has_errors = false;
1449 for (int i = 0; i < totitems * 2; i++) {
1450 if (!isfinite(values[i])) {
1451 if (do_fixes) {
1452 values[i] = 0.0f;
1453 }
1454 has_errors = true;
1455 }
1456 }
1457 return has_errors;
1458}
1459
1460static bool layerEqual_propfloat2(const void *data1, const void *data2)
1461{
1462 const float2 &a = *static_cast<const float2 *>(data1);
1463 const float2 &b = *static_cast<const float2 *>(data2);
1464 return blender::math::distance_squared(a, b) < 0.00001f;
1465}
1466
1467static void layerInitMinMax_propfloat2(void *vmin, void *vmax)
1468{
1469 float2 &min = *static_cast<float2 *>(vmin);
1470 float2 &max = *static_cast<float2 *>(vmax);
1471 INIT_MINMAX2(min, max);
1472}
1473
1474static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax)
1475{
1476 const float2 &value = *static_cast<const float2 *>(data);
1477 float2 &a = *static_cast<float2 *>(vmin);
1478 float2 &b = *static_cast<float2 *>(vmax);
1479 blender::math::min_max(value, a, b);
1480}
1481
1482static void layerCopyValue_propfloat2(const void *source,
1483 void *dest,
1484 const int mixmode,
1485 const float mixfactor)
1486{
1487 const float2 &a = *static_cast<const float2 *>(source);
1488 float2 &b = *static_cast<float2 *>(dest);
1489
1490 /* We only support a limited subset of advanced mixing here-
1491 * namely the mixfactor interpolation. */
1492 if (mixmode == CDT_MIX_NOMIX) {
1493 b = a;
1494 }
1495 else {
1496 b = blender::math::interpolate(b, a, mixfactor);
1497 }
1498}
1499
1502/* -------------------------------------------------------------------- */
1506static void layerInterp_propbool(const void **sources,
1507 const float *weights,
1508 const float * /*sub_weights*/,
1509 int count,
1510 void *dest)
1511{
1512 bool result = false;
1513 for (int i = 0; i < count; i++) {
1514 const float interp_weight = weights[i];
1515 const bool src = *(const bool *)sources[i];
1516 result |= src && (interp_weight > 0.0f);
1517 }
1518 *(bool *)dest = result;
1519}
1520
1523/* -------------------------------------------------------------------- */
1527static void layerDefault_propquaternion(void *data, const int count)
1528{
1529 using namespace blender;
1530 MutableSpan(static_cast<math::Quaternion *>(data), count).fill(math::Quaternion::identity());
1531}
1532
1533static void layerInterp_propquaternion(const void **sources,
1534 const float *weights,
1535 const float * /*sub_weights*/,
1536 int count,
1537 void *dest)
1538{
1540 Quaternion result;
1542 Quaternion::identity());
1543
1544 for (int i = 0; i < count; i++) {
1545 const float interp_weight = weights[i];
1546 const Quaternion *src = static_cast<const Quaternion *>(sources[i]);
1547 mixer.mix_in(0, *src, interp_weight);
1548 }
1549 mixer.finalize();
1550 *static_cast<Quaternion *>(dest) = result;
1551}
1552
1553/* -------------------------------------------------------------------- */
1557static void layerDefault_propfloat4x4(void *data, const int count)
1558{
1559 using namespace blender;
1560 MutableSpan(static_cast<float4x4 *>(data), count).fill(float4x4::identity());
1561}
1562
1565/* -------------------------------------------------------------------- */
1570 /* 0: CD_MVERT */ /* DEPRECATED */
1571 {sizeof(MVert),
1572 alignof(MVert),
1573 "MVert",
1574 1,
1575 nullptr,
1576 nullptr,
1577 nullptr,
1578 nullptr,
1579 nullptr,
1580 nullptr},
1581 /* 1: CD_MSTICKY */ /* DEPRECATED */
1582 {sizeof(float[2]),
1583 alignof(float2),
1584 "",
1585 1,
1586 nullptr,
1587 nullptr,
1588 nullptr,
1589 nullptr,
1590 nullptr,
1591 nullptr},
1592 /* 2: CD_MDEFORMVERT */
1593 {sizeof(MDeformVert),
1594 alignof(MDeformVert),
1595 "MDeformVert",
1596 1,
1597 nullptr,
1601 nullptr,
1602 nullptr,
1604 /* 3: CD_MEDGE */ /* DEPRECATED */
1605 {sizeof(MEdge),
1606 alignof(MEdge),
1607 "MEdge",
1608 1,
1609 nullptr,
1610 nullptr,
1611 nullptr,
1612 nullptr,
1613 nullptr,
1614 nullptr},
1615 /* 4: CD_MFACE */
1616 {sizeof(MFace),
1617 alignof(MFace),
1618 "MFace",
1619 1,
1620 nullptr,
1621 nullptr,
1622 nullptr,
1623 nullptr,
1624 nullptr,
1625 nullptr},
1626 /* 5: CD_MTFACE */
1627 {sizeof(MTFace),
1628 alignof(MTFace),
1629 "MTFace",
1630 1,
1631 N_("UVMap"),
1633 nullptr,
1636 nullptr,
1638 nullptr,
1639 nullptr,
1640 nullptr,
1641 nullptr,
1642 nullptr,
1643 nullptr,
1644 nullptr,
1645 nullptr,
1646 nullptr,
1647 nullptr,
1649 /* 6: CD_MCOL */
1650 /* 4 MCol structs per face */
1651 {sizeof(MCol[4]),
1652 alignof(MCol[4]),
1653 "MCol",
1654 4,
1655 N_("Col"),
1656 nullptr,
1657 nullptr,
1661 /* 7: CD_ORIGINDEX */
1662 {sizeof(int),
1663 alignof(int),
1664 "",
1665 0,
1666 nullptr,
1667 nullptr,
1668 nullptr,
1669 nullptr,
1670 nullptr,
1672 /* 8: CD_NORMAL */
1673 /* 3 floats per normal vector */
1674 {sizeof(float[3]),
1675 alignof(blender::float3),
1676 "vec3f",
1677 1,
1678 nullptr,
1679 nullptr,
1680 nullptr,
1682 nullptr,
1683 nullptr,
1684 nullptr,
1685 nullptr,
1686 nullptr,
1687 nullptr,
1688 nullptr,
1689 nullptr,
1690 nullptr,
1692 /* 9: CD_FACEMAP */ /* DEPRECATED */
1693 {sizeof(int), alignof(int), ""},
1694 /* 10: CD_PROP_FLOAT */
1695 {sizeof(MFloatProperty),
1696 alignof(float),
1697 "MFloatProperty",
1698 1,
1699 N_("Float"),
1701 nullptr,
1703 nullptr,
1704 nullptr,
1705 nullptr,
1707 /* 11: CD_PROP_INT32 */
1708 {sizeof(MIntProperty),
1709 alignof(int),
1710 "MIntProperty",
1711 1,
1712 N_("Int"),
1713 nullptr,
1714 nullptr,
1716 nullptr},
1717 /* 12: CD_PROP_STRING */
1718 {sizeof(MStringProperty),
1719 alignof(MStringProperty),
1720 "MStringProperty",
1721 1,
1722 N_("String"),
1724 nullptr,
1725 nullptr,
1726 nullptr},
1727 /* 13: CD_ORIGSPACE */
1728 {sizeof(OrigSpaceFace),
1729 alignof(OrigSpaceFace),
1730 "OrigSpaceFace",
1731 1,
1732 N_("UVMap"),
1734 nullptr,
1738 /* 14: CD_ORCO */
1739 {sizeof(float[3]),
1740 alignof(blender::float3),
1741 "",
1742 0,
1743 nullptr,
1744 nullptr,
1745 nullptr,
1746 nullptr,
1747 nullptr,
1748 nullptr},
1749 /* 15: CD_MTEXPOLY */ /* DEPRECATED */
1750 /* NOTE: when we expose the UV Map / TexFace split to the user,
1751 * change this back to face Texture. */
1752 {sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1753 /* 16: CD_MLOOPUV */ /* DEPRECATED */
1754 {sizeof(MLoopUV), alignof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
1755 /* 17: CD_PROP_BYTE_COLOR */
1756 {sizeof(MLoopCol),
1757 alignof(MLoopCol),
1758 "MLoopCol",
1759 1,
1760 N_("Col"),
1761 nullptr,
1762 nullptr,
1764 nullptr,
1766 nullptr,
1767 nullptr,
1774 nullptr,
1775 nullptr,
1776 nullptr,
1777 nullptr},
1778 /* 18: CD_TANGENT */
1779 {sizeof(float[4]),
1780 alignof(float[4]),
1781 "",
1782 0,
1783 N_("Tangent"),
1784 nullptr,
1785 nullptr,
1786 nullptr,
1787 nullptr,
1788 nullptr},
1789 /* 19: CD_MDISPS */
1790 {sizeof(MDisps),
1791 alignof(MDisps),
1792 "MDisps",
1793 1,
1794 nullptr,
1797 nullptr,
1799 nullptr,
1801 nullptr,
1802 nullptr,
1803 nullptr,
1804 nullptr,
1805 nullptr,
1806 nullptr,
1807 nullptr,
1811 /* 20: CD_PREVIEW_MCOL */
1812 {sizeof(blender::float4x4),
1813 alignof(blender::float4x4),
1814 "mat4x4f",
1815 1,
1816 N_("4 by 4 Float Matrix"),
1817 nullptr,
1818 nullptr,
1819 nullptr,
1820 nullptr,
1822 /* 21: CD_ID_MCOL */ /* DEPRECATED */
1823 {sizeof(MCol[4]),
1824 alignof(MCol[4]),
1825 "",
1826 0,
1827 nullptr,
1828 nullptr,
1829 nullptr,
1830 nullptr,
1831 nullptr,
1832 nullptr},
1833 /* 22: CD_TEXTURE_MCOL */
1834 {sizeof(MCol[4]),
1835 alignof(MCol[4]),
1836 "MCol",
1837 4,
1838 N_("TexturedCol"),
1839 nullptr,
1840 nullptr,
1844 /* 23: CD_CLOTH_ORCO */
1845 {sizeof(float[3]),
1846 alignof(float[3]),
1847 "",
1848 0,
1849 nullptr,
1850 nullptr,
1851 nullptr,
1852 nullptr,
1853 nullptr,
1854 nullptr},
1855 /* 24: CD_RECAST */
1856 {sizeof(MRecast),
1857 alignof(MRecast),
1858 "MRecast",
1859 1,
1860 N_("Recast"),
1861 nullptr,
1862 nullptr,
1863 nullptr,
1864 nullptr},
1865 /* 25: CD_MPOLY */ /* DEPRECATED */
1866 {sizeof(MPoly),
1867 alignof(MPoly),
1868 "MPoly",
1869 1,
1870 N_("NGon Face"),
1871 nullptr,
1872 nullptr,
1873 nullptr,
1874 nullptr,
1875 nullptr},
1876 /* 26: CD_MLOOP */ /* DEPRECATED */
1877 {sizeof(MLoop),
1878 alignof(MLoop),
1879 "MLoop",
1880 1,
1881 N_("NGon Face-Vertex"),
1882 nullptr,
1883 nullptr,
1884 nullptr,
1885 nullptr,
1886 nullptr},
1887 /* 27: CD_SHAPE_KEYINDEX */
1888 {sizeof(int), alignof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1889 /* 28: CD_SHAPEKEY */
1890 {sizeof(float[3]),
1891 alignof(float[3]),
1892 "",
1893 0,
1894 N_("ShapeKey"),
1895 nullptr,
1896 nullptr,
1898 /* 29: CD_BWEIGHT */ /* DEPRECATED */
1899 {sizeof(MFloatProperty), alignof(MFloatProperty), "MFloatProperty", 1},
1900 /* 30: CD_CREASE */ /* DEPRECATED */
1901 {sizeof(float), alignof(float), ""},
1902 /* 31: CD_ORIGSPACE_MLOOP */
1903 {sizeof(OrigSpaceLoop),
1904 alignof(OrigSpaceLoop),
1905 "OrigSpaceLoop",
1906 1,
1907 N_("OS Loop"),
1908 nullptr,
1909 nullptr,
1911 nullptr,
1912 nullptr,
1913 nullptr,
1914 nullptr,
1921 /* 32: CD_PREVIEW_MLOOPCOL */ /* DEPRECATED */ /* UNUSED */
1922 {},
1923 /* 33: CD_BM_ELEM_PYPTR */
1924 {sizeof(void *),
1925 alignof(void *),
1926 "",
1927 1,
1928 nullptr,
1931 nullptr,
1932 nullptr,
1933 nullptr},
1934 /* 34: CD_PAINT_MASK */ /* DEPRECATED */
1935 {sizeof(float), alignof(float), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1936 /* 35: CD_GRID_PAINT_MASK */
1937 {sizeof(GridPaintMask),
1938 alignof(GridPaintMask),
1939 "GridPaintMask",
1940 1,
1941 nullptr,
1944 nullptr,
1945 nullptr,
1946 nullptr,
1948 /* 36: CD_MVERT_SKIN */
1949 {sizeof(MVertSkin),
1950 alignof(MVertSkin),
1951 "MVertSkin",
1952 1,
1953 nullptr,
1955 nullptr,
1957 nullptr,
1959 /* 37: CD_FREESTYLE_EDGE */
1960 {sizeof(FreestyleEdge),
1961 alignof(FreestyleEdge),
1962 "FreestyleEdge",
1963 1,
1964 nullptr,
1965 nullptr,
1966 nullptr,
1967 nullptr,
1968 nullptr,
1969 nullptr},
1970 /* 38: CD_FREESTYLE_FACE */
1971 {sizeof(FreestyleFace),
1972 alignof(FreestyleFace),
1973 "FreestyleFace",
1974 1,
1975 nullptr,
1976 nullptr,
1977 nullptr,
1978 nullptr,
1979 nullptr,
1980 nullptr},
1981 /* 39: CD_MLOOPTANGENT */
1982 {sizeof(float[4]),
1983 alignof(float[4]),
1984 "",
1985 0,
1986 nullptr,
1987 nullptr,
1988 nullptr,
1989 nullptr,
1990 nullptr,
1991 nullptr},
1992 /* 40: CD_TESSLOOPNORMAL */
1993 {sizeof(short[4][3]),
1994 alignof(short[4][3]),
1995 "",
1996 0,
1997 nullptr,
1998 nullptr,
1999 nullptr,
2000 nullptr,
2002 nullptr},
2003 /* 41: CD_CUSTOMLOOPNORMAL */
2004 {sizeof(short[2]),
2005 alignof(short[2]),
2006 "vec2s",
2007 1,
2008 nullptr,
2009 nullptr,
2010 nullptr,
2011 nullptr,
2012 nullptr,
2013 nullptr},
2014 /* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
2015 {sizeof(int), alignof(int), ""},
2016 /* 43: CD_LOCATION */
2017 {sizeof(float[3]),
2018 alignof(float[3]),
2019 "vec3f",
2020 1,
2021 nullptr,
2022 nullptr,
2023 nullptr,
2024 nullptr,
2025 nullptr,
2026 nullptr},
2027 /* 44: CD_RADIUS */
2028 {sizeof(float),
2029 alignof(float),
2030 "MFloatProperty",
2031 1,
2032 nullptr,
2033 nullptr,
2034 nullptr,
2035 nullptr,
2036 nullptr,
2037 nullptr},
2038 /* 45: CD_PROP_INT8 */
2039 {sizeof(int8_t),
2040 alignof(int8_t),
2041 "MInt8Property",
2042 1,
2043 N_("Int8"),
2044 nullptr,
2045 nullptr,
2046 nullptr,
2047 nullptr,
2048 nullptr},
2049 /* 46: CD_PROP_INT32_2D */
2050 {sizeof(blender::int2),
2051 alignof(blender::int2),
2052 "vec2i",
2053 1,
2054 N_("Int 2D"),
2055 nullptr,
2056 nullptr,
2057 nullptr,
2058 nullptr,
2059 nullptr},
2060 /* 47: CD_PROP_COLOR */
2061 {sizeof(MPropCol),
2062 alignof(MPropCol),
2063 "MPropCol",
2064 1,
2065 N_("Color"),
2066 nullptr,
2067 nullptr,
2069 nullptr,
2071 nullptr,
2072 nullptr,
2079 nullptr,
2080 nullptr,
2081 nullptr,
2082 nullptr},
2083 /* 48: CD_PROP_FLOAT3 */
2084 {sizeof(float[3]),
2085 alignof(blender::float3),
2086 "vec3f",
2087 1,
2088 N_("Float3"),
2089 nullptr,
2090 nullptr,
2092 nullptr,
2093 nullptr,
2094 nullptr,
2096 nullptr,
2098 nullptr,
2100 /* 49: CD_PROP_FLOAT2 */
2101 {sizeof(float[2]),
2102 alignof(float2),
2103 "vec2f",
2104 1,
2105 N_("Float2"),
2106 nullptr,
2107 nullptr,
2109 nullptr,
2110 nullptr,
2111 nullptr,
2119 /* 50: CD_PROP_BOOL */
2120 {sizeof(bool),
2121 alignof(bool),
2122 "bool",
2123 1,
2124 N_("Boolean"),
2125 nullptr,
2126 nullptr,
2128 nullptr,
2129 nullptr,
2130 nullptr,
2131 nullptr,
2132 nullptr,
2133 nullptr,
2134 nullptr},
2135 /* 51: CD_HAIRLENGTH */ /* DEPRECATED */ /* UNUSED */
2136 {sizeof(float),
2137 alignof(float),
2138 "float",
2139 1,
2140 nullptr,
2141 nullptr,
2142 nullptr,
2143 nullptr,
2144 nullptr,
2145 nullptr},
2146 /* 52: CD_PROP_QUATERNION */
2147 {sizeof(float[4]),
2148 alignof(blender::float4),
2149 "vec4f",
2150 1,
2151 N_("Quaternion"),
2152 nullptr,
2153 nullptr,
2155 nullptr,
2157};
2158
2159static_assert(sizeof(mat4x4f) == sizeof(blender::float4x4));
2160
2161static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
2162 /* 0-4 */ "CDMVert",
2163 "CDMSticky",
2164 "CDMDeformVert",
2165 "CDMEdge",
2166 "CDMFace",
2167 /* 5-9 */ "CDMTFace",
2168 "CDMCol",
2169 "CDOrigIndex",
2170 "CDNormal",
2171 "CDFaceMap",
2172 /* 10-14 */ "CDMFloatProperty",
2173 "CDMIntProperty",
2174 "CDMStringProperty",
2175 "CDOrigSpace",
2176 "CDOrco",
2177 /* 15-19 */ "CDMTexPoly",
2178 "CDMLoopUV",
2179 "CDMloopCol",
2180 "CDTangent",
2181 "CDMDisps",
2182 /* 20-24 */ "CDPreviewMCol",
2183 "CDIDMCol",
2184 "CDTextureMCol",
2185 "CDClothOrco",
2186 "CDMRecast",
2187
2188 /* BMESH ONLY */
2189 /* 25-29 */ "CDMPoly",
2190 "CDMLoop",
2191 "CDShapeKeyIndex",
2192 "CDShapeKey",
2193 "CDBevelWeight",
2194 /* 30-34 */ "CDSubSurfCrease",
2195 "CDOrigSpaceLoop",
2196 "CDPreviewLoopCol",
2197 "CDBMElemPyPtr",
2198 "CDPaintMask",
2199 /* 35-36 */ "CDGridPaintMask",
2200 "CDMVertSkin",
2201 /* 37-38 */ "CDFreestyleEdge",
2202 "CDFreestyleFace",
2203 /* 39-42 */ "CDMLoopTangent",
2204 "CDTessLoopNormal",
2205 "CDCustomLoopNormal",
2206 "CDSculptFaceGroups",
2207 /* 43-46 */ "CDHairPoint",
2208 "CDPropInt8",
2209 "CDHairMapping",
2210 "CDPoint",
2211 "CDPropCol",
2212 "CDPropFloat3",
2213 "CDPropFloat2",
2214 "CDPropBoolean",
2215 "CDHairLength",
2216 "CDPropQuaternion",
2217};
2218
2220 /*vmask*/ CD_MASK_PROP_FLOAT3,
2221 /*emask*/ CD_MASK_PROP_INT32_2D,
2222 /*fmask*/ 0,
2223 /*pmask*/ 0,
2224 /*lmask*/ CD_MASK_PROP_INT32,
2225};
2229 /*fmask*/ 0,
2230 /*pmask*/ CD_MASK_ORIGINDEX,
2231 /*lmask*/ CD_MASK_PROP_INT32,
2232};
2280
2282{
2283 if (type < 0 || type >= CD_NUMTYPES) {
2284 return nullptr;
2285 }
2286
2287 return &LAYERTYPEINFO[type];
2288}
2289
2290static const char *layerType_getName(const eCustomDataType type)
2291{
2292 if (type < 0 || type >= CD_NUMTYPES) {
2293 return nullptr;
2294 }
2295
2296 return LAYERTYPENAMES[type];
2297}
2298
2300{
2301 printf("verts mask=0x%" PRIx64 ":\n", mask->vmask);
2302 for (int i = 0; i < CD_NUMTYPES; i++) {
2303 if (mask->vmask & CD_TYPE_AS_MASK(i)) {
2305 }
2306 }
2307
2308 printf("edges mask=0x%" PRIx64 ":\n", mask->emask);
2309 for (int i = 0; i < CD_NUMTYPES; i++) {
2310 if (mask->emask & CD_TYPE_AS_MASK(i)) {
2312 }
2313 }
2314
2315 printf("faces mask=0x%" PRIx64 ":\n", mask->fmask);
2316 for (int i = 0; i < CD_NUMTYPES; i++) {
2317 if (mask->fmask & CD_TYPE_AS_MASK(i)) {
2319 }
2320 }
2321
2322 printf("loops mask=0x%" PRIx64 ":\n", mask->lmask);
2323 for (int i = 0; i < CD_NUMTYPES; i++) {
2324 if (mask->lmask & CD_TYPE_AS_MASK(i)) {
2326 }
2327 }
2328
2329 printf("polys mask=0x%" PRIx64 ":\n", mask->pmask);
2330 for (int i = 0; i < CD_NUMTYPES; i++) {
2331 if (mask->pmask & CD_TYPE_AS_MASK(i)) {
2333 }
2334 }
2335}
2336
2339/* -------------------------------------------------------------------- */
2343static void customData_update_offsets(CustomData *data);
2344
2346 CustomData *data,
2347 eCustomDataType type,
2348 std::optional<eCDAllocType> alloctype,
2349 void *layer_data_to_assign,
2350 const ImplicitSharingInfo *sharing_info_to_assign,
2351 int totelem,
2352 const StringRef name);
2353
2355{
2356 int lasttype = -1;
2357
2358 for (int i = 0; i < CD_NUMTYPES; i++) {
2359 data->typemap[i] = -1;
2360 }
2361
2362 for (int i = 0; i < data->totlayer; i++) {
2363 const eCustomDataType type = eCustomDataType(data->layers[i].type);
2364 if (type != lasttype) {
2365 data->typemap[type] = i;
2366 lasttype = type;
2367 }
2368 }
2369}
2370
2371/* currently only used in BLI_assert */
2372#ifndef NDEBUG
2374{
2375 CustomData data_copy = *data;
2376 CustomData_update_typemap(&data_copy);
2377 return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0);
2378}
2379#endif
2380
2381static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
2382{
2383 const LayerTypeInfo &type_info = *layerType_getInfo(type);
2384 const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
2385 void *new_data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, __func__);
2386 if (type_info.copy) {
2387 type_info.copy(data, new_data, totelem);
2388 }
2389 else {
2390 memcpy(new_data, data, size_in_bytes);
2391 }
2392 return new_data;
2393}
2394
2395static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
2396{
2397 const LayerTypeInfo &type_info = *layerType_getInfo(type);
2398 if (type_info.free) {
2399 type_info.free(const_cast<void *>(data), totelem);
2400 }
2401 MEM_freeN(const_cast<void *>(data));
2402}
2403
2404static bool customdata_merge_internal(const CustomData *source,
2405 CustomData *dest,
2406 const eCustomDataMask mask,
2407 const std::optional<eCDAllocType> alloctype,
2408 const int totelem)
2409{
2410 bool changed = false;
2411
2412 int last_type = -1;
2413 int last_active = 0;
2414 int last_render = 0;
2415 int last_clone = 0;
2416 int last_mask = 0;
2417 int current_type_layer_count = 0;
2418 int max_current_type_layer_count = -1;
2419
2420 for (int i = 0; i < source->totlayer; i++) {
2421 const CustomDataLayer &src_layer = source->layers[i];
2422 const eCustomDataType type = eCustomDataType(src_layer.type);
2423 const int src_layer_flag = src_layer.flag;
2424
2425 if (type != last_type) {
2426 /* Don't exceed layer count on destination. */
2427 const int layernum_dst = CustomData_number_of_layers(dest, type);
2428 current_type_layer_count = layernum_dst;
2429 max_current_type_layer_count = CustomData_layertype_layers_max(type);
2430 last_active = src_layer.active;
2431 last_render = src_layer.active_rnd;
2432 last_clone = src_layer.active_clone;
2433 last_mask = src_layer.active_mask;
2434 last_type = type;
2435 }
2436 else {
2437 current_type_layer_count++;
2438 }
2439
2440 if (src_layer_flag & CD_FLAG_NOCOPY) {
2441 /* Don't merge this layer because it's not supposed to leave the source data. */
2442 continue;
2443 }
2444 if (!(mask & CD_TYPE_AS_MASK(type))) {
2445 /* Don't merge this layer because it does not match the type mask. */
2446 continue;
2447 }
2448 if ((max_current_type_layer_count != -1) &&
2449 (current_type_layer_count >= max_current_type_layer_count))
2450 {
2451 /* Don't merge this layer because the maximum amount of layers of this type is reached. */
2452 continue;
2453 }
2454 if (CustomData_get_named_layer_index(dest, type, src_layer.name) != -1) {
2455 /* Don't merge this layer because it exists in the destination already. */
2456 continue;
2457 }
2458
2459 void *layer_data_to_assign = nullptr;
2460 const ImplicitSharingInfo *sharing_info_to_assign = nullptr;
2461 if (!alloctype.has_value()) {
2462 if (src_layer.data != nullptr) {
2463 if (src_layer.sharing_info == nullptr) {
2464 /* Can't share the layer, duplicate it instead. */
2465 layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
2466 }
2467 else {
2468 /* Share the layer. */
2469 layer_data_to_assign = src_layer.data;
2470 sharing_info_to_assign = src_layer.sharing_info;
2471 }
2472 }
2473 }
2474
2476 type,
2477 alloctype,
2478 layer_data_to_assign,
2479 sharing_info_to_assign,
2480 totelem,
2481 src_layer.name);
2482
2483 new_layer->uid = src_layer.uid;
2484 new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
2485 new_layer->active = last_active;
2486 new_layer->active_rnd = last_render;
2487 new_layer->active_clone = last_clone;
2488 new_layer->active_mask = last_mask;
2489 changed = true;
2490 }
2491
2493 return changed;
2494}
2495
2496bool CustomData_merge(const CustomData *source,
2497 CustomData *dest,
2498 eCustomDataMask mask,
2499 int totelem)
2500{
2501 return customdata_merge_internal(source, dest, mask, std::nullopt, totelem);
2502}
2503
2505 CustomData *dest,
2506 const eCustomDataMask mask,
2507 const eCDAllocType alloctype,
2508 const int totelem)
2509{
2510 return customdata_merge_internal(source, dest, mask, alloctype, totelem);
2511}
2512
2514 const eCustomDataMask mask)
2515{
2516 Vector<CustomDataLayer> dst_layers;
2517 for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) {
2518 if (BM_attribute_stored_in_bmesh_builtin(layer.name)) {
2519 continue;
2520 }
2521 if (!(mask & CD_TYPE_AS_MASK(layer.type))) {
2522 continue;
2523 }
2524 dst_layers.append(layer);
2525 }
2526
2527 CustomData dst = *src;
2528 dst.layers = static_cast<CustomDataLayer *>(
2529 MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
2530 dst.maxlayer = dst.totlayer = dst_layers.size();
2531 memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes());
2532
2534
2535 return dst;
2536}
2537
2543 private:
2544 const void *data_;
2545 int totelem_;
2546 const eCustomDataType type_;
2547
2548 public:
2549 CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
2550 : ImplicitSharingInfo(), data_(data), totelem_(totelem), type_(type)
2551 {
2552 }
2553
2554 private:
2555 void delete_self_with_data() override
2556 {
2557 if (data_ != nullptr) {
2558 free_layer_data(type_, data_, totelem_);
2559 }
2560 MEM_delete(this);
2561 }
2562
2563 void delete_data_only() override
2564 {
2565 free_layer_data(type_, data_, totelem_);
2566 data_ = nullptr;
2567 totelem_ = 0;
2568 }
2569};
2570
2573 const void *data,
2574 const int totelem)
2575{
2576 return MEM_new<CustomDataLayerImplicitSharing>(__func__, data, totelem, type);
2577}
2578
2582static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
2583{
2584 if (layer.data == nullptr) {
2585 return;
2586 }
2587 if (layer.sharing_info == nullptr) {
2588 /* Can not be shared without implicit-sharing data. */
2589 return;
2590 }
2591 if (layer.sharing_info->is_mutable()) {
2592 layer.sharing_info->tag_ensured_mutable();
2593 }
2594 else {
2595 const eCustomDataType type = eCustomDataType(layer.type);
2596 const void *old_data = layer.data;
2597 /* Copy the layer before removing the user because otherwise the data might be freed while
2598 * we're still copying from it here. */
2599 layer.data = copy_layer_data(type, old_data, totelem);
2600 layer.sharing_info->remove_user_and_delete_if_last();
2601 layer.sharing_info = make_implicit_sharing_info_for_layer(type, layer.data, totelem);
2602 }
2603}
2604
2605[[maybe_unused]] static bool layer_is_mutable(CustomDataLayer &layer)
2606{
2607 if (layer.sharing_info == nullptr) {
2608 return true;
2609 }
2610 return layer.sharing_info->is_mutable();
2611}
2612
2614{
2615 ensure_layer_data_is_mutable(*layer, totelem);
2616}
2617
2619{
2620 for (const int i : IndexRange(data->totlayer)) {
2621 ensure_layer_data_is_mutable(data->layers[i], totelem);
2622 }
2623}
2624
2626 const int old_size,
2627 const int new_size,
2628 const eCDAllocType alloctype)
2629{
2630 BLI_assert(new_size >= 0);
2631 for (int i = 0; i < data->totlayer; i++) {
2632 CustomDataLayer *layer = &data->layers[i];
2633 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
2634 const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
2635 const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
2636
2637 void *new_layer_data = MEM_mallocN_aligned(new_size_in_bytes, typeInfo->alignment, __func__);
2638 /* Copy data to new array. */
2639 if (old_size_in_bytes) {
2640 if (typeInfo->copy) {
2641 typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
2642 }
2643 else {
2644 BLI_assert(layer->data != nullptr);
2645 memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
2646 }
2647 }
2648 /* Remove ownership of old array */
2649 if (layer->sharing_info) {
2650 layer->sharing_info->remove_user_and_delete_if_last();
2651 layer->sharing_info = nullptr;
2652 }
2653 /* Take ownership of new array. */
2654 layer->data = new_layer_data;
2655 if (layer->data) {
2656 layer->sharing_info = make_implicit_sharing_info_for_layer(
2657 eCustomDataType(layer->type), layer->data, new_size);
2658 }
2659
2660 if (new_size > old_size) {
2661 const int new_elements_num = new_size - old_size;
2662 void *new_elements_begin = POINTER_OFFSET(layer->data, old_size_in_bytes);
2663 switch (alloctype) {
2664 case CD_CONSTRUCT: {
2665 /* Initialize new values for non-trivial types. */
2666 if (typeInfo->construct) {
2667 typeInfo->construct(new_elements_begin, new_elements_num);
2668 }
2669 break;
2670 }
2671 case CD_SET_DEFAULT: {
2672 if (typeInfo->set_default_value) {
2673 typeInfo->set_default_value(new_elements_begin, new_elements_num);
2674 }
2675 else {
2676 memset(new_elements_begin, 0, typeInfo->size * new_elements_num);
2677 }
2678 break;
2679 }
2680 }
2681 }
2682 }
2683}
2684
2686 CustomData *dest,
2687 eCustomDataMask mask,
2688 int totelem)
2689{
2690 CustomData_reset(dest);
2691
2692 if (source->external) {
2693 dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
2694 }
2695
2696 CustomData_merge(source, dest, mask, totelem);
2697}
2698
2700 CustomData *dest,
2701 eCustomDataMask mask,
2702 eCDAllocType alloctype,
2703 int totelem)
2704{
2705 CustomData_reset(dest);
2706
2707 if (source->external) {
2708 dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
2709 }
2710
2711 CustomData_merge_layout(source, dest, mask, alloctype, totelem);
2712}
2713
2714static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
2715{
2716 const eCustomDataType type = eCustomDataType(layer->type);
2717 if (layer->sharing_info == nullptr) {
2718 if (layer->data) {
2719 free_layer_data(type, layer->data, totelem);
2720 }
2721 }
2722 else {
2723 layer->sharing_info->remove_user_and_delete_if_last();
2724 layer->sharing_info = nullptr;
2725 }
2726}
2727
2729{
2730 if (data->external) {
2731 MEM_freeN(data->external);
2732 data->external = nullptr;
2733 }
2734}
2735
2737{
2738 memset(data, 0, sizeof(*data));
2739 copy_vn_i(data->typemap, CD_NUMTYPES, -1);
2740}
2741
2742void CustomData_free(CustomData *data, const int totelem)
2743{
2744 for (int i = 0; i < data->totlayer; i++) {
2745 customData_free_layer__internal(&data->layers[i], totelem);
2746 }
2747
2748 if (data->layers) {
2749 MEM_freeN(data->layers);
2750 }
2751
2753 CustomData_reset(data);
2754}
2755
2756void CustomData_free_typemask(CustomData *data, const int totelem, eCustomDataMask mask)
2757{
2758 for (int i = 0; i < data->totlayer; i++) {
2759 CustomDataLayer *layer = &data->layers[i];
2760 if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
2761 continue;
2762 }
2763 customData_free_layer__internal(layer, totelem);
2764 }
2765
2766 if (data->layers) {
2767 MEM_freeN(data->layers);
2768 }
2769
2771 CustomData_reset(data);
2772}
2773
2775{
2776 const LayerTypeInfo *typeInfo;
2777 int offset = 0;
2778
2779 for (int i = 0; i < data->totlayer; i++) {
2780 typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
2781
2782 data->layers[i].offset = offset;
2783 offset += typeInfo->size;
2784 }
2785
2786 data->totsize = offset;
2788}
2789
2790/* to use when we're in the middle of modifying layers */
2792 const eCustomDataType type)
2793{
2794 for (int i = 0; i < data->totlayer; i++) {
2795 if (data->layers[i].type == type) {
2796 return i;
2797 }
2798 }
2799
2800 return -1;
2801}
2802
2803/* -------------------------------------------------------------------- */
2804/* index values to access the layers (offset from the layer start) */
2805
2807{
2809 return data->typemap[type];
2810}
2811
2812int CustomData_get_layer_index_n(const CustomData *data, const eCustomDataType type, const int n)
2813{
2814 BLI_assert(n >= 0);
2815 int i = CustomData_get_layer_index(data, type);
2816
2817 if (i != -1) {
2818 /* If the value of n goes past the block of layers of the correct type, return -1. */
2819 i = (i + n < data->totlayer && data->layers[i + n].type == type) ? (i + n) : (-1);
2820 }
2821
2822 return i;
2823}
2824
2826 const eCustomDataType type,
2827 const StringRef name)
2828{
2829 for (int i = 0; i < data->totlayer; i++) {
2830 if (data->layers[i].type == type) {
2831 if (data->layers[i].name == name) {
2832 return i;
2833 }
2834 }
2835 }
2836
2837 return -1;
2838}
2839
2841{
2842 for (int i = 0; i < data->totlayer; i++) {
2843 if (data->layers[i].name == name) {
2844 return i;
2845 }
2846 }
2847
2848 return -1;
2849}
2850
2852{
2853 const int layer_index = data->typemap[type];
2855 return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1;
2856}
2857
2859{
2860 const int layer_index = data->typemap[type];
2862 return (layer_index != -1) ? layer_index + data->layers[layer_index].active_rnd : -1;
2863}
2864
2866{
2867 const int layer_index = data->typemap[type];
2869 return (layer_index != -1) ? layer_index + data->layers[layer_index].active_clone : -1;
2870}
2871
2873{
2874 const int layer_index = data->typemap[type];
2876 return (layer_index != -1) ? layer_index + data->layers[layer_index].active_mask : -1;
2877}
2878
2879/* -------------------------------------------------------------------- */
2880/* index values per layer type */
2881
2883 const eCustomDataType type,
2884 const StringRef name)
2885{
2886 const int named_index = CustomData_get_named_layer_index(data, type, name);
2887 const int layer_index = data->typemap[type];
2889 return (named_index != -1) ? named_index - layer_index : -1;
2890}
2891
2893{
2894 const int layer_index = data->typemap[type];
2896 return (layer_index != -1) ? data->layers[layer_index].active : -1;
2897}
2898
2900{
2901 const int layer_index = data->typemap[type];
2903 return (layer_index != -1) ? data->layers[layer_index].active_rnd : -1;
2904}
2905
2907{
2908 const int layer_index = data->typemap[type];
2910 return (layer_index != -1) ? data->layers[layer_index].active_clone : -1;
2911}
2912
2914{
2915 const int layer_index = data->typemap[type];
2917 return (layer_index != -1) ? data->layers[layer_index].active_mask : -1;
2918}
2919
2921{
2922 /* Get the layer index of the active layer of this type. */
2923 const int layer_index = CustomData_get_active_layer_index(data, type);
2924 return layer_index < 0 ? nullptr : data->layers[layer_index].name;
2925}
2926
2928{
2929 const int layer_index = CustomData_get_render_layer_index(data, type);
2930 return layer_index < 0 ? nullptr : data->layers[layer_index].name;
2931}
2932
2933void CustomData_set_layer_active(CustomData *data, const eCustomDataType type, const int n)
2934{
2935#ifndef NDEBUG
2936 const int layer_num = CustomData_number_of_layers(data, type);
2937#endif
2938 for (int i = 0; i < data->totlayer; i++) {
2939 if (data->layers[i].type == type) {
2940 BLI_assert(uint(n) < uint(layer_num));
2941 data->layers[i].active = n;
2942 }
2943 }
2944}
2945
2946void CustomData_set_layer_render(CustomData *data, const eCustomDataType type, const int n)
2947{
2948#ifndef NDEBUG
2949 const int layer_num = CustomData_number_of_layers(data, type);
2950#endif
2951 for (int i = 0; i < data->totlayer; i++) {
2952 if (data->layers[i].type == type) {
2953 BLI_assert(uint(n) < uint(layer_num));
2954 data->layers[i].active_rnd = n;
2955 }
2956 }
2957}
2958
2959void CustomData_set_layer_clone(CustomData *data, const eCustomDataType type, const int n)
2960{
2961#ifndef NDEBUG
2962 const int layer_num = CustomData_number_of_layers(data, type);
2963#endif
2964 for (int i = 0; i < data->totlayer; i++) {
2965 if (data->layers[i].type == type) {
2966 BLI_assert(uint(n) < uint(layer_num));
2967 data->layers[i].active_clone = n;
2968 }
2969 }
2970}
2971
2972void CustomData_set_layer_stencil(CustomData *data, const eCustomDataType type, const int n)
2973{
2974#ifndef NDEBUG
2975 const int layer_num = CustomData_number_of_layers(data, type);
2976#endif
2977 for (int i = 0; i < data->totlayer; i++) {
2978 if (data->layers[i].type == type) {
2979 BLI_assert(uint(n) < uint(layer_num));
2980 data->layers[i].active_mask = n;
2981 }
2982 }
2983}
2984
2986{
2987#ifndef NDEBUG
2988 const int layer_num = CustomData_number_of_layers(data, type);
2989#endif
2990 const int layer_index = n - data->typemap[type];
2992
2993 for (int i = 0; i < data->totlayer; i++) {
2994 if (data->layers[i].type == type) {
2995 BLI_assert(uint(layer_index) < uint(layer_num));
2996 data->layers[i].active = layer_index;
2997 }
2998 }
2999}
3000
3002{
3003#ifndef NDEBUG
3004 const int layer_num = CustomData_number_of_layers(data, type);
3005#endif
3006 const int layer_index = n - data->typemap[type];
3008
3009 for (int i = 0; i < data->totlayer; i++) {
3010 if (data->layers[i].type == type) {
3011 BLI_assert(uint(layer_index) < uint(layer_num));
3012 data->layers[i].active_rnd = layer_index;
3013 }
3014 }
3015}
3016
3018{
3019#ifndef NDEBUG
3020 const int layer_num = CustomData_number_of_layers(data, type);
3021#endif
3022 const int layer_index = n - data->typemap[type];
3024
3025 for (int i = 0; i < data->totlayer; i++) {
3026 if (data->layers[i].type == type) {
3027 BLI_assert(uint(layer_index) < uint(layer_num));
3028 data->layers[i].active_clone = layer_index;
3029 }
3030 }
3031}
3032
3034{
3035#ifndef NDEBUG
3036 const int layer_num = CustomData_number_of_layers(data, type);
3037#endif
3038 const int layer_index = n - data->typemap[type];
3040
3041 for (int i = 0; i < data->totlayer; i++) {
3042 if (data->layers[i].type == type) {
3043 BLI_assert(uint(layer_index) < uint(layer_num));
3044 data->layers[i].active_mask = layer_index;
3045 }
3046 }
3047}
3048
3050{
3051 for (int i = 0; i < data->totlayer; i++) {
3052 if (data->layers[i].type == type) {
3053 data->layers[i].flag |= flag;
3054 }
3055 }
3056}
3057
3059{
3060 const int nflag = ~flag;
3061
3062 for (int i = 0; i < data->totlayer; i++) {
3063 if (data->layers[i].type == type) {
3064 data->layers[i].flag &= nflag;
3065 }
3066 }
3067}
3068
3070{
3071 const int layer_index = CustomData_get_layer_index_n(data, type, n);
3072
3073 BLI_assert(layer_index >= 0);
3074
3075 return blender::bke::attribute_name_is_anonymous(data->layers[layer_index].name);
3076}
3077
3078static void customData_resize(CustomData *data, const int grow_amount)
3079{
3080 data->layers = static_cast<CustomDataLayer *>(
3081 MEM_reallocN(data->layers, (data->maxlayer + grow_amount) * sizeof(CustomDataLayer)));
3082 data->maxlayer += grow_amount;
3083}
3084
3086 CustomData *data,
3087 const eCustomDataType type,
3088 const std::optional<eCDAllocType> alloctype,
3089 void *layer_data_to_assign,
3090 const ImplicitSharingInfo *sharing_info_to_assign,
3091 const int totelem,
3092 StringRef name)
3093{
3094 const LayerTypeInfo &type_info = *layerType_getInfo(type);
3095 int flag = 0;
3096
3097 /* Some layer types only support a single layer. */
3098 if (!type_info.defaultname && CustomData_has_layer(data, type)) {
3099 /* This function doesn't support dealing with existing layer data for these layer types when
3100 * the layer already exists. */
3101 BLI_assert(layer_data_to_assign == nullptr);
3102 return &data->layers[CustomData_get_layer_index(data, type)];
3103 }
3104
3105 int index = data->totlayer;
3106 if (index >= data->maxlayer) {
3108 }
3109
3110 data->totlayer++;
3111
3112 /* Keep layers ordered by type. */
3113 for (; index > 0 && data->layers[index - 1].type > type; index--) {
3114 data->layers[index] = data->layers[index - 1];
3115 }
3116
3117 CustomDataLayer &new_layer = data->layers[index];
3118
3119 /* Clear remaining data on the layer. The original data on the layer has been moved to another
3120 * index. Without this, it can happen that information from the previous layer at that index
3121 * leaks into the new layer. */
3122 memset(&new_layer, 0, sizeof(CustomDataLayer));
3123
3124 const int64_t size_in_bytes = int64_t(totelem) * type_info.size;
3125 const char *alloc_name = layerType_getName(type);
3126
3127 if (alloctype.has_value()) {
3128 switch (*alloctype) {
3129 case CD_SET_DEFAULT: {
3130 if (totelem > 0) {
3131 new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
3132 if (type_info.set_default_value) {
3133 type_info.set_default_value(new_layer.data, totelem);
3134 }
3135 else {
3136 /* Alternatively, #MEM_calloc_arrayN is faster, but has no aligned version. */
3137 memset(new_layer.data, 0, size_in_bytes);
3138 }
3139 }
3140 break;
3141 }
3142 case CD_CONSTRUCT: {
3143 if (totelem > 0) {
3144 new_layer.data = MEM_mallocN_aligned(size_in_bytes, type_info.alignment, alloc_name);
3145 if (type_info.construct) {
3146 type_info.construct(new_layer.data, totelem);
3147 }
3148 }
3149 break;
3150 }
3151 }
3152 }
3153 else {
3154 if (totelem == 0 && sharing_info_to_assign == nullptr) {
3155 MEM_SAFE_FREE(layer_data_to_assign);
3156 }
3157 else {
3158 new_layer.data = layer_data_to_assign;
3159 new_layer.sharing_info = sharing_info_to_assign;
3160 if (new_layer.sharing_info) {
3161 new_layer.sharing_info->add_user();
3162 }
3163 }
3164 }
3165
3166 if (new_layer.data != nullptr && new_layer.sharing_info == nullptr) {
3167 /* Make layer data shareable. */
3168 new_layer.sharing_info = make_implicit_sharing_info_for_layer(type, new_layer.data, totelem);
3169 }
3170
3171 new_layer.type = type;
3172 new_layer.flag = flag;
3173
3174 /* Set default name if none exists. Note we only call DATA_() once
3175 * we know there is a default name, to avoid overhead of locale lookups
3176 * in the depsgraph. */
3177 if (name.is_empty() && type_info.defaultname) {
3178 name = DATA_(type_info.defaultname);
3179 }
3180
3181 if (!name.is_empty()) {
3182 name.copy(new_layer.name);
3184 }
3185 else {
3186 new_layer.name[0] = '\0';
3187 }
3188
3189 if (index > 0 && data->layers[index - 1].type == type) {
3190 new_layer.active = data->layers[index - 1].active;
3191 new_layer.active_rnd = data->layers[index - 1].active_rnd;
3192 new_layer.active_clone = data->layers[index - 1].active_clone;
3193 new_layer.active_mask = data->layers[index - 1].active_mask;
3194 }
3195 else {
3196 new_layer.active = 0;
3197 new_layer.active_rnd = 0;
3198 new_layer.active_clone = 0;
3199 new_layer.active_mask = 0;
3200 }
3201
3203
3204 return &data->layers[index];
3205}
3206
3208 const eCustomDataType type,
3209 eCDAllocType alloctype,
3210 const int totelem)
3211{
3212 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3213
3215 data, type, alloctype, nullptr, nullptr, totelem, typeInfo->defaultname);
3217
3218 if (layer) {
3219 return layer->data;
3220 }
3221
3222 return nullptr;
3223}
3224
3226 const eCustomDataType type,
3227 void *layer_data,
3228 const int totelem,
3229 const ImplicitSharingInfo *sharing_info)
3230{
3231 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3232
3234 data, type, std::nullopt, layer_data, sharing_info, totelem, typeInfo->defaultname);
3236
3237 if (layer) {
3238 return layer->data;
3239 }
3240
3241 return nullptr;
3242}
3243
3245 const eCustomDataType type,
3246 const eCDAllocType alloctype,
3247 const int totelem,
3248 const StringRef name)
3249{
3251 data, type, alloctype, nullptr, nullptr, totelem, name);
3253
3254 if (layer) {
3255 return layer->data;
3256 }
3257 return nullptr;
3258}
3259
3261 eCustomDataType type,
3262 void *layer_data,
3263 int totelem,
3264 const StringRef name,
3265 const ImplicitSharingInfo *sharing_info)
3266{
3268 data, type, std::nullopt, layer_data, sharing_info, totelem, name);
3270
3271 if (layer) {
3272 return layer->data;
3273 }
3274 return nullptr;
3275}
3276
3278 const eCustomDataType type,
3279 const int totelem,
3280 const int index)
3281{
3282 const int index_first = CustomData_get_layer_index(data, type);
3283 const int n = index - index_first;
3284
3285 BLI_assert(index >= index_first);
3286 if ((index_first == -1) || (n < 0)) {
3287 return false;
3288 }
3289 BLI_assert(data->layers[index].type == type);
3290
3291 customData_free_layer__internal(&data->layers[index], totelem);
3292
3293 for (int i = index + 1; i < data->totlayer; i++) {
3294 data->layers[i - 1] = data->layers[i];
3295 }
3296
3297 data->totlayer--;
3298
3299 /* if layer was last of type in array, set new active layer */
3300 int i = CustomData_get_layer_index__notypemap(data, type);
3301
3302 if (i != -1) {
3303 /* don't decrement zero index */
3304 const int index_nonzero = n ? n : 1;
3305 CustomDataLayer *layer;
3306
3307 for (layer = &data->layers[i]; i < data->totlayer && layer->type == type; i++, layer++) {
3308 if (layer->active >= index_nonzero) {
3309 layer->active--;
3310 }
3311 if (layer->active_rnd >= index_nonzero) {
3312 layer->active_rnd--;
3313 }
3314 if (layer->active_clone >= index_nonzero) {
3315 layer->active_clone--;
3316 }
3317 if (layer->active_mask >= index_nonzero) {
3318 layer->active_mask--;
3319 }
3320 }
3321 }
3322
3323 if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
3325 }
3326
3328
3329 return true;
3330}
3331
3332bool CustomData_free_layer_named(CustomData *data, const StringRef name, const int totelem)
3333{
3334 for (const int i : IndexRange(data->totlayer)) {
3335 const CustomDataLayer &layer = data->layers[i];
3336 if (StringRef(layer.name) == name) {
3337 CustomData_free_layer(data, eCustomDataType(layer.type), totelem, i);
3338 return true;
3339 }
3340 }
3341 return false;
3342}
3343
3344bool CustomData_free_layer_active(CustomData *data, const eCustomDataType type, const int totelem)
3345{
3346 const int index = CustomData_get_active_layer_index(data, type);
3347 if (index == -1) {
3348 return false;
3349 }
3350 return CustomData_free_layer(data, type, totelem, index);
3351}
3352
3353void CustomData_free_layers(CustomData *data, const eCustomDataType type, const int totelem)
3354{
3355 const int index = CustomData_get_layer_index(data, type);
3356 while (CustomData_free_layer(data, type, totelem, index)) {
3357 /* pass */
3358 }
3359}
3360
3362 const eCustomDataType type,
3363 const StringRef name)
3364{
3365 return CustomData_get_named_layer_index(data, type, name) != -1;
3366}
3367
3369{
3370 return (CustomData_get_layer_index(data, type) != -1);
3371}
3372
3374{
3375 int number = 0;
3376
3377 for (int i = 0; i < data->totlayer; i++) {
3378 if (data->layers[i].type == type) {
3379 number++;
3380 }
3381 }
3382
3383 return number;
3384}
3385
3387{
3388 int number = 0;
3389
3390 for (int i = 0; i < data->totlayer; i++) {
3391 if (data->layers[i].type == type &&
3392 blender::bke::attribute_name_is_anonymous(data->layers[i].name))
3393 {
3394 number++;
3395 }
3396 }
3397
3398 return number;
3399}
3400
3401int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDataMask mask)
3402{
3403 int number = 0;
3404
3405 for (int i = 0; i < data->totlayer; i++) {
3406 if (mask & CD_TYPE_AS_MASK(data->layers[i].type)) {
3407 number++;
3408 }
3409 }
3410
3411 return number;
3412}
3413
3414void CustomData_set_only_copy(const CustomData *data, const eCustomDataMask mask)
3415{
3416 for (int i = 0; i < data->totlayer; i++) {
3417 if (!(mask & CD_TYPE_AS_MASK(data->layers[i].type))) {
3418 data->layers[i].flag |= CD_FLAG_NOCOPY;
3419 }
3420 }
3421}
3422
3424 void *src_data_ofs,
3425 void *dst_data_ofs,
3426 const int count)
3427{
3428 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3429
3430 if (typeInfo->copy) {
3431 typeInfo->copy(src_data_ofs, dst_data_ofs, count);
3432 }
3433 else {
3434 memcpy(dst_data_ofs, src_data_ofs, size_t(count) * typeInfo->size);
3435 }
3436}
3437
3439 CustomData *dest,
3440 const int src_layer_index,
3441 const int dst_layer_index,
3442 const int src_index,
3443 const int dst_index,
3444 const int count)
3445{
3446 const LayerTypeInfo *typeInfo;
3447
3448 BLI_assert(layer_is_mutable(dest->layers[dst_layer_index]));
3449
3450 const void *src_data = source->layers[src_layer_index].data;
3451 void *dst_data = dest->layers[dst_layer_index].data;
3452
3453 typeInfo = layerType_getInfo(eCustomDataType(source->layers[src_layer_index].type));
3454
3455 const size_t src_offset = size_t(src_index) * typeInfo->size;
3456 const size_t dst_offset = size_t(dst_index) * typeInfo->size;
3457
3458 if (!count || !src_data || !dst_data) {
3459 if (count && !(src_data == nullptr && dst_data == nullptr)) {
3460 CLOG_WARN(&LOG,
3461 "null data for %s type (%p --> %p), skipping",
3462 layerType_getName(eCustomDataType(source->layers[src_layer_index].type)),
3463 (void *)src_data,
3464 (void *)dst_data);
3465 }
3466 return;
3467 }
3468
3469 if (typeInfo->copy) {
3470 typeInfo->copy(
3471 POINTER_OFFSET(src_data, src_offset), POINTER_OFFSET(dst_data, dst_offset), count);
3472 }
3473 else {
3474 memcpy(POINTER_OFFSET(dst_data, dst_offset),
3475 POINTER_OFFSET(src_data, src_offset),
3476 size_t(count) * typeInfo->size);
3477 }
3478}
3479
3481 CustomData *dest,
3482 const int source_index,
3483 const int dest_index,
3484 const int count)
3485{
3486 /* copies a layer at a time */
3487 for (int src_i = 0; src_i < source->totlayer; src_i++) {
3488
3490 dest, eCustomDataType(source->layers[src_i].type), source->layers[src_i].name);
3491
3492 /* if we found a matching layer, copy the data */
3493 if (dest_i != -1) {
3494 CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
3495 }
3496 }
3497}
3498
3500 CustomData *dest,
3501 const int source_index,
3502 const int dest_index,
3503 const int count)
3504{
3505 /* copies a layer at a time */
3506 int dest_i = 0;
3507 for (int src_i = 0; src_i < source->totlayer; src_i++) {
3508
3509 /* find the first dest layer with type >= the source type
3510 * (this should work because layers are ordered by type)
3511 */
3512 while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
3513 dest_i++;
3514 }
3515
3516 /* if there are no more dest layers, we're done */
3517 if (dest_i >= dest->totlayer) {
3518 return;
3519 }
3520
3521 /* if we found a matching layer, copy the data */
3522 if (dest->layers[dest_i].type == source->layers[src_i].type) {
3523 CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
3524
3525 /* if there are multiple source & dest layers of the same type,
3526 * we don't want to copy all source layers to the same dest, so
3527 * increment dest_i
3528 */
3529 dest_i++;
3530 }
3531 }
3532}
3533
3535 CustomData *destination,
3536 const eCustomDataType type,
3537 int source_index,
3538 int destination_index,
3539 int count)
3540{
3541 const int source_layer_index = CustomData_get_layer_index(source, type);
3542 if (source_layer_index == -1) {
3543 return;
3544 }
3545 const int destinaiton_layer_index = CustomData_get_layer_index(destination, type);
3546 if (destinaiton_layer_index == -1) {
3547 return;
3548 }
3550 destination,
3551 source_layer_index,
3552 destinaiton_layer_index,
3553 source_index,
3554 destination_index,
3555 count);
3556}
3557
3558void CustomData_free_elem(CustomData *data, const int index, const int count)
3559{
3560 for (int i = 0; i < data->totlayer; i++) {
3561 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
3562
3563 if (typeInfo->free) {
3564 size_t offset = size_t(index) * typeInfo->size;
3565 BLI_assert(layer_is_mutable(data->layers[i]));
3566
3567 typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count);
3568 }
3569 }
3570}
3571
3572#define SOURCE_BUF_SIZE 100
3573
3575 CustomData *dest,
3576 const int *src_indices,
3577 const float *weights,
3578 const float *sub_weights,
3579 int count,
3580 int dest_index)
3581{
3582 if (count <= 0) {
3583 return;
3584 }
3585
3586 const void *source_buf[SOURCE_BUF_SIZE];
3587 const void **sources = source_buf;
3588
3589 /* Slow fallback in case we're interpolating a ridiculous number of elements. */
3590 if (count > SOURCE_BUF_SIZE) {
3591 sources = static_cast<const void **>(MEM_malloc_arrayN(count, sizeof(*sources), __func__));
3592 }
3593
3594 /* If no weights are given, generate default ones to produce an average result. */
3595 float default_weights_buf[SOURCE_BUF_SIZE];
3596 float *default_weights = nullptr;
3597 if (weights == nullptr) {
3598 default_weights = (count > SOURCE_BUF_SIZE) ?
3599 static_cast<float *>(
3600 MEM_mallocN(sizeof(*weights) * size_t(count), __func__)) :
3601 default_weights_buf;
3602 copy_vn_fl(default_weights, count, 1.0f / count);
3603 weights = default_weights;
3604 }
3605
3606 /* interpolates a layer at a time */
3607 int dest_i = 0;
3608 for (int src_i = 0; src_i < source->totlayer; src_i++) {
3609 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(source->layers[src_i].type));
3610 if (!typeInfo->interp) {
3611 continue;
3612 }
3613
3614 /* find the first dest layer with type >= the source type
3615 * (this should work because layers are ordered by type)
3616 */
3617 while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
3618 dest_i++;
3619 }
3620
3621 /* if there are no more dest layers, we're done */
3622 if (dest_i >= dest->totlayer) {
3623 break;
3624 }
3625
3626 /* if we found a matching layer, copy the data */
3627 if (dest->layers[dest_i].type == source->layers[src_i].type) {
3628 void *src_data = source->layers[src_i].data;
3629
3630 for (int j = 0; j < count; j++) {
3631 sources[j] = POINTER_OFFSET(src_data, size_t(src_indices[j]) * typeInfo->size);
3632 }
3633
3634 typeInfo->interp(
3635 sources,
3636 weights,
3637 sub_weights,
3638 count,
3639 POINTER_OFFSET(dest->layers[dest_i].data, size_t(dest_index) * typeInfo->size));
3640
3641 /* if there are multiple source & dest layers of the same type,
3642 * we don't want to copy all source layers to the same dest, so
3643 * increment dest_i
3644 */
3645 dest_i++;
3646 }
3647 }
3648
3649 if (count > SOURCE_BUF_SIZE) {
3650 MEM_freeN((void *)sources);
3651 }
3652 if (!ELEM(default_weights, nullptr, default_weights_buf)) {
3653 MEM_freeN(default_weights);
3654 }
3655}
3656
3657void CustomData_swap_corners(CustomData *data, const int index, const int *corner_indices)
3658{
3659 for (int i = 0; i < data->totlayer; i++) {
3660 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
3661
3662 if (typeInfo->swap) {
3663 const size_t offset = size_t(index) * typeInfo->size;
3664
3665 typeInfo->swap(POINTER_OFFSET(data->layers[i].data, offset), corner_indices);
3666 }
3667 }
3668}
3669
3671 const int index,
3672 const eCustomDataType type,
3673 int totelem)
3674{
3675 BLI_assert(index >= 0);
3676 void *layer_data = CustomData_get_layer_for_write(data, type, totelem);
3677 if (!layer_data) {
3678 return nullptr;
3679 }
3680 return POINTER_OFFSET(layer_data, size_t(index) * layerType_getInfo(type)->size);
3681}
3682
3684 CustomData *data, const eCustomDataType type, const int index, const int n, int totelem)
3685{
3686 BLI_assert(index >= 0);
3687 void *layer_data = CustomData_get_layer_n_for_write(data, type, n, totelem);
3688 if (!layer_data) {
3689 return nullptr;
3690 }
3691
3692 return POINTER_OFFSET(layer_data, size_t(index) * layerType_getInfo(type)->size);
3693}
3694
3695const void *CustomData_get_layer(const CustomData *data, const eCustomDataType type)
3696{
3697 int layer_index = CustomData_get_active_layer_index(data, type);
3698 if (layer_index == -1) {
3699 return nullptr;
3700 }
3701
3702 return data->layers[layer_index].data;
3703}
3704
3706 const eCustomDataType type,
3707 const int totelem)
3708{
3709 const int layer_index = CustomData_get_active_layer_index(data, type);
3710 if (layer_index == -1) {
3711 return nullptr;
3712 }
3713 CustomDataLayer &layer = data->layers[layer_index];
3714 ensure_layer_data_is_mutable(layer, totelem);
3715 return layer.data;
3716}
3717
3718const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType type, const int n)
3719{
3720 int layer_index = CustomData_get_layer_index_n(data, type, n);
3721 if (layer_index == -1) {
3722 return nullptr;
3723 }
3724 return data->layers[layer_index].data;
3725}
3726
3728 const eCustomDataType type,
3729 const int n,
3730 const int totelem)
3731{
3732 const int layer_index = CustomData_get_layer_index_n(data, type, n);
3733 if (layer_index == -1) {
3734 return nullptr;
3735 }
3736 CustomDataLayer &layer = data->layers[layer_index];
3737 ensure_layer_data_is_mutable(layer, totelem);
3738 return layer.data;
3739}
3740
3742 const eCustomDataType type,
3743 const StringRef name)
3744{
3745 int layer_index = CustomData_get_named_layer_index(data, type, name);
3746 if (layer_index == -1) {
3747 return nullptr;
3748 }
3749 return data->layers[layer_index].data;
3750}
3751
3753 const eCustomDataType type,
3754 const StringRef name,
3755 const int totelem)
3756{
3757 const int layer_index = CustomData_get_named_layer_index(data, type, name);
3758 if (layer_index == -1) {
3759 return nullptr;
3760 }
3761 CustomDataLayer &layer = data->layers[layer_index];
3762 ensure_layer_data_is_mutable(layer, totelem);
3763 return layer.data;
3764}
3765
3767{
3768 int layer_index = CustomData_get_active_layer_index(data, type);
3769 if (layer_index == -1) {
3770 return -1;
3771 }
3772 return data->layers[layer_index].offset;
3773}
3774
3775int CustomData_get_n_offset(const CustomData *data, const eCustomDataType type, const int n)
3776{
3777 int layer_index = CustomData_get_layer_index_n(data, type, n);
3778 if (layer_index == -1) {
3779 return -1;
3780 }
3781
3782 return data->layers[layer_index].offset;
3783}
3784
3786 const eCustomDataType type,
3787 const StringRef name)
3788{
3789 int layer_index = CustomData_get_named_layer_index(data, type, name);
3790 if (layer_index == -1) {
3791 return -1;
3792 }
3793
3794 return data->layers[layer_index].offset;
3795}
3796
3798 const eCustomDataType type,
3799 const int n,
3800 const StringRef name)
3801{
3802 const int layer_index = CustomData_get_layer_index_n(data, type, n);
3803 if (layer_index == -1) {
3804 return false;
3805 }
3806
3807 name.copy(data->layers[layer_index].name);
3808
3809 return true;
3810}
3811
3813 const eCustomDataType type,
3814 const int n)
3815{
3816 const int layer_index = CustomData_get_layer_index_n(data, type, n);
3817
3818 return (layer_index == -1) ? nullptr : data->layers[layer_index].name;
3819}
3820
3821/* BMesh functions */
3822
3823void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype)
3824{
3825 int chunksize;
3826
3827 /* Dispose old pools before calling here to avoid leaks */
3828 BLI_assert(data->pool == nullptr);
3829
3830 switch (htype) {
3831 case BM_VERT:
3833 break;
3834 case BM_EDGE:
3836 break;
3837 case BM_LOOP:
3839 break;
3840 case BM_FACE:
3842 break;
3843 default:
3845 chunksize = 512;
3846 break;
3847 }
3848
3849 /* If there are no layers, no pool is needed just yet */
3850 if (data->totlayer) {
3851 data->pool = BLI_mempool_create(data->totsize, totelem, chunksize, BLI_MEMPOOL_NOP);
3852 }
3853}
3854
3856 CustomData *dest,
3857 eCustomDataMask mask,
3858 eCDAllocType alloctype,
3859 BMesh *bm,
3860 const char htype)
3861{
3862
3863 if (CustomData_number_of_layers_typemask(source, mask) == 0) {
3864 return false;
3865 }
3866
3867 /* copy old layer description so that old data can be copied into
3868 * the new allocation */
3869 CustomData destold = *dest;
3870 if (destold.layers) {
3871 destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
3872 }
3873
3874 if (CustomData_merge_layout(source, dest, mask, alloctype, 0) == false) {
3875 if (destold.layers) {
3876 MEM_freeN(destold.layers);
3877 }
3878 return false;
3879 }
3880
3881 const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(destold, *dest);
3882
3883 int iter_type;
3884 int totelem;
3885 switch (htype) {
3886 case BM_VERT:
3887 iter_type = BM_VERTS_OF_MESH;
3888 totelem = bm->totvert;
3889 break;
3890 case BM_EDGE:
3891 iter_type = BM_EDGES_OF_MESH;
3892 totelem = bm->totedge;
3893 break;
3894 case BM_LOOP:
3895 iter_type = BM_LOOPS_OF_FACE;
3896 totelem = bm->totloop;
3897 break;
3898 case BM_FACE:
3899 iter_type = BM_FACES_OF_MESH;
3900 totelem = bm->totface;
3901 break;
3902 default: /* should never happen */
3903 BLI_assert_msg(0, "invalid type given");
3904 iter_type = BM_VERTS_OF_MESH;
3905 totelem = bm->totvert;
3906 break;
3907 }
3908
3909 dest->pool = nullptr;
3910 CustomData_bmesh_init_pool(dest, totelem, htype);
3911
3912 if (iter_type != BM_LOOPS_OF_FACE) {
3913 BMHeader *h;
3914 BMIter iter;
3915 /* Ensure all current elements follow new customdata layout. */
3916 BM_ITER_MESH (h, &iter, bm, iter_type) {
3917 void *tmp = nullptr;
3918 CustomData_bmesh_copy_block(*dest, map, h->data, &tmp);
3919 CustomData_bmesh_free_block(&destold, &h->data);
3920 h->data = tmp;
3921 }
3922 }
3923 else {
3924 BMFace *f;
3925 BMLoop *l;
3926 BMIter iter;
3927 BMIter liter;
3928
3929 /* Ensure all current elements follow new customdata layout. */
3930 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3931 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
3932 void *tmp = nullptr;
3933 CustomData_bmesh_copy_block(*dest, map, l->head.data, &tmp);
3935 l->head.data = tmp;
3936 }
3937 }
3938 }
3939
3940 if (destold.pool) {
3941 BLI_mempool_destroy(destold.pool);
3942 }
3943 if (destold.layers) {
3944 MEM_freeN(destold.layers);
3945 }
3946 return true;
3947}
3948
3950{
3951 if (*block == nullptr) {
3952 return;
3953 }
3954
3955 for (int i = 0; i < data->totlayer; i++) {
3956 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
3957
3958 if (typeInfo->free) {
3959 int offset = data->layers[i].offset;
3960 typeInfo->free(POINTER_OFFSET(*block, offset), 1);
3961 }
3962 }
3963
3964 if (data->totsize) {
3965 BLI_mempool_free(data->pool, *block);
3966 }
3967
3968 *block = nullptr;
3969}
3970
3972{
3973 if (block == nullptr) {
3974 return;
3975 }
3976 for (int i = 0; i < data->totlayer; i++) {
3977 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
3978 if (typeInfo->free) {
3979 const size_t offset = data->layers[i].offset;
3980 typeInfo->free(POINTER_OFFSET(block, offset), 1);
3981 }
3982 }
3983 if (data->totsize) {
3984 memset(block, 0, data->totsize);
3985 }
3986}
3987
3989{
3990 if (*block) {
3991 CustomData_bmesh_free_block(data, block);
3992 }
3993
3994 if (data->totsize > 0) {
3995 *block = BLI_mempool_alloc(data->pool);
3996 }
3997 else {
3998 *block = nullptr;
3999 }
4000}
4001
4003 void *block,
4004 const eCustomDataMask mask_exclude)
4005{
4006 if (block == nullptr) {
4007 return;
4008 }
4009 for (int i = 0; i < data->totlayer; i++) {
4010 if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
4011 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
4012 const size_t offset = data->layers[i].offset;
4013 if (typeInfo->free) {
4014 typeInfo->free(POINTER_OFFSET(block, offset), 1);
4015 }
4016 memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
4017 }
4018 }
4019}
4020
4022{
4023 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4024 if (typeInfo->set_default_value) {
4025 typeInfo->set_default_value(elem, 1);
4026 }
4027 else {
4028 memset(elem, 0, typeInfo->size);
4029 }
4030}
4031
4032static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n)
4033{
4034 const int offset = data->layers[n].offset;
4036 POINTER_OFFSET(*block, offset));
4037}
4038
4040{
4041 if (*block == nullptr) {
4042 CustomData_bmesh_alloc_block(data, block);
4043 }
4044
4045 for (int i = 0; i < data->totlayer; i++) {
4046 CustomData_bmesh_set_default_n(data, block, i);
4047 }
4048}
4049
4051 const CustomData &dst,
4052 const eCustomDataMask mask_exclude)
4053{
4055 for (const CustomDataLayer &layer_dst : Span(dst.layers, dst.totlayer)) {
4056 const int dst_offset = layer_dst.offset;
4057 const eCustomDataType dst_type = eCustomDataType(layer_dst.type);
4058 const LayerTypeInfo &type_info = *layerType_getInfo(dst_type);
4059
4060 const int src_offset = CustomData_get_offset_named(&src, dst_type, layer_dst.name);
4061 if (src_offset == -1 || CD_TYPE_AS_MASK(dst_type) & mask_exclude) {
4062 if (type_info.set_default_value) {
4063 map.defaults.append({type_info.set_default_value, dst_offset});
4064 }
4065 else {
4066 map.trivial_defaults.append({type_info.size, dst_offset});
4067 }
4068 }
4069 else {
4070 if (type_info.copy) {
4071 map.copies.append({type_info.copy, src_offset, dst_offset});
4072 }
4073 else {
4074 /* NOTE: A way to improve performance of copies (by reducing the number of `memcpy`
4075 * calls) would be combining contiguous in the source and result format. */
4076 map.trivial_copies.append({type_info.size, src_offset, dst_offset});
4077 }
4078 }
4079
4080 if (type_info.free) {
4081 map.free.append({type_info.free, dst_offset});
4082 }
4083 }
4084 return map;
4085}
4086
4088 const BMCustomDataCopyMap &copy_map,
4089 const void *src_block,
4090 void **dst_block)
4091{
4092 if (*dst_block) {
4093 for (const BMCustomDataCopyMap::Free &info : copy_map.free) {
4094 info.fn(POINTER_OFFSET(*dst_block, info.dst_offset), 1);
4095 }
4096 }
4097 else {
4098 if (dst_data.totsize == 0) {
4099 return;
4100 }
4101 *dst_block = BLI_mempool_alloc(dst_data.pool);
4102 }
4103
4104 for (const BMCustomDataCopyMap::TrivialCopy &info : copy_map.trivial_copies) {
4105 memcpy(POINTER_OFFSET(*dst_block, info.dst_offset),
4106 POINTER_OFFSET(src_block, info.src_offset),
4107 info.size);
4108 }
4109 for (const BMCustomDataCopyMap::Copy &info : copy_map.copies) {
4110 info.fn(POINTER_OFFSET(src_block, info.src_offset),
4111 POINTER_OFFSET(*dst_block, info.dst_offset),
4112 1);
4113 }
4114 for (const BMCustomDataCopyMap::TrivialDefault &info : copy_map.trivial_defaults) {
4115 memset(POINTER_OFFSET(*dst_block, info.dst_offset), 0, info.size);
4116 }
4117 for (const BMCustomDataCopyMap::Default &info : copy_map.defaults) {
4118 info.fn(POINTER_OFFSET(*dst_block, info.dst_offset), 1);
4119 }
4120}
4121
4122void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
4123{
4124 if (*dst_block) {
4125 for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
4126 const LayerTypeInfo &info = *layerType_getInfo(eCustomDataType(layer.type));
4127 if (info.free) {
4128 info.free(POINTER_OFFSET(*dst_block, layer.offset), 1);
4129 }
4130 }
4131 }
4132 else {
4133 if (data.totsize == 0) {
4134 return;
4135 }
4136 *dst_block = BLI_mempool_alloc(data.pool);
4137 }
4138
4139 for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
4140 const int offset = layer.offset;
4141 const LayerTypeInfo &info = *layerType_getInfo(eCustomDataType(layer.type));
4142 if (info.copy) {
4143 info.copy(POINTER_OFFSET(src_block, offset), POINTER_OFFSET(*dst_block, offset), 1);
4144 }
4145 else {
4146 memcpy(POINTER_OFFSET(*dst_block, offset), POINTER_OFFSET(src_block, offset), info.size);
4147 }
4148 }
4149}
4150
4151void *CustomData_bmesh_get(const CustomData *data, void *block, const eCustomDataType type)
4152{
4153 int layer_index = CustomData_get_active_layer_index(data, type);
4154 if (layer_index == -1) {
4155 return nullptr;
4156 }
4157
4158 return POINTER_OFFSET(block, data->layers[layer_index].offset);
4159}
4160
4162 void *block,
4163 const eCustomDataType type,
4164 const int n)
4165{
4166 int layer_index = CustomData_get_layer_index(data, type);
4167 if (layer_index == -1) {
4168 return nullptr;
4169 }
4170
4171 return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
4172}
4173
4174void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, const int n)
4175{
4176 if (n < 0 || n >= data->totlayer) {
4177 return nullptr;
4178 }
4179
4180 return POINTER_OFFSET(block, data->layers[n].offset);
4181}
4182
4183bool CustomData_layer_has_math(const CustomData *data, const int layer_n)
4184{
4185 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[layer_n].type));
4186
4187 if (typeInfo->equal && typeInfo->add && typeInfo->multiply && typeInfo->initminmax &&
4188 typeInfo->dominmax)
4189 {
4190 return true;
4191 }
4192
4193 return false;
4194}
4195
4196bool CustomData_layer_has_interp(const CustomData *data, const int layer_n)
4197{
4198 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[layer_n].type));
4199
4200 if (typeInfo->interp) {
4201 return true;
4202 }
4203
4204 return false;
4205}
4206
4208{
4209 /* interpolates a layer at a time */
4210 for (int i = 0; i < data->totlayer; i++) {
4211 if (CustomData_layer_has_math(data, i)) {
4212 return true;
4213 }
4214 }
4215
4216 return false;
4217}
4218
4220{
4221 for (int i = 0; i < data->totlayer; i++) {
4222 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
4223 if (typeInfo->free) {
4224 return true;
4225 }
4226 }
4227 return false;
4228}
4229
4231{
4232 /* interpolates a layer at a time */
4233 for (int i = 0; i < data->totlayer; i++) {
4234 if (CustomData_layer_has_interp(data, i)) {
4235 return true;
4236 }
4237 }
4238
4239 return false;
4240}
4241
4242void CustomData_data_copy_value(const eCustomDataType type, const void *source, void *dest)
4243{
4244 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4245
4246 if (!dest) {
4247 return;
4248 }
4249
4250 if (typeInfo->copy) {
4251 typeInfo->copy(source, dest, 1);
4252 }
4253 else {
4254 memcpy(dest, source, typeInfo->size);
4255 }
4256}
4257
4259 const void *source,
4260 void *dest,
4261 const int mixmode,
4262 const float mixfactor)
4263{
4264 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4265
4266 if (!dest) {
4267 return;
4268 }
4269
4270 if (typeInfo->copyvalue) {
4271 typeInfo->copyvalue(source, dest, mixmode, mixfactor);
4272 }
4273 else {
4274 /* Mere copy if no advanced interpolation is supported. */
4275 memcpy(dest, source, typeInfo->size);
4276 }
4277}
4278
4279bool CustomData_data_equals(const eCustomDataType type, const void *data1, const void *data2)
4280{
4281 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4282
4283 if (typeInfo->equal) {
4284 return typeInfo->equal(data1, data2);
4285 }
4286
4287 return !memcmp(data1, data2, typeInfo->size);
4288}
4289
4290void CustomData_data_initminmax(const eCustomDataType type, void *min, void *max)
4291{
4292 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4293
4294 if (typeInfo->initminmax) {
4295 typeInfo->initminmax(min, max);
4296 }
4297}
4298
4299void CustomData_data_dominmax(const eCustomDataType type, const void *data, void *min, void *max)
4300{
4301 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4302
4303 if (typeInfo->dominmax) {
4304 typeInfo->dominmax(data, min, max);
4305 }
4306}
4307
4308void CustomData_data_multiply(const eCustomDataType type, void *data, const float fac)
4309{
4310 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4311
4312 if (typeInfo->multiply) {
4313 typeInfo->multiply(data, fac);
4314 }
4315}
4316
4317void CustomData_data_add(const eCustomDataType type, void *data1, const void *data2)
4318{
4319 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4320
4321 if (typeInfo->add) {
4322 typeInfo->add(data1, data2);
4323 }
4324}
4325
4327 CustomData *data, void *block, const eCustomDataType type, const int n, const void *source)
4328{
4329 void *dest = CustomData_bmesh_get_n(data, block, type, n);
4330 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4331
4332 if (!dest) {
4333 return;
4334 }
4335
4336 if (typeInfo->copy) {
4337 typeInfo->copy(source, dest, 1);
4338 }
4339 else {
4340 memcpy(dest, source, typeInfo->size);
4341 }
4342}
4343
4345 const void **src_blocks_ofs,
4346 const float *weights,
4347 const float *sub_weights,
4348 int count,
4349 void *dst_block_ofs,
4350 int n)
4351{
4352 BLI_assert(weights != nullptr);
4353 BLI_assert(count > 0);
4354
4355 CustomDataLayer *layer = &data->layers[n];
4356 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4357
4358 typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
4359}
4360
4362 const void **src_blocks,
4363 const float *weights,
4364 const float *sub_weights,
4365 int count,
4366 void *dst_block)
4367{
4368 if (count <= 0) {
4369 return;
4370 }
4371
4372 void *source_buf[SOURCE_BUF_SIZE];
4373 const void **sources = (const void **)source_buf;
4374
4375 /* Slow fallback in case we're interpolating a ridiculous number of elements. */
4376 if (count > SOURCE_BUF_SIZE) {
4377 sources = (const void **)MEM_malloc_arrayN(count, sizeof(*sources), __func__);
4378 }
4379
4380 /* If no weights are given, generate default ones to produce an average result. */
4381 float default_weights_buf[SOURCE_BUF_SIZE];
4382 float *default_weights = nullptr;
4383 if (weights == nullptr) {
4384 default_weights = (count > SOURCE_BUF_SIZE) ?
4385 (float *)MEM_mallocN(sizeof(*weights) * size_t(count), __func__) :
4386 default_weights_buf;
4387 copy_vn_fl(default_weights, count, 1.0f / count);
4388 weights = default_weights;
4389 }
4390
4391 /* interpolates a layer at a time */
4392 for (int i = 0; i < data->totlayer; i++) {
4393 CustomDataLayer *layer = &data->layers[i];
4394 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4395 if (typeInfo->interp) {
4396 for (int j = 0; j < count; j++) {
4397 sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
4398 }
4400 data, sources, weights, sub_weights, count, POINTER_OFFSET(dst_block, layer->offset), i);
4401 }
4402 }
4403
4404 if (count > SOURCE_BUF_SIZE) {
4405 MEM_freeN((void *)sources);
4406 }
4407 if (!ELEM(default_weights, nullptr, default_weights_buf)) {
4408 MEM_freeN(default_weights);
4409 }
4410}
4411
4413 const char **r_struct_name,
4414 int *r_struct_num)
4415{
4416 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4417
4418 *r_struct_name = typeInfo->structname;
4419 *r_struct_num = typeInfo->structnum;
4420}
4421
4423 Vector<CustomDataLayer, 16> &layers_to_write,
4424 const Set<std::string> &skip_names)
4425{
4426 for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
4427 if (layer.flag & CD_FLAG_NOCOPY) {
4428 continue;
4429 }
4431 continue;
4432 }
4433 if (skip_names.contains(layer.name)) {
4434 continue;
4435 }
4436 layers_to_write.append(layer);
4437 }
4438 data.totlayer = layers_to_write.size();
4439 data.maxlayer = data.totlayer;
4440
4441 /* NOTE: `data->layers` may be null, this happens when adding
4442 * a legacy #MPoly struct to a mesh with no other face attributes.
4443 * This leaves us with no unique ID for DNA to identify the old
4444 * data with when loading the file. */
4445 if (!data.layers && layers_to_write.size() > 0) {
4446 /* We just need an address that's unique. */
4447 data.layers = reinterpret_cast<CustomDataLayer *>(&data.layers);
4448 }
4449}
4450
4452{
4453 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4454
4455 return typeInfo->size;
4456}
4457
4459{
4460 return layerType_getName(type);
4461}
4462
4464{
4465 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4466 return typeInfo->defaultname == nullptr;
4467}
4468
4470{
4471 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4472
4473 return (typeInfo->free != nullptr);
4474}
4475
4477{
4478 const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4479
4480 /* Same test as for singleton above. */
4481 if (typeInfo->defaultname == nullptr) {
4482 return 1;
4483 }
4484 if (typeInfo->layers_max == nullptr) {
4485 return -1;
4486 }
4487
4488 return typeInfo->layers_max();
4489}
4490
4492 const StringRef name,
4493 const eCustomDataType type,
4494 const int index)
4495{
4496 /* see if there is a duplicate */
4497 for (int i = 0; i < data->totlayer; i++) {
4498 if (i != index) {
4499 CustomDataLayer *layer = &data->layers[i];
4500
4501 if (CD_TYPE_AS_MASK(type) & CD_MASK_PROP_ALL) {
4502 if ((CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) && layer->name == name) {
4503 return true;
4504 }
4505 }
4506 else {
4507 if (i != index && layer->type == type && layer->name == name) {
4508 return true;
4509 }
4510 }
4511 }
4512 }
4513
4514 return false;
4515}
4516
4522
4523static bool customdata_unique_check(void *arg, const char *name)
4524{
4525 CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg);
4526 return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
4527}
4528
4530{
4531 if (name.startswith(".")) {
4533 }
4534 for (const blender::StringRef prefix :
4536 {
4537 if (name.startswith(prefix)) {
4539 }
4540 }
4542}
4543
4545{
4546 CustomDataLayer *nlayer = &data->layers[index];
4547 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(nlayer->type));
4548
4549 CustomDataUniqueCheckData data_arg{data, eCustomDataType(nlayer->type), index};
4550
4551 if (!typeInfo->defaultname) {
4552 return;
4553 }
4554
4555 const int name_maxncpy = CustomData_name_maxncpy_calc(nlayer->name);
4556
4557 /* Set default name if none specified. Note we only call DATA_() when
4558 * needed to avoid overhead of locale lookups in the depsgraph. */
4559 if (nlayer->name[0] == '\0') {
4560 STRNCPY_UTF8(nlayer->name, DATA_(typeInfo->defaultname));
4561 }
4562
4563 const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
4564 BLI_uniquename_cb(customdata_unique_check, &data_arg, defname, '.', nlayer->name, name_maxncpy);
4565}
4566
4568 const eCustomDataType type,
4569 const StringRef name,
4570 char *outname)
4571{
4572 int index = -1;
4573
4574 /* if a layer name was given, try to find that layer */
4575 if (!name.is_empty()) {
4576 index = CustomData_get_named_layer_index(data, type, name);
4577 }
4578
4579 if (index == -1) {
4580 /* either no layer was specified, or the layer we want has been
4581 * deleted, so assign the active layer to name
4582 */
4583 index = CustomData_get_active_layer_index(data, type);
4584 BLI_strncpy_utf8(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
4585 }
4586 else {
4587 char name_c_str[MAX_CUSTOMDATA_LAYER_NAME];
4588 name.copy(name_c_str);
4589 BLI_strncpy_utf8(outname, name_c_str, MAX_CUSTOMDATA_LAYER_NAME);
4590 }
4591}
4592
4593bool CustomData_verify_versions(CustomData *data, const int index)
4594{
4595 const LayerTypeInfo *typeInfo;
4596 CustomDataLayer *layer = &data->layers[index];
4597 bool keeplayer = true;
4598
4599 if (layer->type >= CD_NUMTYPES) {
4600 keeplayer = false; /* unknown layer type from future version */
4601 }
4602 else {
4603 typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4604
4605 if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) {
4606 keeplayer = false; /* multiple layers of which we only support one */
4607 }
4608 /* This is a preemptive fix for cases that should not happen
4609 * (layers that should not be written in .blend files),
4610 * but can happen due to bugs (see e.g. #62318).
4611 * Also for forward compatibility, in future,
4612 * we may put into `.blend` file some currently un-written data types,
4613 * this should cover that case as well.
4614 * Better to be safe here, and fix issue on the fly rather than crash... */
4615 /* 0 structnum is used in writing code to tag layer types that should not be written. */
4616 else if (typeInfo->structnum == 0 &&
4617 /* XXX Not sure why those three are exception, maybe that should be fixed? */
4618 !ELEM(layer->type,
4619 CD_PAINT_MASK,
4620 CD_FACEMAP,
4621 CD_MTEXPOLY,
4622 CD_SCULPT_FACE_SETS,
4623 CD_CREASE))
4624 {
4625 keeplayer = false;
4626 CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
4627 }
4628 }
4629
4630 if (!keeplayer) {
4631 for (int i = index + 1; i < data->totlayer; i++) {
4632 data->layers[i - 1] = data->layers[i];
4633 }
4634 data->totlayer--;
4635 }
4636
4637 return keeplayer;
4638}
4639
4641{
4642 BLI_assert(layer);
4643 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4644 BLI_assert(typeInfo);
4645
4646 if (layer->data || count == 0) {
4647 return false;
4648 }
4649
4650 switch (layer->type) {
4651 /* When more instances of corrupt files are found, add them here. */
4652 case CD_PROP_BOOL: /* See #84935. */
4653 case CD_MLOOPUV: /* See #90620. */
4654 case CD_PROP_FLOAT2: /* See #90620. */
4655 layer->data = MEM_calloc_arrayN(
4656 count, typeInfo->size, layerType_getName(eCustomDataType(layer->type)));
4657 BLI_assert(layer->data);
4658 if (typeInfo->set_default_value) {
4659 typeInfo->set_default_value(layer->data, count);
4660 }
4661 return true;
4662 break;
4663
4664 case CD_MTEXPOLY:
4665 /* TODO: Investigate multiple test failures on cycles, e.g. cycles_shadow_catcher_cpu. */
4666 break;
4667
4668 default:
4669 /* Log an error so we can collect instances of bad files. */
4670 CLOG_WARN(&LOG, "CustomDataLayer->data is null for type %d.", layer->type);
4671 break;
4672 }
4673 return false;
4674}
4675
4676bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
4677{
4678 BLI_assert(layer);
4679 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4680 BLI_assert(typeInfo);
4681
4682 if (do_fixes) {
4683 CustomData_layer_ensure_data_exists(layer, totitems);
4684 }
4685
4686 BLI_assert((totitems == 0) || layer->data);
4687 BLI_assert(MEM_allocN_len(layer->data) >= totitems * typeInfo->size);
4688
4689 if (typeInfo->validate != nullptr) {
4690 return typeInfo->validate(layer->data, totitems, do_fixes);
4691 }
4692
4693 return false;
4694}
4695
4698/* -------------------------------------------------------------------- */
4702static void customdata_external_filename(char filepath[FILE_MAX],
4703 ID *id,
4704 CustomDataExternal *external)
4705{
4706 BLI_strncpy(filepath, external->filepath, FILE_MAX);
4708}
4709
4710void CustomData_external_reload(CustomData *data, ID * /*id*/, eCustomDataMask mask, int totelem)
4711{
4712 for (int i = 0; i < data->totlayer; i++) {
4713 CustomDataLayer *layer = &data->layers[i];
4714 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4715
4716 if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4717 /* pass */
4718 }
4719 else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) {
4720 if (typeInfo->free) {
4721 typeInfo->free(layer->data, totelem);
4722 }
4723 layer->flag &= ~CD_FLAG_IN_MEMORY;
4724 }
4725 }
4726}
4727
4728void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, const int totelem)
4729{
4730 CustomDataExternal *external = data->external;
4731 CustomDataLayer *layer;
4732 char filepath[FILE_MAX];
4733 int update = 0;
4734
4735 if (!external) {
4736 return;
4737 }
4738
4739 for (int i = 0; i < data->totlayer; i++) {
4740 layer = &data->layers[i];
4741 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4742
4743 if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4744 /* pass */
4745 }
4746 else if (layer->flag & CD_FLAG_IN_MEMORY) {
4747 /* pass */
4748 }
4749 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
4750 update = 1;
4751 }
4752 }
4753
4754 if (!update) {
4755 return;
4756 }
4757
4758 customdata_external_filename(filepath, id, external);
4759
4761 if (!cdf_read_open(cdf, filepath)) {
4762 cdf_free(cdf);
4763 CLOG_ERROR(&LOG,
4764 "Failed to read %s layer from %s.",
4765 layerType_getName(eCustomDataType(layer->type)),
4766 filepath);
4767 return;
4768 }
4769
4770 for (int i = 0; i < data->totlayer; i++) {
4771 layer = &data->layers[i];
4772 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4773
4774 if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4775 /* pass */
4776 }
4777 else if (layer->flag & CD_FLAG_IN_MEMORY) {
4778 /* pass */
4779 }
4780 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
4781 const CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
4782
4783 if (blay) {
4784 if (cdf_read_layer(cdf, blay)) {
4785 if (typeInfo->read(cdf, layer->data, totelem)) {
4786 /* pass */
4787 }
4788 else {
4789 break;
4790 }
4791 layer->flag |= CD_FLAG_IN_MEMORY;
4792 }
4793 else {
4794 break;
4795 }
4796 }
4797 }
4798 }
4799
4800 cdf_read_close(cdf);
4801 cdf_free(cdf);
4802}
4803
4805 CustomData *data, ID *id, eCustomDataMask mask, const int totelem, const int free)
4806{
4807 CustomDataExternal *external = data->external;
4808 int update = 0;
4809 char filepath[FILE_MAX];
4810
4811 if (!external) {
4812 return;
4813 }
4814
4815 /* test if there is anything to write */
4816 for (int i = 0; i < data->totlayer; i++) {
4817 CustomDataLayer *layer = &data->layers[i];
4818 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4819
4820 if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4821 /* pass */
4822 }
4823 else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4824 update = 1;
4825 }
4826 }
4827
4828 if (!update) {
4829 return;
4830 }
4831
4832 /* make sure data is read before we try to write */
4833 CustomData_external_read(data, id, mask, totelem);
4834 customdata_external_filename(filepath, id, external);
4835
4837
4838 for (int i = 0; i < data->totlayer; i++) {
4839 CustomDataLayer *layer = &data->layers[i];
4840 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4841
4842 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
4843 if (layer->flag & CD_FLAG_IN_MEMORY) {
4845 cdf, layer->type, layer->name, typeInfo->filesize(cdf, layer->data, totelem));
4846 }
4847 else {
4848 cdf_free(cdf);
4849 return; /* read failed for a layer! */
4850 }
4851 }
4852 }
4853
4854 if (!cdf_write_open(cdf, filepath)) {
4855 CLOG_ERROR(&LOG, "Failed to open %s for writing.", filepath);
4856 cdf_free(cdf);
4857 return;
4858 }
4859
4860 int i;
4861 for (i = 0; i < data->totlayer; i++) {
4862 CustomDataLayer *layer = &data->layers[i];
4863 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4864
4865 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4866 CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
4867
4868 if (cdf_write_layer(cdf, blay)) {
4869 if (typeInfo->write(cdf, layer->data, totelem)) {
4870 /* pass */
4871 }
4872 else {
4873 break;
4874 }
4875 }
4876 else {
4877 break;
4878 }
4879 }
4880 }
4881
4882 if (i != data->totlayer) {
4883 CLOG_ERROR(&LOG, "Failed to write data to %s.", filepath);
4884 cdf_write_close(cdf);
4885 cdf_free(cdf);
4886 return;
4887 }
4888
4889 for (i = 0; i < data->totlayer; i++) {
4890 CustomDataLayer *layer = &data->layers[i];
4891 const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
4892
4893 if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4894 if (free) {
4895 if (typeInfo->free) {
4896 typeInfo->free(layer->data, totelem);
4897 }
4898 layer->flag &= ~CD_FLAG_IN_MEMORY;
4899 }
4900 }
4901 }
4902
4903 cdf_write_close(cdf);
4904 cdf_free(cdf);
4905}
4906
4908 ID * /*id*/,
4909 const eCustomDataType type,
4910 const int /*totelem*/,
4911 const char *filepath)
4912{
4913 CustomDataExternal *external = data->external;
4914
4915 int layer_index = CustomData_get_active_layer_index(data, type);
4916 if (layer_index == -1) {
4917 return;
4918 }
4919
4920 CustomDataLayer *layer = &data->layers[layer_index];
4921
4922 if (layer->flag & CD_FLAG_EXTERNAL) {
4923 return;
4924 }
4925
4926 if (!external) {
4927 external = MEM_cnew<CustomDataExternal>(__func__);
4928 data->external = external;
4929 }
4930 STRNCPY(external->filepath, filepath);
4931
4932 layer->flag |= CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY;
4933}
4934
4936 ID *id,
4937 const eCustomDataType type,
4938 const int totelem)
4939{
4940 CustomDataExternal *external = data->external;
4941
4942 int layer_index = CustomData_get_active_layer_index(data, type);
4943 if (layer_index == -1) {
4944 return;
4945 }
4946
4947 CustomDataLayer *layer = &data->layers[layer_index];
4948
4949 if (!external) {
4950 return;
4951 }
4952
4953 if (layer->flag & CD_FLAG_EXTERNAL) {
4954 if (!(layer->flag & CD_FLAG_IN_MEMORY)) {
4955 CustomData_external_read(data, id, CD_TYPE_AS_MASK(layer->type), totelem);
4956 }
4957
4958 layer->flag &= ~CD_FLAG_EXTERNAL;
4959 }
4960}
4961
4963{
4964 int layer_index = CustomData_get_active_layer_index(data, type);
4965 if (layer_index == -1) {
4966 return false;
4967 }
4968
4969 CustomDataLayer *layer = &data->layers[layer_index];
4970 return (layer->flag & CD_FLAG_EXTERNAL) != 0;
4971}
4972
4975/* -------------------------------------------------------------------- */
4979static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
4980{
4981#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
4982 { \
4983 const _type _val = *((_type *)(_src)) & (_type)(_f); \
4984 *((_type *)(_dst)) &= ~(_type)(_f); \
4985 *((_type *)(_dst)) |= _val; \
4986 } \
4987 (void)0
4988
4989 switch (data_size) {
4990 case 1:
4991 COPY_BIT_FLAG(uint8_t, dst, src, flag);
4992 break;
4993 case 2:
4994 COPY_BIT_FLAG(uint16_t, dst, src, flag);
4995 break;
4996 case 4:
4997 COPY_BIT_FLAG(uint32_t, dst, src, flag);
4998 break;
4999 case 8:
5000 COPY_BIT_FLAG(uint64_t, dst, src, flag);
5001 break;
5002 default:
5003 // CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
5004 break;
5005 }
5006
5007#undef COPY_BIT_FLAG
5008}
5009
5010static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
5011{
5012 switch (data_size) {
5013 case 1:
5014 return ((*((uint8_t *)data) & uint8_t(flag)) != 0);
5015 case 2:
5016 return ((*((uint16_t *)data) & uint16_t(flag)) != 0);
5017 case 4:
5018 return ((*((uint32_t *)data) & uint32_t(flag)) != 0);
5019 case 8:
5020 return ((*((uint64_t *)data) & uint64_t(flag)) != 0);
5021 default:
5022 // CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
5023 return false;
5024 }
5025}
5026
5028 void *data_dst,
5029 const void **sources,
5030 const float *weights,
5031 const int count,
5032 const float mix_factor)
5033{
5034 BLI_assert(weights != nullptr);
5035 BLI_assert(count > 0);
5036
5037 /* Fake interpolation, we actually copy highest weighted source to dest.
5038 * Note we also handle bitflags here,
5039 * in which case we rather choose to transfer value of elements totaling
5040 * more than 0.5 of weight. */
5041 int best_src_idx = 0;
5042
5043 const int data_type = laymap->data_type;
5044 const int mix_mode = laymap->mix_mode;
5045
5046 size_t data_size;
5047 const uint64_t data_flag = laymap->data_flag;
5048
5049 cd_interp interp_cd = nullptr;
5050 cd_copy copy_cd = nullptr;
5051
5052 if (!sources) {
5053 /* Not supported here, abort. */
5054 return;
5055 }
5056
5057 if (int(data_type) & CD_FAKE) {
5058 data_size = laymap->data_size;
5059 }
5060 else {
5061 const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
5062
5063 data_size = size_t(type_info->size);
5064 interp_cd = type_info->interp;
5065 copy_cd = type_info->copy;
5066 }
5067
5068 void *tmp_dst = MEM_mallocN(data_size, __func__);
5069
5070 if (count > 1 && !interp_cd) {
5071 if (data_flag) {
5072 /* Boolean case, we can 'interpolate' in two groups,
5073 * and choose value from highest weighted group. */
5074 float tot_weight_true = 0.0f;
5075 int item_true_idx = -1, item_false_idx = -1;
5076
5077 for (int i = 0; i < count; i++) {
5078 if (check_bit_flag(sources[i], data_size, data_flag)) {
5079 tot_weight_true += weights[i];
5080 item_true_idx = i;
5081 }
5082 else {
5083 item_false_idx = i;
5084 }
5085 }
5086 best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
5087 }
5088 else {
5089 /* We just choose highest weighted source. */
5090 float max_weight = 0.0f;
5091
5092 for (int i = 0; i < count; i++) {
5093 if (weights[i] > max_weight) {
5094 max_weight = weights[i];
5095 best_src_idx = i;
5096 }
5097 }
5098 }
5099 }
5100
5101 BLI_assert(best_src_idx >= 0);
5102
5103 if (interp_cd) {
5104 interp_cd(sources, weights, nullptr, count, tmp_dst);
5105 }
5106 else if (data_flag) {
5107 copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
5108 }
5109 /* No interpolation, just copy highest weight source element's data. */
5110 else if (copy_cd) {
5111 copy_cd(sources[best_src_idx], tmp_dst, 1);
5112 }
5113 else {
5114 memcpy(tmp_dst, sources[best_src_idx], data_size);
5115 }
5116
5117 if (data_flag) {
5118 /* Bool flags, only copy if dest data is set (resp. unset) -
5119 * only 'advanced' modes we can support here! */
5120 if (mix_factor >= 0.5f && ((mix_mode == CDT_MIX_TRANSFER) ||
5121 (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD &&
5122 check_bit_flag(data_dst, data_size, data_flag)) ||
5123 (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD &&
5124 !check_bit_flag(data_dst, data_size, data_flag))))
5125 {
5126 copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
5127 }
5128 }
5129 else if (!(int(data_type) & CD_FAKE)) {
5130 CustomData_data_mix_value(eCustomDataType(data_type), tmp_dst, data_dst, mix_mode, mix_factor);
5131 }
5132 /* Else we can do nothing by default, needs custom interp func!
5133 * Note this is here only for sake of consistency, not expected to be used much actually? */
5134 else {
5135 if (mix_factor >= 0.5f) {
5136 memcpy(data_dst, tmp_dst, data_size);
5137 }
5138 }
5139
5140 MEM_freeN(tmp_dst);
5141}
5142
5144 void *data_dst,
5145 const void **sources,
5146 const float *weights,
5147 const int count,
5148 const float mix_factor)
5149{
5150 BLI_assert(weights != nullptr);
5151 BLI_assert(count > 0);
5152
5153 const eCustomDataType data_type = eCustomDataType(laymap->data_type);
5154 BLI_assert(data_type == CD_NORMAL);
5155 const int mix_mode = laymap->mix_mode;
5156
5157 SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
5158
5159 const LayerTypeInfo *type_info = layerType_getInfo(data_type);
5160 cd_interp interp_cd = type_info->interp;
5161
5162 float tmp_dst[3];
5163
5164 if (!sources) {
5165 /* Not supported here, abort. */
5166 return;
5167 }
5168
5169 interp_cd(sources, weights, nullptr, count, tmp_dst);
5170 if (space_transform) {
5171 /* tmp_dst is in source space so far, bring it back in destination space. */
5172 BLI_space_transform_invert_normal(space_transform, tmp_dst);
5173 }
5174
5175 CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
5176}
5177
5179 const CustomDataTransferLayerMap *laymap)
5180{
5181 MeshPairRemapItem *mapit = me_remap->items;
5182 const int totelem = me_remap->items_num;
5183
5184 const int data_type = laymap->data_type;
5185 const void *data_src = laymap->data_src;
5186 void *data_dst = laymap->data_dst;
5187
5188 size_t data_step;
5189 size_t data_size;
5190 size_t data_offset;
5191
5193
5194 size_t tmp_buff_size = 32;
5195 const void **tmp_data_src = nullptr;
5196
5197 /* NOTE: null data_src may happen and be valid (see vgroups...). */
5198 if (!data_dst) {
5199 return;
5200 }
5201
5202 if (data_src) {
5203 tmp_data_src = (const void **)MEM_malloc_arrayN(
5204 tmp_buff_size, sizeof(*tmp_data_src), __func__);
5205 }
5206
5207 if (int(data_type) & CD_FAKE) {
5208 data_step = laymap->elem_size;
5209 data_size = laymap->data_size;
5210 data_offset = laymap->data_offset;
5211 }
5212 else {
5213 const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
5214
5215 /* NOTE: we can use 'fake' CDLayers for crease :/. */
5216 data_size = size_t(type_info->size);
5217 data_step = laymap->elem_size ? laymap->elem_size : data_size;
5218 data_offset = laymap->data_offset;
5219 }
5220
5222
5223 for (int i = 0; i < totelem; i++, data_dst = POINTER_OFFSET(data_dst, data_step), mapit++) {
5224 const int sources_num = mapit->sources_num;
5225 const float mix_factor = laymap->mix_factor *
5226 (laymap->mix_weights ? laymap->mix_weights[i] : 1.0f);
5227
5228 if (!sources_num) {
5229 /* No sources for this element, skip it. */
5230 continue;
5231 }
5232
5233 if (tmp_data_src) {
5234 if (UNLIKELY(sources_num > tmp_buff_size)) {
5235 tmp_buff_size = size_t(sources_num);
5236 tmp_data_src = (const void **)MEM_reallocN((void *)tmp_data_src,
5237 sizeof(*tmp_data_src) * tmp_buff_size);
5238 }
5239
5240 for (int j = 0; j < sources_num; j++) {
5241 const size_t src_idx = size_t(mapit->indices_src[j]);
5242 tmp_data_src[j] = POINTER_OFFSET(data_src, (data_step * src_idx) + data_offset);
5243 }
5244 }
5245
5246 interp(laymap,
5247 POINTER_OFFSET(data_dst, data_offset),
5248 tmp_data_src,
5249 mapit->weights_src,
5250 sources_num,
5251 mix_factor);
5252 }
5253
5254 MEM_SAFE_FREE(tmp_data_src);
5255}
5256
5259/* -------------------------------------------------------------------- */
5263static void write_mdisps(BlendWriter *writer,
5264 const int count,
5265 const MDisps *mdlist,
5266 const int external)
5267{
5268 if (mdlist) {
5269 BLO_write_struct_array(writer, MDisps, count, mdlist);
5270 for (int i = 0; i < count; i++) {
5271 const MDisps *md = &mdlist[i];
5272 if (md->disps) {
5273 if (!external) {
5274 BLO_write_float3_array(writer, md->totdisp, &md->disps[0][0]);
5275 }
5276 }
5277
5278 if (md->hidden) {
5279 BLO_write_int8_array(writer,
5280 BLI_BITMAP_SIZE(md->totdisp) * sizeof(BLI_bitmap),
5281 reinterpret_cast<const int8_t *>(md->hidden));
5282 }
5283 }
5284 }
5285}
5286
5288 int count,
5289 const GridPaintMask *grid_paint_mask)
5290{
5291 if (grid_paint_mask) {
5292 BLO_write_struct_array(writer, GridPaintMask, count, grid_paint_mask);
5293 for (int i = 0; i < count; i++) {
5294 const GridPaintMask *gpm = &grid_paint_mask[i];
5295 if (gpm->data) {
5296 const uint32_t gridsize = uint32_t(BKE_ccg_gridsize(gpm->level));
5297 BLO_write_float_array(writer, gridsize * gridsize, gpm->data);
5298 }
5299 }
5300 }
5301}
5302
5304 const CustomDataLayer &layer,
5305 const int count)
5306{
5307 switch (layer.type) {
5308 case CD_MDEFORMVERT:
5309 BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
5310 break;
5311 case CD_MDISPS:
5313 writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
5314 break;
5315 case CD_PAINT_MASK:
5316 BLO_write_float_array(writer, count, static_cast<const float *>(layer.data));
5317 break;
5318 case CD_GRID_PAINT_MASK:
5319 write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
5320 break;
5321 case CD_PROP_BOOL:
5322 BLI_STATIC_ASSERT(sizeof(bool) == sizeof(uint8_t),
5323 "bool type is expected to have the same size as uint8_t")
5324 BLO_write_uint8_array(writer, count, static_cast<const uint8_t *>(layer.data));
5325 break;
5326 default: {
5327 const char *structname;
5328 int structnum;
5329 CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
5330 if (structnum > 0) {
5331 int datasize = structnum * count;
5332 BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
5333 }
5334 else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
5335 printf("%s error: layer '%s':%d - can't be written to file\n",
5336 __func__,
5337 structname,
5338 layer.type);
5339 }
5340 }
5341 }
5342}
5343
5345 CustomData *data,
5346 Span<CustomDataLayer> layers_to_write,
5347 int count,
5348 eCustomDataMask cddata_mask,
5349 ID *id)
5350{
5351 /* write external customdata (not for undo) */
5352 if (data->external && !BLO_write_is_undo(writer)) {
5353 CustomData_external_write(data, id, cddata_mask, count, 0);
5354 }
5355
5357 writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
5358
5359 for (const CustomDataLayer &layer : layers_to_write) {
5360 const size_t size_in_bytes = CustomData_sizeof(eCustomDataType(layer.type)) * count;
5361 BLO_write_shared(writer, layer.data, size_in_bytes, layer.sharing_info, [&]() {
5362 blend_write_layer_data(writer, layer, count);
5363 });
5364 }
5365
5366 if (data->external) {
5367 BLO_write_struct(writer, CustomDataExternal, data->external);
5368 }
5369}
5370
5372 const int count,
5373 MDisps *mdisps,
5374 const int external)
5375{
5376 if (mdisps) {
5377 for (int i = 0; i < count; i++) {
5378 MDisps &md = mdisps[i];
5379
5380 BLO_read_float3_array(reader, md.totdisp, reinterpret_cast<float **>(&md.disps));
5381 BLO_read_int8_array(reader,
5382 BLI_BITMAP_SIZE(md.totdisp) * sizeof(BLI_bitmap),
5383 reinterpret_cast<int8_t **>(&md.hidden));
5384
5385 if (md.totdisp && !md.level) {
5386 /* this calculation is only correct for loop mdisps;
5387 * if loading pre-BMesh face mdisps this will be
5388 * overwritten with the correct value in
5389 * #bm_corners_to_loops() */
5390 float gridsize = sqrtf(md.totdisp);
5391 md.level = int(logf(gridsize - 1.0f) / float(M_LN2)) + 1;
5392 }
5393
5394 if (!external && !md.disps) {
5395 md.totdisp = 0;
5396 }
5397 }
5398 }
5399}
5400
5402 int count,
5403 GridPaintMask *grid_paint_mask)
5404{
5405 if (grid_paint_mask) {
5406 for (int i = 0; i < count; i++) {
5407 GridPaintMask *gpm = &grid_paint_mask[i];
5408 if (gpm->data) {
5409 const int gridsize = BKE_ccg_gridsize(gpm->level);
5410 BLO_read_float_array(reader, gridsize * gridsize, &gpm->data);
5411 }
5412 }
5413 }
5414}
5415
5416static void blend_read_layer_data(BlendDataReader *reader, CustomDataLayer &layer, const int count)
5417{
5418 switch (layer.type) {
5419 case CD_MDEFORMVERT:
5420 BLO_read_struct_array(reader, MDeformVert, count, &layer.data);
5421 BKE_defvert_blend_read(reader, count, static_cast<MDeformVert *>(layer.data));
5422 break;
5423 case CD_MDISPS:
5424 BLO_read_struct_array(reader, MDisps, count, &layer.data);
5426 reader, count, static_cast<MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
5427 break;
5428 case CD_PAINT_MASK:
5429 BLO_read_float_array(reader, count, reinterpret_cast<float **>(&layer.data));
5430 break;
5431 case CD_GRID_PAINT_MASK:
5433 blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer.data));
5434 break;
5435 case CD_PROP_BOOL:
5436 BLI_STATIC_ASSERT(sizeof(bool) == sizeof(uint8_t),
5437 "bool type is expected to have the same size as uint8_t")
5438 BLO_read_uint8_array(reader, count, reinterpret_cast<uint8_t **>(&layer.data));
5439 break;
5440 default: {
5441 const char *structname;
5442 int structnum;
5443 CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
5444 if (structnum > 0) {
5445 const int data_num = structnum * count;
5446 layer.data = BLO_read_struct_by_name_array(reader, structname, data_num, layer.data);
5447 }
5448 else {
5449 /* Can happen with deprecated types of customdata. */
5450 const size_t elem_size = CustomData_sizeof(eCustomDataType(layer.type));
5451 BLO_read_struct_array(reader, char, elem_size *count, &layer.data);
5452 }
5453 }
5454 }
5455
5457 /* Under normal operations, this shouldn't happen, but...
5458 * For a CD_PROP_BOOL example, see #84935.
5459 * For a CD_MLOOPUV example, see #90620. */
5460 CLOG_WARN(&LOG,
5461 "Allocated custom data layer that was not saved correctly for layer.type = %d.",
5462 layer.type);
5463 }
5464}
5465
5467{
5468 BLO_read_struct_array(reader, CustomDataLayer, data->totlayer, &data->layers);
5469
5470 /* Annoying workaround for bug #31079 loading legacy files with
5471 * no polygons _but_ have stale custom-data. */
5472 if (UNLIKELY(count == 0 && data->layers == nullptr && data->totlayer != 0)) {
5473 CustomData_reset(data);
5474 return;
5475 }
5476
5477 BLO_read_struct(reader, CustomDataExternal, &data->external);
5478
5479 int i = 0;
5480 while (i < data->totlayer) {
5481 CustomDataLayer *layer = &data->layers[i];
5482
5483 if (layer->flag & CD_FLAG_EXTERNAL) {
5484 layer->flag &= ~CD_FLAG_IN_MEMORY;
5485 }
5486 layer->sharing_info = nullptr;
5487
5488 if (CustomData_verify_versions(data, i)) {
5489 layer->sharing_info = BLO_read_shared(
5490 reader, &layer->data, [&]() -> const ImplicitSharingInfo * {
5491 blend_read_layer_data(reader, *layer, count);
5492 if (layer->data == nullptr) {
5493 return nullptr;
5494 }
5496 eCustomDataType(layer->type), layer->data, count);
5497 });
5498 i++;
5499 }
5500 }
5501
5502 /* Ensure allocated size is set to the size of the read array. While this should always be the
5503 * case (see #CustomData_blend_write_prepare), there can be some corruption in rare cases (e.g.
5504 * files saved between ff3d535bc2a63092 and 945f32e66d6ada2a). */
5505 data->maxlayer = data->totlayer;
5506
5508}
5509
5512/* -------------------------------------------------------------------- */
5516#ifndef NDEBUG
5517
5518void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
5519{
5520 for (eCustomDataType type = eCustomDataType(0); type < CD_NUMTYPES;
5521 type = eCustomDataType(type + 1))
5522 {
5523 if (CustomData_has_layer(data, type)) {
5524 /* NOTE: doesn't account for multiple layers. */
5525 const char *name = CustomData_layertype_name(type);
5526 const int size = CustomData_sizeof(type);
5527 const void *pt = CustomData_get_layer(data, type);
5528 const int pt_size = pt ? int(MEM_allocN_len(pt) / size) : 0;
5529 const char *structname;
5530 int structnum;
5531 CustomData_file_write_info(type, &structname, &structnum);
5533 dynstr,
5534 "%sdict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
5535 indent,
5536 name,
5537 structname,
5538 type,
5539 (const void *)pt,
5540 size,
5541 pt_size);
5542 }
5543 }
5544}
5545
5546#endif /* !NDEBUG */
5547
5550namespace blender::bke {
5551
5552/* -------------------------------------------------------------------- */
5556std::optional<VolumeGridType> custom_data_type_to_volume_grid_type(const eCustomDataType type)
5557{
5558 switch (type) {
5559 case CD_PROP_FLOAT:
5560 return VOLUME_GRID_FLOAT;
5561 case CD_PROP_FLOAT3:
5563 case CD_PROP_INT32:
5564 return VOLUME_GRID_INT;
5565 case CD_PROP_BOOL:
5566 return VOLUME_GRID_BOOLEAN;
5567 default:
5568 return std::nullopt;
5569 }
5570}
5571
5572std::optional<eCustomDataType> volume_grid_type_to_custom_data_type(const VolumeGridType type)
5573{
5574 switch (type) {
5575 case VOLUME_GRID_FLOAT:
5576 return CD_PROP_FLOAT;
5578 return CD_PROP_FLOAT3;
5579 case VOLUME_GRID_INT:
5580 return CD_PROP_INT32;
5582 return CD_PROP_BOOL;
5583 default:
5584 return std::nullopt;
5585 }
5586}
5587
5590} // namespace blender::bke
5591
5593{
5594 return LAYERTYPEINFO[layer->type].size;
5595}
5596
5598 const int totelem,
5599 blender::MemoryCounter &memory)
5600{
5601 for (const CustomDataLayer &layer : Span{data.layers, data.totlayer}) {
5602 memory.add_shared(layer.sharing_info, [&](blender::MemoryCounter &shared_memory) {
5603 /* Not quite correct for all types, but this is only a rough approximation anyway. */
5604 const int64_t elem_size = CustomData_get_elem_size(&layer);
5605 shared_memory.add(totelem * elem_size);
5606 });
5607 }
5608}
CustomData interface, see also DNA_customdata_types.h.
void(*)( const void **sources, const float *weights, const float *sub_weights, int count, void *dest) cd_interp
@ CDT_MIX_SUB
@ CDT_MIX_REPLACE_BELOW_THRESHOLD
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
@ CDT_MIX_ADD
@ CDT_MIX_MUL
@ CDT_MIX_TRANSFER
@ CDT_MIX_MIX
@ CDT_MIX_NOMIX
void(*)(const CustomDataTransferLayerMap *laymap, void *dest, const void **sources, const float *weights, int count, float mix_factor) cd_datatransfer_interp
eCDAllocType
@ CD_SET_DEFAULT
@ CD_CONSTRUCT
#define UV_VERTSEL_NAME
void(*)(void *data, int count) cd_set_default_value
void(*)(void *data, int count) cd_free
#define ORIGINDEX_NONE
void(*)(const void *source, void *dest, int count) cd_copy
bool(*)(void *item, uint totitems, bool do_fixes) cd_validate
#define UV_PINNED_NAME
@ CD_FAKE
#define CD_TYPE_AS_MASK(_type)
#define UV_EDGESEL_NAME
CDataFile * cdf_create(int type)
bool cdf_read_layer(CDataFile *cdf, const CDataFileLayer *blay)
bool cdf_write_open(CDataFile *cdf, const char *filepath)
bool cdf_read_data(CDataFile *cdf, unsigned int size, void *data)
bool cdf_write_data(CDataFile *cdf, unsigned int size, const void *data)
#define CDF_TYPE_MESH
CDataFileLayer * cdf_layer_find(CDataFile *cdf, int type, const char *name)
void cdf_read_close(CDataFile *cdf)
CDataFileLayer * cdf_layer_add(CDataFile *cdf, int type, const char *name, size_t datasize)
void cdf_write_close(CDataFile *cdf)
void cdf_free(CDataFile *cdf)
bool cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay)
bool cdf_read_open(CDataFile *cdf, const char *filepath)
support for deformation groups and hooks.
void BKE_defvert_blend_write(BlendWriter *writer, int count, const MDeformVert *dvlist)
Definition deform.cc:1642
void BKE_defvert_blend_read(BlendDataReader *reader, int count, MDeformVert *mdverts)
Definition deform.cc:1659
int multires_mdisp_corners(const MDisps *s)
Definition multires.cc:1417
int BKE_ccg_gridsize(int level)
Definition CCGSubSurf.cc:25
VolumeGridType
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_BOOLEAN
@ VOLUME_GRID_INT
@ VOLUME_GRID_FLOAT
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_BITMAP_SIZE(_num)
Definition BLI_bitmap.h:36
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
A dynamically sized string ADT.
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_kdtree_nd_ free(KDTree *tree)
#define M_LN2
MINLINE unsigned char round_fl_to_uchar_clamp(float a)
MINLINE void blend_color_add_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_mul_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_sub_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float ft)
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3])
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void copy_vn_fl(float *array_tar, int size, float val)
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], float t)
Definition math_vector.c:99
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3_short(short r[3], const short a[3])
void minmax_v4v4_v4(float min[4], float max[4], const float vec[4])
MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void copy_vn_i(int *array_tar, int size, int val)
MINLINE void zero_v2(float r[2])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void zero_v3(float r[3])
MINLINE void copy_v4_fl(float r[4], float f)
MINLINE float normalize_v3(float n[3])
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
void BLI_mempool_free(BLI_mempool *pool, void *addr) 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_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
unsigned char uchar
unsigned int uint
#define INIT_MINMAX2(min, max)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition readfile.cc:4977
void * BLO_read_struct_by_name_array(BlendDataReader *reader, const char *struct_name, uint32_t items_num, const void *old_address)
Definition readfile.cc:4873
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr)
void BLO_read_uint8_array(BlendDataReader *reader, int array_size, uint8_t **ptr_p)
Definition readfile.cc:4935
#define BLO_write_struct_array_at_address(writer, struct_name, array_size, address, data_ptr)
void BLO_write_uint8_array(BlendWriter *writer, uint num, const uint8_t *data_ptr)
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition readfile.cc:4967
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
void BLO_write_int8_array(BlendWriter *writer, uint num, const int8_t *data_ptr)
void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, int array_size, const void *data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
void BLO_write_shared(BlendWriter *writer, const void *data, size_t approximate_size_in_bytes, const blender::ImplicitSharingInfo *sharing_info, blender::FunctionRef< void()> write_fn)
void BLO_read_int8_array(BlendDataReader *reader, int array_size, int8_t **ptr_p)
Definition readfile.cc:4941
const blender::ImplicitSharingInfo * BLO_read_shared(BlendDataReader *reader, T **data_ptr, blender::FunctionRef< const blender::ImplicitSharingInfo *()> read_fn)
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
ID and Library types, which are fundamental for SDNA.
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition DNA_ID.h:649
#define CD_MASK_BM_ELEM_PYPTR
#define MAX_CUSTOMDATA_LAYER_NAME
#define CD_MASK_NORMAL
#define CD_MASK_PROP_FLOAT3
#define CD_MASK_ORIGINDEX
#define CD_MASK_MCOL
#define CD_MASK_ORCO
#define CD_MASK_MDEFORMVERT
#define CD_MASK_TESSLOOPNORMAL
#define CD_MASK_MVERT_SKIN
#define CD_MASK_PROP_ALL
#define CD_MASK_TANGENT
#define CD_MASK_PROP_INT32_2D
#define CD_MASK_FREESTYLE_FACE
@ CD_FLAG_NOCOPY
@ CD_FLAG_IN_MEMORY
@ CD_FLAG_EXTERNAL
#define CD_MASK_SHAPE_KEYINDEX
#define CD_MASK_MTFACE
#define CD_MASK_ORIGSPACE_MLOOP
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_MDEFORMVERT
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_GRID_PAINT_MASK
#define CD_MASK_CLOTH_ORCO
#define CD_MASK_PROP_INT32
#define CD_MASK_GRID_PAINT_MASK
#define CD_MASK_CUSTOMLOOPNORMAL
#define CD_MASK_SHAPEKEY
#define CD_MASK_MFACE
#define MAX_MTFACE
#define CD_MASK_MDISPS
#define CD_MASK_FREESTYLE_EDGE
#define CD_MASK_ORIGSPACE
#define CD_MASK_MLOOPTANGENT
#define MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX
struct FreestyleEdge FreestyleEdge
struct MDisps MDisps
struct MVertSkin MVertSkin
struct MStringProperty MStringProperty
struct GridPaintMask GridPaintMask
struct MDeformVert MDeformVert
struct MTFace MTFace
struct OrigSpaceFace OrigSpaceFace
struct OrigSpaceLoop OrigSpaceLoop
struct MIntProperty MIntProperty
struct MLoopCol MLoopCol
struct MFloatProperty MFloatProperty
struct MPropCol MPropCol
struct MFace MFace
struct FreestyleFace FreestyleFace
struct mat4x4f mat4x4f
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
@ BM_LOOP
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
const BMAllocTemplate bm_mesh_chunksize_default
Definition bmesh_mesh.cc:30
bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
bool contains(const Key &key) const
Definition BLI_set.hh:291
constexpr const T * data() const
Definition BLI_span.hh:216
int64_t size() const
void append(const T &value)
Span< T > as_span() const
void add_shared(const ImplicitSharingInfo *sharing_info, const FunctionRef< void(MemoryCounter &shared_memory)> count_fn)
local_group_size(16, 16) .push_constant(Type b
#define printf
void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
static int layerMaxNum_tface()
void * CustomData_get_layer_named_for_write(CustomData *data, const eCustomDataType type, const StringRef name, const int totelem)
bool CustomData_verify_versions(CustomData *data, const int index)
static void layerFree_mdisps(void *data, const int count)
void * CustomData_get_for_write(CustomData *data, const int index, const eCustomDataType type, int totelem)
static void layerCopy_propString(const void *source, void *dest, const int count)
static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
static void layerMultiply_propfloat2(void *data, const float fac)
void CustomData_data_mix_value(const eCustomDataType type, const void *source, void *dest, const int mixmode, const float mixfactor)
const CustomData_MeshMasks CD_MASK_EVERYTHING
static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
int CustomData_get_active_layer(const CustomData *data, const eCustomDataType type)
int CustomData_get_layer_index_n(const CustomData *data, const eCustomDataType type, const int n)
void * CustomData_get_n_for_write(CustomData *data, const eCustomDataType type, const int index, const int n, int totelem)
static const LayerTypeInfo * layerType_getInfo(const eCustomDataType type)
static size_t layerFilesize_mdisps(CDataFile *, const void *data, const int count)
static void layerSwap_flnor(void *data, const int *corner_indices)
static void layerInitMinMax_propfloat2(void *vmin, void *vmax)
static void blend_write_layer_data(BlendWriter *writer, const CustomDataLayer &layer, const int count)
void CustomData_free(CustomData *data, const int totelem)
static void layerCopyValue_mloop_origspace(const void *source, void *dest, const int, const float)
void CustomData_blend_write_prepare(CustomData &data, Vector< CustomDataLayer, 16 > &layers_to_write, const Set< std::string > &skip_names)
void CustomData_set_layer_flag(CustomData *data, const eCustomDataType type, const int flag)
int CustomData_layertype_layers_max(const eCustomDataType type)
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX
static bool layerRead_mdisps(CDataFile *cdf, void *data, const int count)
void CustomData_set_layer_active_index(CustomData *data, const eCustomDataType type, const int n)
static void layerInterp_propcol(const void **sources, const float *weights, const float *, int count, void *dest)
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES]
int CustomData_get_offset_named(const CustomData *data, const eCustomDataType type, const StringRef name)
void CustomData_validate_layer_name(const CustomData *data, const eCustomDataType type, const StringRef name, char *outname)
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap, void *data_dst, const void **sources, const float *weights, const int count, const float mix_factor)
static void blend_read_mdisps(BlendDataReader *reader, const int count, MDisps *mdisps, const int external)
static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
bool CustomData_layer_is_anonymous(const CustomData *data, eCustomDataType type, int n)
static void layerConstruct_mdeformvert(void *data, const int count)
void CustomData_blend_write(BlendWriter *writer, CustomData *data, Span< CustomDataLayer > layers_to_write, int count, eCustomDataMask cddata_mask, ID *id)
void CustomData_interp(const CustomData *source, CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
static void layerCopy_propFloat(const void *source, void *dest, const int count)
static void layerMultiply_mloopcol(void *data, const float fac)
static void layerDefault_mloopcol(void *data, const int count)
int CustomData_get_stencil_layer(const CustomData *data, const eCustomDataType type)
int CustomData_get_render_layer_index(const CustomData *data, const eCustomDataType type)
const char * CustomData_layertype_name(const eCustomDataType type)
void CustomData_set_layer_stencil(CustomData *data, const eCustomDataType type, const int n)
void CustomData_bmesh_free_block(CustomData *data, void **block)
static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t count)
void CustomData_data_add(const eCustomDataType type, void *data1, const void *data2)
static void layerCopy_grid_paint_mask(const void *source, void *dest, const int count)
static void customdata_data_transfer_interp_generic(const CustomDataTransferLayerMap *laymap, void *data_dst, const void **sources, const float *weights, const int count, const float mix_factor)
void * CustomData_get_layer_for_write(CustomData *data, const eCustomDataType type, const int totelem)
bool CustomData_layertype_is_dynamic(const eCustomDataType type)
static void layerDefault_propquaternion(void *data, const int count)
void CustomData_clear_layer_flag(CustomData *data, const eCustomDataType type, const int flag)
const void * CustomData_get_layer_n(const CustomData *data, const eCustomDataType type, const int n)
bool CustomData_free_layer_active(CustomData *data, const eCustomDataType type, const int totelem)
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition customdata.cc:91
void CustomData_set_layer_render_index(CustomData *data, const eCustomDataType type, const int n)
int CustomData_get_named_layer_index_notype(const CustomData *data, const StringRef name)
static void layerCopy_origspace_face(const void *source, void *dest, const int count)
static bool layerEqual_propfloat2(const void *data1, const void *data2)
void CustomData_copy_layer_type_data(const CustomData *source, CustomData *destination, const eCustomDataType type, int source_index, int destination_index, int count)
static void layerMultiply_mloop_origspace(void *data, const float fac)
static void layerInterp_mvert_skin(const void **sources, const float *weights, const float *, int count, void *dest)
static void write_mdisps(BlendWriter *writer, const int count, const MDisps *mdlist, const int external)
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n)
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data, void *block, const eCustomDataMask mask_exclude)
void customData_mask_layers__print(const CustomData_MeshMasks *mask)
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int count)
void CustomData_reset(CustomData *data)
bool CustomData_free_layer_named(CustomData *data, const StringRef name, const int totelem)
static void layerMultiply_propcol(void *data, const float fac)
static void layerFree_grid_paint_mask(void *data, const int count)
static void layerInterp_mcol(const void **sources, const float *weights, const float *sub_weights, const int count, void *dest)
static void layerCopy_bmesh_elem_py_ptr(const void *, void *dest, const int count)
static void * copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
#define SOURCE_BUF_SIZE
static void write_grid_paint_mask(BlendWriter *writer, int count, const GridPaintMask *grid_paint_mask)
static void layerDefault_origspace_face(void *data, const int count)
static void layerMultiply_propfloat3(void *data, const float fac)
static bool customdata_unique_check(void *arg, const char *name)
int CustomData_get_layer_index(const CustomData *data, const eCustomDataType type)
static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
static void layerSwap_tface(void *data, const int *corner_indices)
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref, const CustomData_MeshMasks *mask_required)
int CustomData_get_render_layer(const CustomData *data, const eCustomDataType type)
int CustomData_get_clone_layer_index(const CustomData *data, const eCustomDataType type)
static const ImplicitSharingInfo * make_implicit_sharing_info_for_layer(const eCustomDataType type, const void *data, const int totelem)
void CustomData_copy_data(const CustomData *source, CustomData *dest, const int source_index, const int dest_index, const int count)
bool CustomData_has_interp(const CustomData *data)
bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
void CustomData_copy_elements(const eCustomDataType type, void *src_data_ofs, void *dst_data_ofs, const int count)
const void * CustomData_add_layer_with_data(CustomData *data, const eCustomDataType type, void *layer_data, const int totelem, const ImplicitSharingInfo *sharing_info)
void CustomData_bmesh_interp(CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block)
const CustomData_MeshMasks CD_MASK_BAREMESH
int CustomData_get_active_layer_index(const CustomData *data, const eCustomDataType type)
void CustomData_free_typemask(CustomData *data, const int totelem, eCustomDataMask mask)
static void customData_update_offsets(CustomData *data)
const char * CustomData_get_render_layer_name(const CustomData *data, const eCustomDataType type)
static void layerAdd_mloopcol(void *data1, const void *data2)
static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
void CustomData_free_layers(CustomData *data, const eCustomDataType type, const int totelem)
static void layerCopy_mdeformvert(const void *source, void *dest, const int count)
static void layerInterp_tface(const void **sources, const float *weights, const float *sub_weights, const int count, void *dest)
static CustomDataLayer * customData_add_layer__internal(CustomData *data, eCustomDataType type, std::optional< eCDAllocType > alloctype, void *layer_data_to_assign, const ImplicitSharingInfo *sharing_info_to_assign, int totelem, const StringRef name)
void CustomData_data_initminmax(const eCustomDataType type, void *min, void *max)
void CustomData_copy_data_named(const CustomData *source, CustomData *dest, const int source_index, const int dest_index, const int count)
static void layerAdd_mloop_origspace(void *data1, const void *data2)
void CustomData_set_layer_render(CustomData *data, const eCustomDataType type, const int n)
static void layerSwap_origspace_face(void *data, const int *corner_indices)
static void layerCopy_mvert_skin(const void *source, void *dest, const int count)
int CustomData_name_maxncpy_calc(const blender::StringRef name)
void * CustomData_bmesh_get(const CustomData *data, void *block, const eCustomDataType type)
void CustomData_data_copy_value(const eCustomDataType type, const void *source, void *dest)
void CustomData_init_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
const void * CustomData_add_layer_named_with_data(CustomData *data, eCustomDataType type, void *layer_data, int totelem, const StringRef name, const ImplicitSharingInfo *sharing_info)
static bool layerEqual_propcol(const void *data1, const void *data2)
static void layerInterp_shapekey(const void **sources, const float *weights, const float *, int count, void *dest)
static void layerInitMinMax_propcol(void *vmin, void *vmax)
void CustomData_bmesh_interp_n(CustomData *data, const void **src_blocks_ofs, const float *weights, const float *sub_weights, int count, void *dst_block_ofs, int n)
const void * CustomData_get_layer_named(const CustomData *data, const eCustomDataType type, const StringRef name)
bool CustomData_has_layer(const CustomData *data, const eCustomDataType type)
bool CustomData_merge_layout(const CustomData *source, CustomData *dest, const eCustomDataMask mask, const eCDAllocType alloctype, const int totelem)
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
bool CustomData_merge(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDataMask mask)
void CustomData_file_write_info(const eCustomDataType type, const char **r_struct_name, int *r_struct_num)
static void layerAdd_propfloat3(void *data1, const void *data2)
bool CustomData_data_equals(const eCustomDataType type, const void *data1, const void *data2)
static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
static void layerInterp_propFloat(const void **sources, const float *weights, const float *, const int count, void *dest)
void CustomData_external_reload(CustomData *data, ID *, eCustomDataMask mask, int totelem)
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src, const eCustomDataMask mask)
static void layerDefault_tface(void *data, const int count)
void CustomData_set_layer_clone(CustomData *data, const eCustomDataType type, const int n)
void CustomData_free_elem(CustomData *data, const int index, const int count)
static void layerDefault_propcol(void *data, const int count)
static void blend_read_paint_mask(BlendDataReader *reader, int count, GridPaintMask *grid_paint_mask)
void CustomData_data_set_default_value(const eCustomDataType type, void *elem)
static bool layer_is_mutable(CustomDataLayer &layer)
static void layerCopy_tface(const void *source, void *dest, const int count)
const CustomData_MeshMasks CD_MASK_BMESH
static bool layerWrite_mdisps(CDataFile *cdf, const void *data, const int count)
void CustomData_update_typemap(CustomData *data)
void CustomData_bmesh_copy_block(CustomData &dst_data, const BMCustomDataCopyMap &copy_map, const void *src_block, void **dst_block)
void CustomData_bmesh_set_default(CustomData *data, void **block)
static void layerAdd_propcol(void *data1, const void *data2)
void CustomData_data_dominmax(const eCustomDataType type, const void *data, void *min, void *max)
static void layerInterp_propfloat2(const void **sources, const float *weights, const float *, int count, void *dest)
void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype)
static void layerInterp_origspace_face(const void **sources, const float *weights, const float *sub_weights, const int count, void *dest)
void CustomData_realloc(CustomData *data, const int old_size, const int new_size, const eCDAllocType alloctype)
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *)
void CustomData_set_layer_clone_index(CustomData *data, const eCustomDataType type, const int n)
static void CustomData_external_free(CustomData *data)
void CustomData_set_layer_stencil_index(CustomData *data, const eCustomDataType type, const int n)
static void layerAdd_propfloat2(void *data1, const void *data2)
const char * CustomData_get_active_layer_name(const CustomData *data, const eCustomDataType type)
static bool customdata_typemap_is_valid(const CustomData *data)
static void layerInterp_normal(const void **sources, const float *weights, const float *, const int count, void *dest)
static void layerDefault_mcol(void *data, const int count)
bool CustomData_layertype_is_singleton(const eCustomDataType type)
bool CustomData_layer_has_interp(const CustomData *data, const int layer_n)
static void layerFree_mdeformvert(void *data, const int count)
static void layerInterp_mloopcol(const void **sources, const float *weights, const float *, int count, void *dest)
static bool layerEqual_mloopcol(const void *data1, const void *data2)
void CustomData_init_layout_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
bool CustomData_free_layer(CustomData *data, const eCustomDataType type, const int totelem, const int index)
void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
static void layerDefault_origindex(void *data, const int count)
static void layerDefault_mvert_skin(void *data, const int count)
void * CustomData_add_layer(CustomData *data, const eCustomDataType type, eCDAllocType alloctype, const int totelem)
int CustomData_get_stencil_layer_index(const CustomData *data, const eCustomDataType type)
int CustomData_get_named_layer(const CustomData *data, const eCustomDataType type, const StringRef name)
static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
void CustomData_external_add(CustomData *data, ID *, const eCustomDataType type, const int, const char *filepath)
void CustomData_external_remove(CustomData *data, ID *id, const eCustomDataType type, const int totelem)
static void customdata_external_filename(char filepath[FILE_MAX], ID *id, CustomDataExternal *external)
bool CustomData_bmesh_has_free(const CustomData *data)
static void layerInterp_propInt(const void **sources, const float *weights, const float *, const int count, void *dest)
static void layerDefault_propfloat4x4(void *data, const int count)
static void layerInterp_mdeformvert(const void **sources, const float *weights, const float *, const int count, void *dest)
static bool customdata_merge_internal(const CustomData *source, CustomData *dest, const eCustomDataMask mask, const std::optional< eCDAllocType > alloctype, const int totelem)
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, const int totelem)
static void layerFree_bmesh_elem_py_ptr(void *data, const int count)
int CustomData_number_of_anonymous_layers(const CustomData *data, const eCustomDataType type)
void CustomData_swap_corners(CustomData *data, const int index, const int *corner_indices)
static void layerCopyValue_propfloat2(const void *source, void *dest, const int mixmode, const float mixfactor)
size_t CustomData_get_elem_size(const CustomDataLayer *layer)
void CustomData_count_memory(const CustomData &data, const int totelem, blender::MemoryCounter &memory)
int CustomData_number_of_layers(const CustomData *data, const eCustomDataType type)
bool CustomData_has_layer_named(const CustomData *data, const eCustomDataType type, const StringRef name)
static void layerCopyValue_propcol(const void *source, void *dest, const int mixmode, const float mixfactor)
BMCustomDataCopyMap CustomData_bmesh_copy_map_calc(const CustomData &src, const CustomData &dst, const eCustomDataMask mask_exclude)
const void * CustomData_get_layer(const CustomData *data, const eCustomDataType type)
static void blend_read_layer_data(BlendDataReader *reader, CustomDataLayer &layer, const int count)
static int CustomData_get_layer_index__notypemap(const CustomData *data, const eCustomDataType type)
void CustomData_set_layer_unique_name(CustomData *data, const int index)
void CustomData_ensure_layers_are_mutable(CustomData *data, int totelem)
static void layerSwap_mcol(void *data, const int *corner_indices)
static void customData_resize(CustomData *data, const int grow_amount)
static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
static CLG_LogRef LOG
Definition customdata.cc:85
const CustomData_MeshMasks CD_MASK_DERIVEDMESH
int CustomData_sizeof(const eCustomDataType type)
static void layerInterp_mloop_origspace(const void **sources, const float *weights, const float *, int count, void *dest)
static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
bool CustomData_external_test(CustomData *data, const eCustomDataType type)
void CustomData_bmesh_set_n(CustomData *data, void *block, const eCustomDataType type, const int n, const void *source)
bool CustomData_bmesh_merge_layout(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, BMesh *bm, const char htype)
bool CustomData_set_layer_name(CustomData *data, const eCustomDataType type, const int n, const StringRef name)
int CustomData_get_clone_layer(const CustomData *data, const eCustomDataType type)
void CustomData_ensure_data_is_mutable(CustomDataLayer *layer, const int totelem)
static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
const char * CustomData_get_layer_name(const CustomData *data, const eCustomDataType type, const int n)
int CustomData_get_named_layer_index(const CustomData *data, const eCustomDataType type, const StringRef name)
static void layerConstruct_mdisps(void *data, const int count)
static const char * LAYERTYPENAMES[CD_NUMTYPES]
static void layerCopy_mdisps(const void *source, void *dest, const int count)
int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
void * CustomData_bmesh_get_n(const CustomData *data, void *block, const eCustomDataType type, const int n)
bool CustomData_layer_has_math(const CustomData *data, const int layer_n)
static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax)
static void layerInterp_propbool(const void **sources, const float *weights, const float *, int count, void *dest)
bool CustomData_has_math(const CustomData *data)
void CustomData_bmesh_alloc_block(CustomData *data, void **block)
static bool cd_layer_find_dupe(CustomData *data, const StringRef name, const eCustomDataType type, const int index)
void CustomData_data_multiply(const eCustomDataType type, void *data, const float fac)
void CustomData_set_only_copy(const CustomData *data, const eCustomDataMask mask)
static const char * layerType_getName(const eCustomDataType type)
void * CustomData_bmesh_get_layer_n(const CustomData *data, void *block, const int n)
#define CUSTOMDATA_GROW
Definition customdata.cc:79
static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
static void layerInterp_propquaternion(const void **sources, const float *weights, const float *, int count, void *dest)
const CustomData_MeshMasks CD_MASK_MESH
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
#define COPY_BIT_FLAG(_type, _dst, _src, _f)
void CustomData_external_write(CustomData *data, ID *id, eCustomDataMask mask, const int totelem, const int free)
void * CustomData_get_layer_n_for_write(CustomData *data, const eCustomDataType type, const int n, const int totelem)
static void layerCopyValue_mloopcol(const void *source, void *dest, const int mixmode, const float mixfactor)
static void layerSwap_mdisps(void *data, const int *ci)
void CustomData_set_layer_active(CustomData *data, const eCustomDataType type, const int n)
static void layerConstruct_grid_paint_mask(void *data, const int count)
void * CustomData_add_layer_named(CustomData *data, const eCustomDataType type, const eCDAllocType alloctype, const int totelem, const StringRef name)
void CustomData_copy_data_layer(const CustomData *source, CustomData *dest, const int src_layer_index, const int dst_layer_index, const int src_index, const int dst_index, const int count)
int CustomData_get_n_offset(const CustomData *data, const eCustomDataType type, const int n)
static void layerInterp_propfloat3(const void **sources, const float *weights, const float *, int count, void *dest)
OperationNode * node
#define logf(x)
#define sqrtf(x)
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
uint col
int count
#define PRIx64
Definition inttypes.h:133
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:110
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float2 interp(const float2 a, const float2 b, float t)
static ulong * next
typename DefaultMixerStruct< T >::type DefaultMixer
bool attribute_name_is_anonymous(const StringRef name)
std::optional< VolumeGridType > custom_data_type_to_volume_grid_type(eCustomDataType type)
std::optional< eCustomDataType > volume_grid_type_to_custom_data_type(VolumeGridType type)
T interpolate(const T &a, const T &b, const FactorT &t)
void min_max(const T &value, T &min, T &max)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
static void update(bNodeTree *ntree)
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
unsigned short uint16_t
Definition stdint.h:79
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
signed char int8_t
Definition stdint.h:75
blender::Vector< Free > free
blender::Vector< TrivialCopy > trivial_copies
blender::Vector< TrivialDefault > trivial_defaults
blender::Vector< Default > defaults
blender::Vector< Copy > copies
void * data
BMHeader head
int totvert
int totedge
int totloop
int totface
CLG_LogType * type
Definition CLG_log.h:108
const ImplicitSharingInfoHandle * sharing_info
cd_datatransfer_interp interp
struct BLI_mempool * pool
CustomDataLayer * layers
CustomDataExternal * external
Definition DNA_ID.h:413
bool(* write)(CDataFile *cdf, const void *data, int count)
void(* dominmax)(const void *data1, void *min, void *max)
const char * defaultname
cd_interp interp
void(* copyvalue)(const void *source, void *dest, int mixmode, const float mixfactor)
void(* add)(void *data1, const void *data2)
cd_set_default_value set_default_value
size_t(* filesize)(CDataFile *cdf, const void *data, int count)
const char * structname
int(* layers_max)()
bool(* read)(CDataFile *cdf, void *data, int count)
void(* initminmax)(void *min, void *max)
cd_validate validate
void(* swap)(void *data, const int *corner_indices)
bool(* equal)(const void *data1, const void *data2)
void(* construct)(void *data, int count)
void(* multiply)(void *data, float fac)
unsigned char r
unsigned char a
unsigned char g
unsigned char b
struct MDeformWeight * dw
unsigned int def_nr
float(* disps)[3]
unsigned int * hidden
unsigned char a
unsigned char b
unsigned char r
unsigned char g
float uv[4][2]
MeshPairRemapItem * items
float x
float y
float x
float z
float y
float max
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138