Blender  V3.3
customdata.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2006 Blender Foundation. All rights reserved. */
3 
11 #include "MEM_guardedalloc.h"
12 
13 /* Since we have versioning code here (CustomData_verify_versions()). */
14 #define DNA_DEPRECATED_ALLOW
15 
16 #include "DNA_ID.h"
17 #include "DNA_customdata_types.h"
18 #include "DNA_meshdata_types.h"
19 
20 #include "BLI_bitmap.h"
21 #include "BLI_color.hh"
22 #include "BLI_endian_switch.h"
23 #include "BLI_index_range.hh"
24 #include "BLI_math.h"
25 #include "BLI_math_color_blend.h"
26 #include "BLI_math_vector.hh"
27 #include "BLI_mempool.h"
28 #include "BLI_path_util.h"
29 #include "BLI_span.hh"
30 #include "BLI_string.h"
31 #include "BLI_string_ref.hh"
32 #include "BLI_string_utils.h"
33 #include "BLI_utildefines.h"
34 
35 #ifndef NDEBUG
36 # include "BLI_dynstr.h"
37 #endif
38 
39 #include "BLT_translation.h"
40 
42 #include "BKE_customdata.h"
43 #include "BKE_customdata_file.h"
44 #include "BKE_deform.h"
45 #include "BKE_main.h"
46 #include "BKE_mesh_mapping.h"
47 #include "BKE_mesh_remap.h"
48 #include "BKE_multires.h"
49 #include "BKE_subsurf.h"
50 
51 #include "BLO_read_write.h"
52 
53 #include "bmesh.h"
54 
55 #include "CLG_log.h"
56 
57 /* only for customdata_data_transfer_interp_normal_normals */
58 #include "data_transfer_intern.h"
59 
61 using blender::Span;
62 using blender::StringRef;
63 using blender::Vector;
64 
65 /* number of layers to add when growing a CustomData object */
66 #define CUSTOMDATA_GROW 5
67 
68 /* ensure typemap size is ok */
69 BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)nullptr)->typemap) == CD_NUMTYPES, "size mismatch");
70 
71 static CLG_LogRef LOG = {"bke.customdata"};
72 
73 /* -------------------------------------------------------------------- */
78  const CustomData_MeshMasks *mask_src)
79 {
80  mask_dst->vmask |= mask_src->vmask;
81  mask_dst->emask |= mask_src->emask;
82  mask_dst->fmask |= mask_src->fmask;
83  mask_dst->pmask |= mask_src->pmask;
84  mask_dst->lmask |= mask_src->lmask;
85 }
86 
88  const CustomData_MeshMasks *mask_required)
89 {
90  return (((mask_required->vmask & mask_ref->vmask) == mask_required->vmask) &&
91  ((mask_required->emask & mask_ref->emask) == mask_required->emask) &&
92  ((mask_required->fmask & mask_ref->fmask) == mask_required->fmask) &&
93  ((mask_required->pmask & mask_ref->pmask) == mask_required->pmask) &&
94  ((mask_required->lmask & mask_ref->lmask) == mask_required->lmask));
95 }
96 
99 /* -------------------------------------------------------------------- */
104  int size; /* the memory size of one element of this layer's data */
105 
107  const char *structname;
110 
117  const char *defaultname;
118 
125 
132  void (*free)(void *data, int count, int size);
133 
150 
152  void (*swap)(void *data, const int *corner_indices);
153 
157  void (*set_default)(void *data, int count);
158 
161 
163  bool (*equal)(const void *data1, const void *data2);
164  void (*multiply)(void *data, float fac);
165  void (*initminmax)(void *min, void *max);
166  void (*add)(void *data1, const void *data2);
167  void (*dominmax)(const void *data1, void *min, void *max);
168  void (*copyvalue)(const void *source, void *dest, const int mixmode, const float mixfactor);
169 
171  bool (*read)(CDataFile *cdf, void *data, int count);
172 
174  bool (*write)(CDataFile *cdf, const void *data, int count);
175 
177  size_t (*filesize)(CDataFile *cdf, const void *data, int count);
178 
181  int (*layers_max)();
182 };
183 
186 /* -------------------------------------------------------------------- */
190 static void layerCopy_mdeformvert(const void *source, void *dest, int count)
191 {
192  int i, size = sizeof(MDeformVert);
193 
194  memcpy(dest, source, count * size);
195 
196  for (i = 0; i < count; i++) {
197  MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(dest, i * size));
198 
199  if (dvert->totweight) {
200  MDeformWeight *dw = static_cast<MDeformWeight *>(
201  MEM_malloc_arrayN(dvert->totweight, sizeof(*dw), __func__));
202 
203  memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
204  dvert->dw = dw;
205  }
206  else {
207  dvert->dw = nullptr;
208  }
209  }
210 }
211 
212 static void layerFree_mdeformvert(void *data, int count, int size)
213 {
214  for (int i = 0; i < count; i++) {
215  MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(data, i * size));
216 
217  if (dvert->dw) {
218  MEM_freeN(dvert->dw);
219  dvert->dw = nullptr;
220  dvert->totweight = 0;
221  }
222  }
223 }
224 
225 /* copy just zeros in this case */
226 static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, int count)
227 {
228  const int size = sizeof(void *);
229 
230  for (int i = 0; i < count; i++) {
231  void **ptr = (void **)POINTER_OFFSET(dest, i * size);
232  *ptr = nullptr;
233  }
234 }
235 
236 #ifndef WITH_PYTHON
238 {
239  /* dummy */
240 }
241 #endif
242 
243 static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size)
244 {
245  for (int i = 0; i < count; i++) {
246  void **ptr = (void **)POINTER_OFFSET(data, i * size);
247  if (*ptr) {
248  bpy_bm_generic_invalidate(static_cast<BPy_BMGeneric *>(*ptr));
249  }
250  }
251 }
252 
253 static void layerInterp_mdeformvert(const void **sources,
254  const float *weights,
255  const float *UNUSED(sub_weights),
256  int count,
257  void *dest)
258 {
259  /* a single linked list of MDeformWeight's
260  * use this to avoid double allocs (which LinkNode would do) */
261  struct MDeformWeight_Link {
262  struct MDeformWeight_Link *next;
263  MDeformWeight dw;
264  };
265 
266  MDeformVert *dvert = static_cast<MDeformVert *>(dest);
267  MDeformWeight_Link *dest_dwlink = nullptr;
268  MDeformWeight_Link *node;
269 
270  /* build a list of unique def_nrs for dest */
271  int totweight = 0;
272  for (int i = 0; i < count; i++) {
273  const MDeformVert *source = static_cast<const MDeformVert *>(sources[i]);
274  float interp_weight = weights[i];
275 
276  for (int j = 0; j < source->totweight; j++) {
277  MDeformWeight *dw = &source->dw[j];
278  float weight = dw->weight * interp_weight;
279 
280  if (weight == 0.0f) {
281  continue;
282  }
283 
284  for (node = dest_dwlink; node; node = node->next) {
285  MDeformWeight *tmp_dw = &node->dw;
286 
287  if (tmp_dw->def_nr == dw->def_nr) {
288  tmp_dw->weight += weight;
289  break;
290  }
291  }
292 
293  /* if this def_nr is not in the list, add it */
294  if (!node) {
295  MDeformWeight_Link *tmp_dwlink = static_cast<MDeformWeight_Link *>(
296  alloca(sizeof(*tmp_dwlink)));
297  tmp_dwlink->dw.def_nr = dw->def_nr;
298  tmp_dwlink->dw.weight = weight;
299 
300  /* Inline linked-list. */
301  tmp_dwlink->next = dest_dwlink;
302  dest_dwlink = tmp_dwlink;
303 
304  totweight++;
305  }
306  }
307  }
308 
309  /* Delay writing to the destination in case dest is in sources. */
310 
311  /* now we know how many unique deform weights there are, so realloc */
312  if (dvert->dw && (dvert->totweight == totweight)) {
313  /* pass (fast-path if we don't need to realloc). */
314  }
315  else {
316  if (dvert->dw) {
317  MEM_freeN(dvert->dw);
318  }
319 
320  if (totweight) {
321  dvert->dw = static_cast<MDeformWeight *>(
322  MEM_malloc_arrayN(totweight, sizeof(*dvert->dw), __func__));
323  }
324  }
325 
326  if (totweight) {
327  dvert->totweight = totweight;
328  int i = 0;
329  for (node = dest_dwlink; node; node = node->next, i++) {
330  if (node->dw.weight > 1.0f) {
331  node->dw.weight = 1.0f;
332  }
333  dvert->dw[i] = node->dw;
334  }
335  }
336  else {
337  memset(dvert, 0, sizeof(*dvert));
338  }
339 }
340 
343 /* -------------------------------------------------------------------- */
347 static void layerInterp_normal(const void **sources,
348  const float *weights,
349  const float *UNUSED(sub_weights),
350  int count,
351  void *dest)
352 {
353  /* NOTE: This is linear interpolation, which is not optimal for vectors.
354  * Unfortunately, spherical interpolation of more than two values is hairy,
355  * so for now it will do... */
356  float no[3] = {0.0f};
357 
358  while (count--) {
359  madd_v3_v3fl(no, (const float *)sources[count], weights[count]);
360  }
361 
362  /* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */
363  normalize_v3_v3((float *)dest, no);
364 }
365 
366 static void layerCopyValue_normal(const void *source,
367  void *dest,
368  const int mixmode,
369  const float mixfactor)
370 {
371  const float *no_src = (const float *)source;
372  float *no_dst = (float *)dest;
373  float no_tmp[3];
374 
375  if (ELEM(mixmode,
379  /* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
380  copy_v3_v3(no_dst, no_src);
381  }
382  else { /* Modes that support 'real' mix factor. */
383  /* Since we normalize in the end, MIX and ADD are the same op here. */
384  if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
385  add_v3_v3v3(no_tmp, no_dst, no_src);
386  normalize_v3(no_tmp);
387  }
388  else if (mixmode == CDT_MIX_SUB) {
389  sub_v3_v3v3(no_tmp, no_dst, no_src);
390  normalize_v3(no_tmp);
391  }
392  else if (mixmode == CDT_MIX_MUL) {
393  mul_v3_v3v3(no_tmp, no_dst, no_src);
394  normalize_v3(no_tmp);
395  }
396  else {
397  copy_v3_v3(no_tmp, no_src);
398  }
399  interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
400  }
401 }
402 
405 /* -------------------------------------------------------------------- */
409 static void layerCopy_tface(const void *source, void *dest, int count)
410 {
411  const MTFace *source_tf = (const MTFace *)source;
412  MTFace *dest_tf = (MTFace *)dest;
413  for (int i = 0; i < count; i++) {
414  dest_tf[i] = source_tf[i];
415  }
416 }
417 
418 static void layerInterp_tface(
419  const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
420 {
421  MTFace *tf = static_cast<MTFace *>(dest);
422  float uv[4][2] = {{0.0f}};
423 
424  const float *sub_weight = sub_weights;
425  for (int i = 0; i < count; i++) {
426  const float interp_weight = weights[i];
427  const MTFace *src = static_cast<const MTFace *>(sources[i]);
428 
429  for (int j = 0; j < 4; j++) {
430  if (sub_weights) {
431  for (int k = 0; k < 4; k++, sub_weight++) {
432  madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
433  }
434  }
435  else {
436  madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
437  }
438  }
439  }
440 
441  /* Delay writing to the destination in case dest is in sources. */
442  *tf = *(MTFace *)(*sources);
443  memcpy(tf->uv, uv, sizeof(tf->uv));
444 }
445 
446 static void layerSwap_tface(void *data, const int *corner_indices)
447 {
448  MTFace *tf = static_cast<MTFace *>(data);
449  float uv[4][2];
450 
451  for (int j = 0; j < 4; j++) {
452  const int source_index = corner_indices[j];
453  copy_v2_v2(uv[j], tf->uv[source_index]);
454  }
455 
456  memcpy(tf->uv, uv, sizeof(tf->uv));
457 }
458 
459 static void layerDefault_tface(void *data, int count)
460 {
461  static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
462  MTFace *tf = (MTFace *)data;
463 
464  for (int i = 0; i < count; i++) {
465  tf[i] = default_tf;
466  }
467 }
468 
469 static int layerMaxNum_tface()
470 {
471  return MAX_MTFACE;
472 }
473 
476 /* -------------------------------------------------------------------- */
480 static void layerCopy_propFloat(const void *source, void *dest, int count)
481 {
482  memcpy(dest, source, sizeof(MFloatProperty) * count);
483 }
484 
485 static void layerInterp_propFloat(const void **sources,
486  const float *weights,
487  const float *UNUSED(sub_weights),
488  int count,
489  void *dest)
490 {
491  float result = 0.0f;
492  for (int i = 0; i < count; i++) {
493  const float interp_weight = weights[i];
494  const float src = *(const float *)sources[i];
495  result += src * interp_weight;
496  }
497  *(float *)dest = result;
498 }
499 
500 static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
501 {
502  MFloatProperty *fp = static_cast<MFloatProperty *>(data);
503  bool has_errors = false;
504 
505  for (int i = 0; i < totitems; i++, fp++) {
506  if (!isfinite(fp->f)) {
507  if (do_fixes) {
508  fp->f = 0.0f;
509  }
510  has_errors = true;
511  }
512  }
513 
514  return has_errors;
515 }
516 
519 /* -------------------------------------------------------------------- */
523 static void layerCopy_propInt(const void *source, void *dest, int count)
524 {
525  memcpy(dest, source, sizeof(MIntProperty) * count);
526 }
527 
528 static void layerInterp_propInt(const void **sources,
529  const float *weights,
530  const float *UNUSED(sub_weights),
531  int count,
532  void *dest)
533 {
534  float result = 0.0f;
535  for (const int i : IndexRange(count)) {
536  const float weight = weights[i];
537  const float src = *static_cast<const int *>(sources[i]);
538  result += src * weight;
539  }
540  const int rounded_result = static_cast<int>(round(result));
541  *static_cast<int *>(dest) = rounded_result;
542 }
543 
546 /* -------------------------------------------------------------------- */
550 static void layerCopy_propString(const void *source, void *dest, int count)
551 {
552  memcpy(dest, source, sizeof(MStringProperty) * count);
553 }
554 
557 /* -------------------------------------------------------------------- */
561 static void layerCopy_origspace_face(const void *source, void *dest, int count)
562 {
563  const OrigSpaceFace *source_tf = (const OrigSpaceFace *)source;
564  OrigSpaceFace *dest_tf = (OrigSpaceFace *)dest;
565 
566  for (int i = 0; i < count; i++) {
567  dest_tf[i] = source_tf[i];
568  }
569 }
570 
572  const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
573 {
574  OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(dest);
575  float uv[4][2] = {{0.0f}};
576 
577  const float *sub_weight = sub_weights;
578  for (int i = 0; i < count; i++) {
579  const float interp_weight = weights[i];
580  const OrigSpaceFace *src = static_cast<const OrigSpaceFace *>(sources[i]);
581 
582  for (int j = 0; j < 4; j++) {
583  if (sub_weights) {
584  for (int k = 0; k < 4; k++, sub_weight++) {
585  madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
586  }
587  }
588  else {
589  madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
590  }
591  }
592  }
593 
594  /* Delay writing to the destination in case dest is in sources. */
595  memcpy(osf->uv, uv, sizeof(osf->uv));
596 }
597 
598 static void layerSwap_origspace_face(void *data, const int *corner_indices)
599 {
600  OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(data);
601  float uv[4][2];
602 
603  for (int j = 0; j < 4; j++) {
604  copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
605  }
606  memcpy(osf->uv, uv, sizeof(osf->uv));
607 }
608 
609 static void layerDefault_origspace_face(void *data, int count)
610 {
611  static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
612  OrigSpaceFace *osf = (OrigSpaceFace *)data;
613 
614  for (int i = 0; i < count; i++) {
615  osf[i] = default_osf;
616  }
617 }
618 
621 /* -------------------------------------------------------------------- */
625 static void layerSwap_mdisps(void *data, const int *ci)
626 {
627  MDisps *s = static_cast<MDisps *>(data);
628 
629  if (s->disps) {
630  int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
631  int corners = multires_mdisp_corners(s);
632  int cornersize = s->totdisp / corners;
633 
634  if (corners != nverts) {
635  /* happens when face changed vertex count in edit mode
636  * if it happened, just forgot displacement */
637 
638  MEM_freeN(s->disps);
639  s->totdisp = (s->totdisp / corners) * nverts;
640  s->disps = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisp swap");
641  return;
642  }
643 
644  float(*d)[3] = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
645 
646  for (int S = 0; S < corners; S++) {
647  memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize);
648  }
649 
650  MEM_freeN(s->disps);
651  s->disps = d;
652  }
653 }
654 
655 static void layerCopy_mdisps(const void *source, void *dest, int count)
656 {
657  const MDisps *s = static_cast<const MDisps *>(source);
658  MDisps *d = static_cast<MDisps *>(dest);
659 
660  for (int i = 0; i < count; i++) {
661  if (s[i].disps) {
662  d[i].disps = static_cast<float(*)[3]>(MEM_dupallocN(s[i].disps));
663  d[i].hidden = static_cast<unsigned int *>(MEM_dupallocN(s[i].hidden));
664  }
665  else {
666  d[i].disps = nullptr;
667  d[i].hidden = nullptr;
668  }
669 
670  /* still copy even if not in memory, displacement can be external */
671  d[i].totdisp = s[i].totdisp;
672  d[i].level = s[i].level;
673  }
674 }
675 
676 static void layerFree_mdisps(void *data, int count, int UNUSED(size))
677 {
678  MDisps *d = static_cast<MDisps *>(data);
679 
680  for (int i = 0; i < count; i++) {
681  if (d[i].disps) {
682  MEM_freeN(d[i].disps);
683  }
684  if (d[i].hidden) {
685  MEM_freeN(d[i].hidden);
686  }
687  d[i].disps = nullptr;
688  d[i].hidden = nullptr;
689  d[i].totdisp = 0;
690  d[i].level = 0;
691  }
692 }
693 
694 static bool layerRead_mdisps(CDataFile *cdf, void *data, int count)
695 {
696  MDisps *d = static_cast<MDisps *>(data);
697 
698  for (int i = 0; i < count; i++) {
699  if (!d[i].disps) {
700  d[i].disps = (float(*)[3])MEM_calloc_arrayN(d[i].totdisp, sizeof(float[3]), "mdisps read");
701  }
702 
703  if (!cdf_read_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
704  CLOG_ERROR(&LOG, "failed to read multires displacement %d/%d %d", i, count, d[i].totdisp);
705  return false;
706  }
707  }
708 
709  return true;
710 }
711 
712 static bool layerWrite_mdisps(CDataFile *cdf, const void *data, int count)
713 {
714  const MDisps *d = static_cast<const MDisps *>(data);
715 
716  for (int i = 0; i < count; i++) {
717  if (!cdf_write_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
718  CLOG_ERROR(&LOG, "failed to write multires displacement %d/%d %d", i, count, d[i].totdisp);
719  return false;
720  }
721  }
722 
723  return true;
724 }
725 
726 static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int count)
727 {
728  const MDisps *d = static_cast<const MDisps *>(data);
729  size_t size = 0;
730 
731  for (int i = 0; i < count; i++) {
732  size += sizeof(float[3]) * d[i].totdisp;
733  }
734 
735  return size;
736 }
737 
740 /* -------------------------------------------------------------------- */
744 static void layerInterp_paint_mask(const void **sources,
745  const float *weights,
746  const float *UNUSED(sub_weights),
747  int count,
748  void *dest)
749 {
750  float mask = 0.0f;
751  for (int i = 0; i < count; i++) {
752  const float interp_weight = weights[i];
753  const float *src = static_cast<const float *>(sources[i]);
754  mask += (*src) * interp_weight;
755  }
756  *(float *)dest = mask;
757 }
758 
761 /* -------------------------------------------------------------------- */
765 static void layerCopy_grid_paint_mask(const void *source, void *dest, int count)
766 {
767  const GridPaintMask *s = static_cast<const GridPaintMask *>(source);
768  GridPaintMask *d = static_cast<GridPaintMask *>(dest);
769 
770  for (int i = 0; i < count; i++) {
771  if (s[i].data) {
772  d[i].data = static_cast<float *>(MEM_dupallocN(s[i].data));
773  d[i].level = s[i].level;
774  }
775  else {
776  d[i].data = nullptr;
777  d[i].level = 0;
778  }
779  }
780 }
781 
782 static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
783 {
784  GridPaintMask *gpm = static_cast<GridPaintMask *>(data);
785 
786  for (int i = 0; i < count; i++) {
787  MEM_SAFE_FREE(gpm[i].data);
788  gpm[i].level = 0;
789  }
790 }
791 
794 /* -------------------------------------------------------------------- */
798 static void layerCopyValue_mloopcol(const void *source,
799  void *dest,
800  const int mixmode,
801  const float mixfactor)
802 {
803  const MLoopCol *m1 = static_cast<const MLoopCol *>(source);
804  MLoopCol *m2 = static_cast<MLoopCol *>(dest);
805  unsigned char tmp_col[4];
806 
807  if (ELEM(mixmode,
811  /* Modes that do a full copy or nothing. */
813  /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
814  const float f = ((float)m2->r + (float)m2->g + (float)m2->b) / 3.0f;
815  if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
816  return; /* Do Nothing! */
817  }
818  if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
819  return; /* Do Nothing! */
820  }
821  }
822  m2->r = m1->r;
823  m2->g = m1->g;
824  m2->b = m1->b;
825  m2->a = m1->a;
826  }
827  else { /* Modes that support 'real' mix factor. */
828  unsigned char src[4] = {m1->r, m1->g, m1->b, m1->a};
829  unsigned char dst[4] = {m2->r, m2->g, m2->b, m2->a};
830 
831  if (mixmode == CDT_MIX_MIX) {
832  blend_color_mix_byte(tmp_col, dst, src);
833  }
834  else if (mixmode == CDT_MIX_ADD) {
835  blend_color_add_byte(tmp_col, dst, src);
836  }
837  else if (mixmode == CDT_MIX_SUB) {
838  blend_color_sub_byte(tmp_col, dst, src);
839  }
840  else if (mixmode == CDT_MIX_MUL) {
841  blend_color_mul_byte(tmp_col, dst, src);
842  }
843  else {
844  memcpy(tmp_col, src, sizeof(tmp_col));
845  }
846 
847  blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
848 
849  m2->r = (char)dst[0];
850  m2->g = (char)dst[1];
851  m2->b = (char)dst[2];
852  m2->a = (char)dst[3];
853  }
854 }
855 
856 static bool layerEqual_mloopcol(const void *data1, const void *data2)
857 {
858  const MLoopCol *m1 = static_cast<const MLoopCol *>(data1);
859  const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
860  float r, g, b, a;
861 
862  r = m1->r - m2->r;
863  g = m1->g - m2->g;
864  b = m1->b - m2->b;
865  a = m1->a - m2->a;
866 
867  return r * r + g * g + b * b + a * a < 0.001f;
868 }
869 
870 static void layerMultiply_mloopcol(void *data, float fac)
871 {
872  MLoopCol *m = static_cast<MLoopCol *>(data);
873 
874  m->r = (float)m->r * fac;
875  m->g = (float)m->g * fac;
876  m->b = (float)m->b * fac;
877  m->a = (float)m->a * fac;
878 }
879 
880 static void layerAdd_mloopcol(void *data1, const void *data2)
881 {
882  MLoopCol *m = static_cast<MLoopCol *>(data1);
883  const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
884 
885  m->r += m2->r;
886  m->g += m2->g;
887  m->b += m2->b;
888  m->a += m2->a;
889 }
890 
891 static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
892 {
893  const MLoopCol *m = static_cast<const MLoopCol *>(data);
894  MLoopCol *min = static_cast<MLoopCol *>(vmin);
895  MLoopCol *max = static_cast<MLoopCol *>(vmax);
896 
897  if (m->r < min->r) {
898  min->r = m->r;
899  }
900  if (m->g < min->g) {
901  min->g = m->g;
902  }
903  if (m->b < min->b) {
904  min->b = m->b;
905  }
906  if (m->a < min->a) {
907  min->a = m->a;
908  }
909  if (m->r > max->r) {
910  max->r = m->r;
911  }
912  if (m->g > max->g) {
913  max->g = m->g;
914  }
915  if (m->b > max->b) {
916  max->b = m->b;
917  }
918  if (m->a > max->a) {
919  max->a = m->a;
920  }
921 }
922 
923 static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
924 {
925  MLoopCol *min = static_cast<MLoopCol *>(vmin);
926  MLoopCol *max = static_cast<MLoopCol *>(vmax);
927 
928  min->r = 255;
929  min->g = 255;
930  min->b = 255;
931  min->a = 255;
932 
933  max->r = 0;
934  max->g = 0;
935  max->b = 0;
936  max->a = 0;
937 }
938 
939 static void layerDefault_mloopcol(void *data, int count)
940 {
941  MLoopCol default_mloopcol = {255, 255, 255, 255};
942  MLoopCol *mlcol = (MLoopCol *)data;
943  for (int i = 0; i < count; i++) {
944  mlcol[i] = default_mloopcol;
945  }
946 }
947 
948 static void layerInterp_mloopcol(const void **sources,
949  const float *weights,
950  const float *UNUSED(sub_weights),
951  int count,
952  void *dest)
953 {
954  MLoopCol *mc = static_cast<MLoopCol *>(dest);
955  struct {
956  float a;
957  float r;
958  float g;
959  float b;
960  } col = {0};
961 
962  for (int i = 0; i < count; i++) {
963  const float interp_weight = weights[i];
964  const MLoopCol *src = static_cast<const MLoopCol *>(sources[i]);
965  col.r += src->r * interp_weight;
966  col.g += src->g * interp_weight;
967  col.b += src->b * interp_weight;
968  col.a += src->a * interp_weight;
969  }
970 
971  /* Subdivide smooth or fractal can cause problems without clamping
972  * although weights should also not cause this situation */
973 
974  /* Also delay writing to the destination in case dest is in sources. */
975  mc->r = round_fl_to_uchar_clamp(col.r);
976  mc->g = round_fl_to_uchar_clamp(col.g);
977  mc->b = round_fl_to_uchar_clamp(col.b);
978  mc->a = round_fl_to_uchar_clamp(col.a);
979 }
980 
983 /* -------------------------------------------------------------------- */
987 static void layerCopyValue_mloopuv(const void *source,
988  void *dest,
989  const int mixmode,
990  const float mixfactor)
991 {
992  const MLoopUV *luv1 = static_cast<const MLoopUV *>(source);
993  MLoopUV *luv2 = static_cast<MLoopUV *>(dest);
994 
995  /* We only support a limited subset of advanced mixing here -
996  * namely the mixfactor interpolation. */
997 
998  if (mixmode == CDT_MIX_NOMIX) {
999  copy_v2_v2(luv2->uv, luv1->uv);
1000  }
1001  else {
1002  interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor);
1003  }
1004 }
1005 
1006 static bool layerEqual_mloopuv(const void *data1, const void *data2)
1007 {
1008  const MLoopUV *luv1 = static_cast<const MLoopUV *>(data1);
1009  const MLoopUV *luv2 = static_cast<const MLoopUV *>(data2);
1010 
1011  return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
1012 }
1013 
1014 static void layerMultiply_mloopuv(void *data, float fac)
1015 {
1016  MLoopUV *luv = static_cast<MLoopUV *>(data);
1017 
1018  mul_v2_fl(luv->uv, fac);
1019 }
1020 
1021 static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
1022 {
1023  MLoopUV *min = static_cast<MLoopUV *>(vmin);
1024  MLoopUV *max = static_cast<MLoopUV *>(vmax);
1025 
1026  INIT_MINMAX2(min->uv, max->uv);
1027 }
1028 
1029 static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax)
1030 {
1031  const MLoopUV *luv = static_cast<const MLoopUV *>(data);
1032  MLoopUV *min = static_cast<MLoopUV *>(vmin);
1033  MLoopUV *max = static_cast<MLoopUV *>(vmax);
1034 
1035  minmax_v2v2_v2(min->uv, max->uv, luv->uv);
1036 }
1037 
1038 static void layerAdd_mloopuv(void *data1, const void *data2)
1039 {
1040  MLoopUV *l1 = static_cast<MLoopUV *>(data1);
1041  const MLoopUV *l2 = static_cast<const MLoopUV *>(data2);
1042 
1043  add_v2_v2(l1->uv, l2->uv);
1044 }
1045 
1046 static void layerInterp_mloopuv(const void **sources,
1047  const float *weights,
1048  const float *UNUSED(sub_weights),
1049  int count,
1050  void *dest)
1051 {
1052  float uv[2];
1053  int flag = 0;
1054 
1055  zero_v2(uv);
1056 
1057  for (int i = 0; i < count; i++) {
1058  const float interp_weight = weights[i];
1059  const MLoopUV *src = static_cast<const MLoopUV *>(sources[i]);
1060  madd_v2_v2fl(uv, src->uv, interp_weight);
1061  if (interp_weight > 0.0f) {
1062  flag |= src->flag;
1063  }
1064  }
1065 
1066  /* Delay writing to the destination in case dest is in sources. */
1067  copy_v2_v2(((MLoopUV *)dest)->uv, uv);
1068  ((MLoopUV *)dest)->flag = flag;
1069 }
1070 
1071 static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes)
1072 {
1073  MLoopUV *uv = static_cast<MLoopUV *>(data);
1074  bool has_errors = false;
1075 
1076  for (int i = 0; i < totitems; i++, uv++) {
1077  if (!is_finite_v2(uv->uv)) {
1078  if (do_fixes) {
1079  zero_v2(uv->uv);
1080  }
1081  has_errors = true;
1082  }
1083  }
1084 
1085  return has_errors;
1086 }
1087 
1088 /* origspace is almost exact copy of mloopuv's, keep in sync */
1089 static void layerCopyValue_mloop_origspace(const void *source,
1090  void *dest,
1091  const int UNUSED(mixmode),
1092  const float UNUSED(mixfactor))
1093 {
1094  const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source);
1095  OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest);
1096 
1097  copy_v2_v2(luv2->uv, luv1->uv);
1098 }
1099 
1100 static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
1101 {
1102  const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(data1);
1103  const OrigSpaceLoop *luv2 = static_cast<const OrigSpaceLoop *>(data2);
1104 
1105  return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
1106 }
1107 
1108 static void layerMultiply_mloop_origspace(void *data, float fac)
1109 {
1110  OrigSpaceLoop *luv = static_cast<OrigSpaceLoop *>(data);
1111 
1112  mul_v2_fl(luv->uv, fac);
1113 }
1114 
1115 static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
1116 {
1117  OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
1118  OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
1119 
1120  INIT_MINMAX2(min->uv, max->uv);
1121 }
1122 
1123 static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
1124 {
1125  const OrigSpaceLoop *luv = static_cast<const OrigSpaceLoop *>(data);
1126  OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
1127  OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
1128 
1129  minmax_v2v2_v2(min->uv, max->uv, luv->uv);
1130 }
1131 
1132 static void layerAdd_mloop_origspace(void *data1, const void *data2)
1133 {
1134  OrigSpaceLoop *l1 = static_cast<OrigSpaceLoop *>(data1);
1135  const OrigSpaceLoop *l2 = static_cast<const OrigSpaceLoop *>(data2);
1136 
1137  add_v2_v2(l1->uv, l2->uv);
1138 }
1139 
1140 static void layerInterp_mloop_origspace(const void **sources,
1141  const float *weights,
1142  const float *UNUSED(sub_weights),
1143  int count,
1144  void *dest)
1145 {
1146  float uv[2];
1147  zero_v2(uv);
1148 
1149  for (int i = 0; i < count; i++) {
1150  const float interp_weight = weights[i];
1151  const OrigSpaceLoop *src = static_cast<const OrigSpaceLoop *>(sources[i]);
1152  madd_v2_v2fl(uv, src->uv, interp_weight);
1153  }
1154 
1155  /* Delay writing to the destination in case dest is in sources. */
1156  copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
1157 }
1158 /* --- end copy */
1159 
1160 static void layerInterp_mcol(
1161  const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
1162 {
1163  MCol *mc = static_cast<MCol *>(dest);
1164  struct {
1165  float a;
1166  float r;
1167  float g;
1168  float b;
1169  } col[4] = {{0.0f}};
1170 
1171  const float *sub_weight = sub_weights;
1172  for (int i = 0; i < count; i++) {
1173  const float interp_weight = weights[i];
1174 
1175  for (int j = 0; j < 4; j++) {
1176  if (sub_weights) {
1177  const MCol *src = static_cast<const MCol *>(sources[i]);
1178  for (int k = 0; k < 4; k++, sub_weight++, src++) {
1179  const float w = (*sub_weight) * interp_weight;
1180  col[j].a += src->a * w;
1181  col[j].r += src->r * w;
1182  col[j].g += src->g * w;
1183  col[j].b += src->b * w;
1184  }
1185  }
1186  else {
1187  const MCol *src = static_cast<const MCol *>(sources[i]);
1188  col[j].a += src[j].a * interp_weight;
1189  col[j].r += src[j].r * interp_weight;
1190  col[j].g += src[j].g * interp_weight;
1191  col[j].b += src[j].b * interp_weight;
1192  }
1193  }
1194  }
1195 
1196  /* Delay writing to the destination in case dest is in sources. */
1197  for (int j = 0; j < 4; j++) {
1198 
1199  /* Subdivide smooth or fractal can cause problems without clamping
1200  * although weights should also not cause this situation */
1201  mc[j].a = round_fl_to_uchar_clamp(col[j].a);
1202  mc[j].r = round_fl_to_uchar_clamp(col[j].r);
1203  mc[j].g = round_fl_to_uchar_clamp(col[j].g);
1204  mc[j].b = round_fl_to_uchar_clamp(col[j].b);
1205  }
1206 }
1207 
1208 static void layerSwap_mcol(void *data, const int *corner_indices)
1209 {
1210  MCol *mcol = static_cast<MCol *>(data);
1211  MCol col[4];
1212 
1213  for (int j = 0; j < 4; j++) {
1214  col[j] = mcol[corner_indices[j]];
1215  }
1216 
1217  memcpy(mcol, col, sizeof(col));
1218 }
1219 
1220 static void layerDefault_mcol(void *data, int count)
1221 {
1222  static MCol default_mcol = {255, 255, 255, 255};
1223  MCol *mcol = (MCol *)data;
1224 
1225  for (int i = 0; i < 4 * count; i++) {
1226  mcol[i] = default_mcol;
1227  }
1228 }
1229 
1230 static void layerDefault_origindex(void *data, int count)
1231 {
1232  copy_vn_i((int *)data, count, ORIGINDEX_NONE);
1233 }
1234 
1235 static void layerInterp_bweight(const void **sources,
1236  const float *weights,
1237  const float *UNUSED(sub_weights),
1238  int count,
1239  void *dest)
1240 {
1241  float **in = (float **)sources;
1242 
1243  if (count <= 0) {
1244  return;
1245  }
1246 
1247  float f = 0.0f;
1248 
1249  for (int i = 0; i < count; i++) {
1250  const float interp_weight = weights[i];
1251  f += *in[i] * interp_weight;
1252  }
1253 
1254  /* Delay writing to the destination in case dest is in sources. */
1255  *((float *)dest) = f;
1256 }
1257 
1258 static void layerInterp_shapekey(const void **sources,
1259  const float *weights,
1260  const float *UNUSED(sub_weights),
1261  int count,
1262  void *dest)
1263 {
1264  float **in = (float **)sources;
1265 
1266  if (count <= 0) {
1267  return;
1268  }
1269 
1270  float co[3];
1271  zero_v3(co);
1272 
1273  for (int i = 0; i < count; i++) {
1274  const float interp_weight = weights[i];
1275  madd_v3_v3fl(co, in[i], interp_weight);
1276  }
1277 
1278  /* Delay writing to the destination in case dest is in sources. */
1279  copy_v3_v3((float *)dest, co);
1280 }
1281 
1284 /* -------------------------------------------------------------------- */
1288 static void layerDefault_mvert_skin(void *data, int count)
1289 {
1290  MVertSkin *vs = static_cast<MVertSkin *>(data);
1291 
1292  for (int i = 0; i < count; i++) {
1293  copy_v3_fl(vs[i].radius, 0.25f);
1294  vs[i].flag = 0;
1295  }
1296 }
1297 
1298 static void layerCopy_mvert_skin(const void *source, void *dest, int count)
1299 {
1300  memcpy(dest, source, sizeof(MVertSkin) * count);
1301 }
1302 
1303 static void layerInterp_mvert_skin(const void **sources,
1304  const float *weights,
1305  const float *UNUSED(sub_weights),
1306  int count,
1307  void *dest)
1308 {
1309  float radius[3];
1310  zero_v3(radius);
1311 
1312  for (int i = 0; i < count; i++) {
1313  const float interp_weight = weights[i];
1314  const MVertSkin *vs_src = static_cast<const MVertSkin *>(sources[i]);
1315 
1316  madd_v3_v3fl(radius, vs_src->radius, interp_weight);
1317  }
1318 
1319  /* Delay writing to the destination in case dest is in sources. */
1320  MVertSkin *vs_dst = static_cast<MVertSkin *>(dest);
1321  copy_v3_v3(vs_dst->radius, radius);
1322  vs_dst->flag &= ~MVERT_SKIN_ROOT;
1323 }
1324 
1327 /* -------------------------------------------------------------------- */
1331 static void layerSwap_flnor(void *data, const int *corner_indices)
1332 {
1333  short(*flnors)[4][3] = static_cast<short(*)[4][3]>(data);
1334  short nors[4][3];
1335  int i = 4;
1336 
1337  while (i--) {
1338  copy_v3_v3_short(nors[i], (*flnors)[corner_indices[i]]);
1339  }
1340 
1341  memcpy(flnors, nors, sizeof(nors));
1342 }
1343 
1346 /* -------------------------------------------------------------------- */
1350 static void layerDefault_fmap(void *data, int count)
1351 {
1352  int *fmap_num = (int *)data;
1353  for (int i = 0; i < count; i++) {
1354  fmap_num[i] = -1;
1355  }
1356 }
1357 
1360 /* -------------------------------------------------------------------- */
1364 static void layerCopyValue_propcol(const void *source,
1365  void *dest,
1366  const int mixmode,
1367  const float mixfactor)
1368 {
1369  const MPropCol *m1 = static_cast<const MPropCol *>(source);
1370  MPropCol *m2 = static_cast<MPropCol *>(dest);
1371  float tmp_col[4];
1372 
1373  if (ELEM(mixmode,
1374  CDT_MIX_NOMIX,
1377  /* Modes that do a full copy or nothing. */
1379  /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
1380  const float f = (m2->color[0] + m2->color[1] + m2->color[2]) / 3.0f;
1381  if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
1382  return; /* Do Nothing! */
1383  }
1384  if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
1385  return; /* Do Nothing! */
1386  }
1387  }
1388  copy_v4_v4(m2->color, m1->color);
1389  }
1390  else { /* Modes that support 'real' mix factor. */
1391  if (mixmode == CDT_MIX_MIX) {
1392  blend_color_mix_float(tmp_col, m2->color, m1->color);
1393  }
1394  else if (mixmode == CDT_MIX_ADD) {
1395  blend_color_add_float(tmp_col, m2->color, m1->color);
1396  }
1397  else if (mixmode == CDT_MIX_SUB) {
1398  blend_color_sub_float(tmp_col, m2->color, m1->color);
1399  }
1400  else if (mixmode == CDT_MIX_MUL) {
1401  blend_color_mul_float(tmp_col, m2->color, m1->color);
1402  }
1403  else {
1404  memcpy(tmp_col, m1->color, sizeof(tmp_col));
1405  }
1406  blend_color_interpolate_float(m2->color, m2->color, tmp_col, mixfactor);
1407 
1408  copy_v4_v4(m2->color, m1->color);
1409  }
1410 }
1411 
1412 static bool layerEqual_propcol(const void *data1, const void *data2)
1413 {
1414  const MPropCol *m1 = static_cast<const MPropCol *>(data1);
1415  const MPropCol *m2 = static_cast<const MPropCol *>(data2);
1416  float tot = 0;
1417 
1418  for (int i = 0; i < 4; i++) {
1419  float c = (m1->color[i] - m2->color[i]);
1420  tot += c * c;
1421  }
1422 
1423  return tot < 0.001f;
1424 }
1425 
1426 static void layerMultiply_propcol(void *data, float fac)
1427 {
1428  MPropCol *m = static_cast<MPropCol *>(data);
1429  mul_v4_fl(m->color, fac);
1430 }
1431 
1432 static void layerAdd_propcol(void *data1, const void *data2)
1433 {
1434  MPropCol *m = static_cast<MPropCol *>(data1);
1435  const MPropCol *m2 = static_cast<const MPropCol *>(data2);
1436  add_v4_v4(m->color, m2->color);
1437 }
1438 
1439 static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
1440 {
1441  const MPropCol *m = static_cast<const MPropCol *>(data);
1442  MPropCol *min = static_cast<MPropCol *>(vmin);
1443  MPropCol *max = static_cast<MPropCol *>(vmax);
1444  minmax_v4v4_v4(min->color, max->color, m->color);
1445 }
1446 
1447 static void layerInitMinMax_propcol(void *vmin, void *vmax)
1448 {
1449  MPropCol *min = static_cast<MPropCol *>(vmin);
1450  MPropCol *max = static_cast<MPropCol *>(vmax);
1451 
1452  copy_v4_fl(min->color, FLT_MAX);
1453  copy_v4_fl(max->color, FLT_MIN);
1454 }
1455 
1456 static void layerDefault_propcol(void *data, int count)
1457 {
1458  /* Default to white, full alpha. */
1459  MPropCol default_propcol = {{1.0f, 1.0f, 1.0f, 1.0f}};
1460  MPropCol *pcol = (MPropCol *)data;
1461  for (int i = 0; i < count; i++) {
1462  copy_v4_v4(pcol[i].color, default_propcol.color);
1463  }
1464 }
1465 
1466 static void layerInterp_propcol(const void **sources,
1467  const float *weights,
1468  const float *UNUSED(sub_weights),
1469  int count,
1470  void *dest)
1471 {
1472  MPropCol *mc = static_cast<MPropCol *>(dest);
1473  float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1474  for (int i = 0; i < count; i++) {
1475  const float interp_weight = weights[i];
1476  const MPropCol *src = static_cast<const MPropCol *>(sources[i]);
1477  madd_v4_v4fl(col, src->color, interp_weight);
1478  }
1479  copy_v4_v4(mc->color, col);
1480 }
1481 
1484 /* -------------------------------------------------------------------- */
1488 static void layerInterp_propfloat3(const void **sources,
1489  const float *weights,
1490  const float *UNUSED(sub_weights),
1491  int count,
1492  void *dest)
1493 {
1494  vec3f result = {0.0f, 0.0f, 0.0f};
1495  for (int i = 0; i < count; i++) {
1496  const float interp_weight = weights[i];
1497  const vec3f *src = static_cast<const vec3f *>(sources[i]);
1498  madd_v3_v3fl(&result.x, &src->x, interp_weight);
1499  }
1500  copy_v3_v3((float *)dest, &result.x);
1501 }
1502 
1503 static void layerMultiply_propfloat3(void *data, float fac)
1504 {
1505  vec3f *vec = static_cast<vec3f *>(data);
1506  vec->x *= fac;
1507  vec->y *= fac;
1508  vec->z *= fac;
1509 }
1510 
1511 static void layerAdd_propfloat3(void *data1, const void *data2)
1512 {
1513  vec3f *vec1 = static_cast<vec3f *>(data1);
1514  const vec3f *vec2 = static_cast<const vec3f *>(data2);
1515  vec1->x += vec2->x;
1516  vec1->y += vec2->y;
1517  vec1->z += vec2->z;
1518 }
1519 
1520 static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
1521 {
1522  float *values = static_cast<float *>(data);
1523  bool has_errors = false;
1524  for (int i = 0; i < totitems * 3; i++) {
1525  if (!isfinite(values[i])) {
1526  if (do_fixes) {
1527  values[i] = 0.0f;
1528  }
1529  has_errors = true;
1530  }
1531  }
1532  return has_errors;
1533 }
1534 
1537 /* -------------------------------------------------------------------- */
1541 static void layerInterp_propfloat2(const void **sources,
1542  const float *weights,
1543  const float *UNUSED(sub_weights),
1544  int count,
1545  void *dest)
1546 {
1547  vec2f result = {0.0f, 0.0f};
1548  for (int i = 0; i < count; i++) {
1549  const float interp_weight = weights[i];
1550  const vec2f *src = static_cast<const vec2f *>(sources[i]);
1551  madd_v2_v2fl(&result.x, &src->x, interp_weight);
1552  }
1553  copy_v2_v2((float *)dest, &result.x);
1554 }
1555 
1556 static void layerMultiply_propfloat2(void *data, float fac)
1557 {
1558  vec2f *vec = static_cast<vec2f *>(data);
1559  vec->x *= fac;
1560  vec->y *= fac;
1561 }
1562 
1563 static void layerAdd_propfloat2(void *data1, const void *data2)
1564 {
1565  vec2f *vec1 = static_cast<vec2f *>(data1);
1566  const vec2f *vec2 = static_cast<const vec2f *>(data2);
1567  vec1->x += vec2->x;
1568  vec1->y += vec2->y;
1569 }
1570 
1571 static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
1572 {
1573  float *values = static_cast<float *>(data);
1574  bool has_errors = false;
1575  for (int i = 0; i < totitems * 2; i++) {
1576  if (!isfinite(values[i])) {
1577  if (do_fixes) {
1578  values[i] = 0.0f;
1579  }
1580  has_errors = true;
1581  }
1582  }
1583  return has_errors;
1584 }
1585 
1588 /* -------------------------------------------------------------------- */
1592 static void layerInterp_propbool(const void **sources,
1593  const float *weights,
1594  const float *UNUSED(sub_weights),
1595  int count,
1596  void *dest)
1597 {
1598  bool result = false;
1599  for (int i = 0; i < count; i++) {
1600  const float interp_weight = weights[i];
1601  const bool src = *(const bool *)sources[i];
1602  result |= src && (interp_weight > 0.0f);
1603  }
1604  *(bool *)dest = result;
1605 }
1606 
1608  /* 0: CD_MVERT */
1609  {sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1610  /* 1: CD_MSTICKY */ /* DEPRECATED */
1611  {sizeof(float[2]), "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1612  /* 2: CD_MDEFORMVERT */
1613  {sizeof(MDeformVert),
1614  "MDeformVert",
1615  1,
1616  nullptr,
1620  nullptr,
1621  nullptr},
1622  /* 3: CD_MEDGE */
1623  {sizeof(MEdge), "MEdge", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1624  /* 4: CD_MFACE */
1625  {sizeof(MFace), "MFace", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1626  /* 5: CD_MTFACE */
1627  {sizeof(MTFace), "MTFace", 1,
1628  N_("UVMap"), layerCopy_tface, nullptr,
1630  nullptr, nullptr, nullptr,
1631  nullptr, nullptr, nullptr,
1632  nullptr, nullptr, nullptr,
1633  nullptr, layerMaxNum_tface},
1634  /* 6: CD_MCOL */
1635  /* 4 MCol structs per face */
1636  {sizeof(MCol[4]), "MCol", 4,
1637  N_("Col"), nullptr, nullptr,
1639  nullptr, nullptr, nullptr,
1640  nullptr, nullptr, nullptr,
1641  nullptr, nullptr, nullptr,
1642  nullptr, nullptr},
1643  /* 7: CD_ORIGINDEX */
1644  {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_origindex},
1645  /* 8: CD_NORMAL */
1646  /* 3 floats per normal vector */
1647  {sizeof(float[3]),
1648  "vec3f",
1649  1,
1650  nullptr,
1651  nullptr,
1652  nullptr,
1654  nullptr,
1655  nullptr,
1656  nullptr,
1657  nullptr,
1658  nullptr,
1659  nullptr,
1660  nullptr,
1661  nullptr,
1663  /* 9: CD_FACEMAP */
1664  {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_fmap, nullptr},
1665  /* 10: CD_PROP_FLOAT */
1666  {sizeof(MFloatProperty),
1667  "MFloatProperty",
1668  1,
1669  N_("Float"),
1671  nullptr,
1673  nullptr,
1674  nullptr,
1676  /* 11: CD_PROP_INT32 */
1677  {sizeof(MIntProperty),
1678  "MIntProperty",
1679  1,
1680  N_("Int"),
1682  nullptr,
1684  nullptr},
1685  /* 12: CD_PROP_STRING */
1686  {sizeof(MStringProperty),
1687  "MStringProperty",
1688  1,
1689  N_("String"),
1691  nullptr,
1692  nullptr,
1693  nullptr},
1694  /* 13: CD_ORIGSPACE */
1695  {sizeof(OrigSpaceFace),
1696  "OrigSpaceFace",
1697  1,
1698  N_("UVMap"),
1700  nullptr,
1704  /* 14: CD_ORCO */
1705  {sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1706  /* 15: CD_MTEXPOLY */ /* DEPRECATED */
1707  /* NOTE: when we expose the UV Map / TexFace split to the user,
1708  * change this back to face Texture. */
1709  {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1710  /* 16: CD_MLOOPUV */
1711  {sizeof(MLoopUV),
1712  "MLoopUV",
1713  1,
1714  N_("UVMap"),
1715  nullptr,
1716  nullptr,
1718  nullptr,
1719  nullptr,
1727  nullptr,
1728  nullptr,
1729  nullptr,
1731  /* 17: CD_PROP_BYTE_COLOR */
1732  {sizeof(MLoopCol),
1733  "MLoopCol",
1734  1,
1735  N_("Col"),
1736  nullptr,
1737  nullptr,
1739  nullptr,
1741  nullptr,
1748  nullptr,
1749  nullptr,
1750  nullptr,
1751  nullptr},
1752  /* 18: CD_TANGENT */
1753  {sizeof(float[4][4]), "", 0, N_("Tangent"), nullptr, nullptr, nullptr, nullptr, nullptr},
1754  /* 19: CD_MDISPS */
1755  {sizeof(MDisps),
1756  "MDisps",
1757  1,
1758  nullptr,
1761  nullptr,
1763  nullptr,
1764  nullptr,
1765  nullptr,
1766  nullptr,
1767  nullptr,
1768  nullptr,
1769  nullptr,
1770  nullptr,
1774  /* 20: CD_PREVIEW_MCOL */
1775  {sizeof(MCol[4]),
1776  "MCol",
1777  4,
1778  N_("PreviewCol"),
1779  nullptr,
1780  nullptr,
1784  /* 21: CD_ID_MCOL */ /* DEPRECATED */
1785  {sizeof(MCol[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1786  /* 22: CD_TEXTURE_MCOL */
1787  {sizeof(MCol[4]),
1788  "MCol",
1789  4,
1790  N_("TexturedCol"),
1791  nullptr,
1792  nullptr,
1796  /* 23: CD_CLOTH_ORCO */
1797  {sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1798  /* 24: CD_RECAST */
1799  {sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr},
1800  /* 25: CD_MPOLY */
1801  {sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr},
1802  /* 26: CD_MLOOP */
1803  {sizeof(MLoop),
1804  "MLoop",
1805  1,
1806  N_("NGon Face-Vertex"),
1807  nullptr,
1808  nullptr,
1809  nullptr,
1810  nullptr,
1811  nullptr},
1812  /* 27: CD_SHAPE_KEYINDEX */
1813  {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1814  /* 28: CD_SHAPEKEY */
1815  {sizeof(float[3]), "", 0, N_("ShapeKey"), nullptr, nullptr, layerInterp_shapekey},
1816  /* 29: CD_BWEIGHT */
1817  {sizeof(float), "", 0, N_("BevelWeight"), nullptr, nullptr, layerInterp_bweight},
1818  /* 30: CD_CREASE */
1819  /* NOTE: we do not interpolate crease data as it should be either inherited for subdivided
1820  * edges, or for vertex creases, only present on the original vertex. */
1821  {sizeof(float), "", 0, N_("SubSurfCrease"), nullptr, nullptr, nullptr},
1822  /* 31: CD_ORIGSPACE_MLOOP */
1823  {sizeof(OrigSpaceLoop),
1824  "OrigSpaceLoop",
1825  1,
1826  N_("OS Loop"),
1827  nullptr,
1828  nullptr,
1830  nullptr,
1831  nullptr,
1832  nullptr,
1839  /* 32: CD_PREVIEW_MLOOPCOL */
1840  {sizeof(MLoopCol),
1841  "MLoopCol",
1842  1,
1843  N_("PreviewLoopCol"),
1844  nullptr,
1845  nullptr,
1847  nullptr,
1849  nullptr,
1856  /* 33: CD_BM_ELEM_PYPTR */
1857  {sizeof(void *),
1858  "",
1859  1,
1860  nullptr,
1863  nullptr,
1864  nullptr,
1865  nullptr},
1866  /* 34: CD_PAINT_MASK */
1867  {sizeof(float), "", 0, nullptr, nullptr, nullptr, layerInterp_paint_mask, nullptr, nullptr},
1868  /* 35: CD_GRID_PAINT_MASK */
1869  {sizeof(GridPaintMask),
1870  "GridPaintMask",
1871  1,
1872  nullptr,
1875  nullptr,
1876  nullptr,
1877  nullptr},
1878  /* 36: CD_MVERT_SKIN */
1879  {sizeof(MVertSkin),
1880  "MVertSkin",
1881  1,
1882  nullptr,
1884  nullptr,
1886  nullptr,
1888  /* 37: CD_FREESTYLE_EDGE */
1889  {sizeof(FreestyleEdge),
1890  "FreestyleEdge",
1891  1,
1892  nullptr,
1893  nullptr,
1894  nullptr,
1895  nullptr,
1896  nullptr,
1897  nullptr},
1898  /* 38: CD_FREESTYLE_FACE */
1899  {sizeof(FreestyleFace),
1900  "FreestyleFace",
1901  1,
1902  nullptr,
1903  nullptr,
1904  nullptr,
1905  nullptr,
1906  nullptr,
1907  nullptr},
1908  /* 39: CD_MLOOPTANGENT */
1909  {sizeof(float[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1910  /* 40: CD_TESSLOOPNORMAL */
1911  {sizeof(short[4][3]), "", 0, nullptr, nullptr, nullptr, nullptr, layerSwap_flnor, nullptr},
1912  /* 41: CD_CUSTOMLOOPNORMAL */
1913  {sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1914  /* 42: CD_SCULPT_FACE_SETS */
1915  {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1916  /* 43: CD_LOCATION */
1917  {sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1918  /* 44: CD_RADIUS */
1919  {sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1920  /* 45: CD_PROP_INT8 */
1921  {sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
1922  /* 46: CD_HAIRMAPPING */ /* UNUSED */
1923  {-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1924  /* 47: CD_PROP_COLOR */
1925  {sizeof(MPropCol),
1926  "MPropCol",
1927  1,
1928  N_("Color"),
1929  nullptr,
1930  nullptr,
1932  nullptr,
1934  nullptr,
1941  nullptr,
1942  nullptr,
1943  nullptr,
1944  nullptr},
1945  /* 48: CD_PROP_FLOAT3 */
1946  {sizeof(float[3]),
1947  "vec3f",
1948  1,
1949  N_("Float3"),
1950  nullptr,
1951  nullptr,
1953  nullptr,
1954  nullptr,
1956  nullptr,
1958  nullptr,
1960  /* 49: CD_PROP_FLOAT2 */
1961  {sizeof(float[2]),
1962  "vec2f",
1963  1,
1964  N_("Float2"),
1965  nullptr,
1966  nullptr,
1968  nullptr,
1969  nullptr,
1971  nullptr,
1973  nullptr,
1975  /* 50: CD_PROP_BOOL */
1976  {sizeof(bool),
1977  "bool",
1978  1,
1979  N_("Boolean"),
1980  nullptr,
1981  nullptr,
1983  nullptr,
1984  nullptr,
1985  nullptr,
1986  nullptr,
1987  nullptr,
1988  nullptr,
1989  nullptr},
1990  /* 51: CD_HAIRLENGTH */
1991  {sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
1992 };
1993 
1994 static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
1995  /* 0-4 */ "CDMVert",
1996  "CDMSticky",
1997  "CDMDeformVert",
1998  "CDMEdge",
1999  "CDMFace",
2000  /* 5-9 */ "CDMTFace",
2001  "CDMCol",
2002  "CDOrigIndex",
2003  "CDNormal",
2004  "CDFaceMap",
2005  /* 10-14 */ "CDMFloatProperty",
2006  "CDMIntProperty",
2007  "CDMStringProperty",
2008  "CDOrigSpace",
2009  "CDOrco",
2010  /* 15-19 */ "CDMTexPoly",
2011  "CDMLoopUV",
2012  "CDMloopCol",
2013  "CDTangent",
2014  "CDMDisps",
2015  /* 20-24 */ "CDPreviewMCol",
2016  "CDIDMCol",
2017  "CDTextureMCol",
2018  "CDClothOrco",
2019  "CDMRecast",
2020 
2021  /* BMESH ONLY */
2022  /* 25-29 */ "CDMPoly",
2023  "CDMLoop",
2024  "CDShapeKeyIndex",
2025  "CDShapeKey",
2026  "CDBevelWeight",
2027  /* 30-34 */ "CDSubSurfCrease",
2028  "CDOrigSpaceLoop",
2029  "CDPreviewLoopCol",
2030  "CDBMElemPyPtr",
2031  "CDPaintMask",
2032  /* 35-36 */ "CDGridPaintMask",
2033  "CDMVertSkin",
2034  /* 37-38 */ "CDFreestyleEdge",
2035  "CDFreestyleFace",
2036  /* 39-42 */ "CDMLoopTangent",
2037  "CDTessLoopNormal",
2038  "CDCustomLoopNormal",
2039  "CDSculptFaceGroups",
2040  /* 43-46 */ "CDHairPoint",
2041  "CDPropInt8",
2042  "CDHairMapping",
2043  "CDPoint",
2044  "CDPropCol",
2045  "CDPropFloat3",
2046  "CDPropFloat2",
2047  "CDPropBoolean",
2048  "CDHairLength",
2049 };
2050 
2052  /* vmask */ CD_MASK_MVERT | CD_MASK_BWEIGHT,
2053  /* emask */ CD_MASK_MEDGE | CD_MASK_BWEIGHT,
2054  /* fmask */ 0,
2055  /* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP,
2056  /* lmask */ CD_MASK_MLOOP,
2057 };
2061  /* fmask */ 0,
2063  /* lmask */ CD_MASK_MLOOP,
2064 };
2069  /* fmask */ 0,
2070  /* pmask */
2073  /* lmask */
2076 };
2080  CD_MASK_CREASE),
2083  /* pmask */
2086  /* lmask */
2088  CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
2089 };
2094  /* fmask */ 0,
2095  /* pmask */
2097  /* lmask */
2100 };
2106  /* emask */
2109  /* fmask */
2113  /* pmask */
2116  /* lmask */
2120 };
2121 
2123 {
2124  if (type < 0 || type >= CD_NUMTYPES) {
2125  return nullptr;
2126  }
2127 
2128  return &LAYERTYPEINFO[type];
2129 }
2130 
2131 static const char *layerType_getName(int type)
2132 {
2133  if (type < 0 || type >= CD_NUMTYPES) {
2134  return nullptr;
2135  }
2136 
2137  return LAYERTYPENAMES[type];
2138 }
2139 
2141 {
2142  printf("verts mask=0x%" PRIx64 ":\n", mask->vmask);
2143  for (int i = 0; i < CD_NUMTYPES; i++) {
2144  if (mask->vmask & CD_TYPE_AS_MASK(i)) {
2145  printf(" %s\n", layerType_getName(i));
2146  }
2147  }
2148 
2149  printf("edges mask=0x%" PRIx64 ":\n", mask->emask);
2150  for (int i = 0; i < CD_NUMTYPES; i++) {
2151  if (mask->emask & CD_TYPE_AS_MASK(i)) {
2152  printf(" %s\n", layerType_getName(i));
2153  }
2154  }
2155 
2156  printf("faces mask=0x%" PRIx64 ":\n", mask->fmask);
2157  for (int i = 0; i < CD_NUMTYPES; i++) {
2158  if (mask->fmask & CD_TYPE_AS_MASK(i)) {
2159  printf(" %s\n", layerType_getName(i));
2160  }
2161  }
2162 
2163  printf("loops mask=0x%" PRIx64 ":\n", mask->lmask);
2164  for (int i = 0; i < CD_NUMTYPES; i++) {
2165  if (mask->lmask & CD_TYPE_AS_MASK(i)) {
2166  printf(" %s\n", layerType_getName(i));
2167  }
2168  }
2169 
2170  printf("polys mask=0x%" PRIx64 ":\n", mask->pmask);
2171  for (int i = 0; i < CD_NUMTYPES; i++) {
2172  if (mask->pmask & CD_TYPE_AS_MASK(i)) {
2173  printf(" %s\n", layerType_getName(i));
2174  }
2175  }
2176 }
2177 
2180 /* -------------------------------------------------------------------- */
2185 
2187  int type,
2188  eCDAllocType alloctype,
2189  void *layerdata,
2190  int totelem,
2191  const char *name);
2192 
2194 {
2195  int lasttype = -1;
2196 
2197  for (int i = 0; i < CD_NUMTYPES; i++) {
2198  data->typemap[i] = -1;
2199  }
2200 
2201  for (int i = 0; i < data->totlayer; i++) {
2202  const int type = data->layers[i].type;
2203  if (type != lasttype) {
2204  data->typemap[type] = i;
2205  lasttype = type;
2206  }
2207  }
2208 }
2209 
2210 /* currently only used in BLI_assert */
2211 #ifndef NDEBUG
2213 {
2214  CustomData data_copy = *data;
2215  CustomData_update_typemap(&data_copy);
2216  return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0);
2217 }
2218 #endif
2219 
2220 bool CustomData_merge(const CustomData *source,
2221  CustomData *dest,
2223  eCDAllocType alloctype,
2224  int totelem)
2225 {
2226  // const LayerTypeInfo *typeInfo;
2227  CustomDataLayer *layer, *newlayer;
2228  int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
2229  int number = 0, maxnumber = -1;
2230  bool changed = false;
2231 
2232  for (int i = 0; i < source->totlayer; i++) {
2233  layer = &source->layers[i];
2234  // typeInfo = layerType_getInfo(layer->type); /* UNUSED */
2235 
2236  int type = layer->type;
2237  int flag = layer->flag;
2238 
2239  if (type != lasttype) {
2240  number = 0;
2242  lastactive = layer->active;
2243  lastrender = layer->active_rnd;
2244  lastclone = layer->active_clone;
2245  lastmask = layer->active_mask;
2246  lasttype = type;
2247  }
2248  else {
2249  number++;
2250  }
2251 
2252  if (flag & CD_FLAG_NOCOPY) {
2253  continue;
2254  }
2255  if (!(mask & CD_TYPE_AS_MASK(type))) {
2256  continue;
2257  }
2258  if ((maxnumber != -1) && (number >= maxnumber)) {
2259  continue;
2260  }
2261  if (CustomData_get_named_layer_index(dest, type, layer->name) != -1) {
2262  continue;
2263  }
2264 
2265  void *data;
2266  switch (alloctype) {
2267  case CD_ASSIGN:
2268  case CD_REFERENCE:
2269  case CD_DUPLICATE:
2270  data = layer->data;
2271  break;
2272  default:
2273  data = nullptr;
2274  break;
2275  }
2276 
2277  if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
2278  newlayer = customData_add_layer__internal(
2279  dest, type, CD_REFERENCE, data, totelem, layer->name);
2280  }
2281  else {
2282  newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
2283  }
2284 
2285  if (newlayer) {
2286  newlayer->uid = layer->uid;
2287 
2288  newlayer->active = lastactive;
2289  newlayer->active_rnd = lastrender;
2290  newlayer->active_clone = lastclone;
2291  newlayer->active_mask = lastmask;
2292  newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY | CD_FLAG_COLOR_ACTIVE |
2294  changed = true;
2295 
2296  if (layer->anonymous_id != nullptr) {
2298  newlayer->anonymous_id = layer->anonymous_id;
2299  }
2300  }
2301  }
2302 
2304  return changed;
2305 }
2306 
2308 {
2309  BLI_assert(totelem >= 0);
2310  for (int i = 0; i < data->totlayer; i++) {
2311  CustomDataLayer *layer = &data->layers[i];
2312  const LayerTypeInfo *typeInfo;
2313  if (layer->flag & CD_FLAG_NOFREE) {
2314  continue;
2315  }
2316  typeInfo = layerType_getInfo(layer->type);
2317  /* Use calloc to avoid the need to manually initialize new data in layers.
2318  * Useful for types like #MDeformVert which contain a pointer. */
2319  layer->data = MEM_recallocN(layer->data, (size_t)totelem * typeInfo->size);
2320  }
2321 }
2322 
2323 void CustomData_copy(const CustomData *source,
2324  CustomData *dest,
2326  eCDAllocType alloctype,
2327  int totelem)
2328 {
2330 
2331  if (source->external) {
2332  dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
2333  }
2334 
2335  CustomData_merge(source, dest, mask, alloctype, totelem);
2336 }
2337 
2338 static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
2339 {
2340  const LayerTypeInfo *typeInfo;
2341 
2342  if (layer->anonymous_id != nullptr) {
2344  layer->anonymous_id = nullptr;
2345  }
2346  if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
2347  typeInfo = layerType_getInfo(layer->type);
2348 
2349  if (typeInfo->free) {
2350  typeInfo->free(layer->data, totelem, typeInfo->size);
2351  }
2352 
2353  if (layer->data) {
2354  MEM_freeN(layer->data);
2355  }
2356  }
2357 }
2358 
2360 {
2361  if (data->external) {
2362  MEM_freeN(data->external);
2363  data->external = nullptr;
2364  }
2365 }
2366 
2368 {
2369  memset(data, 0, sizeof(*data));
2370  copy_vn_i(data->typemap, CD_NUMTYPES, -1);
2371 }
2372 
2373 void CustomData_free(CustomData *data, int totelem)
2374 {
2375  for (int i = 0; i < data->totlayer; i++) {
2376  customData_free_layer__internal(&data->layers[i], totelem);
2377  }
2378 
2379  if (data->layers) {
2380  MEM_freeN(data->layers);
2381  }
2382 
2385 }
2386 
2388 {
2389  for (int i = 0; i < data->totlayer; i++) {
2390  CustomDataLayer *layer = &data->layers[i];
2391  if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
2392  continue;
2393  }
2394  customData_free_layer__internal(layer, totelem);
2395  }
2396 
2397  if (data->layers) {
2398  MEM_freeN(data->layers);
2399  }
2400 
2403 }
2404 
2406 {
2407  const LayerTypeInfo *typeInfo;
2408  int offset = 0;
2409 
2410  for (int i = 0; i < data->totlayer; i++) {
2411  typeInfo = layerType_getInfo(data->layers[i].type);
2412 
2413  data->layers[i].offset = offset;
2414  offset += typeInfo->size;
2415  }
2416 
2417  data->totsize = offset;
2419 }
2420 
2421 /* to use when we're in the middle of modifying layers */
2423 {
2424  for (int i = 0; i < data->totlayer; i++) {
2425  if (data->layers[i].type == type) {
2426  return i;
2427  }
2428  }
2429 
2430  return -1;
2431 }
2432 
2433 /* -------------------------------------------------------------------- */
2434 /* index values to access the layers (offset from the layer start) */
2435 
2437 {
2439  return data->typemap[type];
2440 }
2441 
2443 {
2444  BLI_assert(n >= 0);
2446 
2447  if (i != -1) {
2448  BLI_assert(i + n < data->totlayer);
2449  i = (data->layers[i + n].type == type) ? (i + n) : (-1);
2450  }
2451 
2452  return i;
2453 }
2454 
2455 int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
2456 {
2457  for (int i = 0; i < data->totlayer; i++) {
2458  if (data->layers[i].type == type) {
2459  if (STREQ(data->layers[i].name, name)) {
2460  return i;
2461  }
2462  }
2463  }
2464 
2465  return -1;
2466 }
2467 
2469 {
2470  const int layer_index = data->typemap[type];
2472  return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1;
2473 }
2474 
2476 {
2477  const int layer_index = data->typemap[type];
2479  return (layer_index != -1) ? layer_index + data->layers[layer_index].active_rnd : -1;
2480 }
2481 
2483 {
2484  const int layer_index = data->typemap[type];
2486  return (layer_index != -1) ? layer_index + data->layers[layer_index].active_clone : -1;
2487 }
2488 
2490 {
2491  const int layer_index = data->typemap[type];
2493  return (layer_index != -1) ? layer_index + data->layers[layer_index].active_mask : -1;
2494 }
2495 
2496 /* -------------------------------------------------------------------- */
2497 /* index values per layer type */
2498 
2499 int CustomData_get_named_layer(const CustomData *data, int type, const char *name)
2500 {
2501  const int named_index = CustomData_get_named_layer_index(data, type, name);
2502  const int layer_index = data->typemap[type];
2504  return (named_index != -1) ? named_index - layer_index : -1;
2505 }
2506 
2508 {
2509  const int layer_index = data->typemap[type];
2511  return (layer_index != -1) ? data->layers[layer_index].active : -1;
2512 }
2513 
2515 {
2516  const int layer_index = data->typemap[type];
2518  return (layer_index != -1) ? data->layers[layer_index].active_rnd : -1;
2519 }
2520 
2522 {
2523  const int layer_index = data->typemap[type];
2525  return (layer_index != -1) ? data->layers[layer_index].active_clone : -1;
2526 }
2527 
2529 {
2530  const int layer_index = data->typemap[type];
2532  return (layer_index != -1) ? data->layers[layer_index].active_mask : -1;
2533 }
2534 
2536 {
2537  /* Get the layer index of the active layer of this type. */
2538  const int layer_index = CustomData_get_active_layer_index(data, type);
2539  return layer_index < 0 ? nullptr : data->layers[layer_index].name;
2540 }
2541 
2543 {
2544  for (int i = 0; i < data->totlayer; i++) {
2545  if (data->layers[i].type == type) {
2546  data->layers[i].active = n;
2547  }
2548  }
2549 }
2550 
2552 {
2553  for (int i = 0; i < data->totlayer; i++) {
2554  if (data->layers[i].type == type) {
2555  data->layers[i].active_rnd = n;
2556  }
2557  }
2558 }
2559 
2561 {
2562  for (int i = 0; i < data->totlayer; i++) {
2563  if (data->layers[i].type == type) {
2564  data->layers[i].active_clone = n;
2565  }
2566  }
2567 }
2568 
2570 {
2571  for (int i = 0; i < data->totlayer; i++) {
2572  if (data->layers[i].type == type) {
2573  data->layers[i].active_mask = n;
2574  }
2575  }
2576 }
2577 
2579 {
2580  const int layer_index = data->typemap[type];
2582 
2583  for (int i = 0; i < data->totlayer; i++) {
2584  if (data->layers[i].type == type) {
2585  data->layers[i].active = n - layer_index;
2586  }
2587  }
2588 }
2589 
2591 {
2592  const int layer_index = data->typemap[type];
2594 
2595  for (int i = 0; i < data->totlayer; i++) {
2596  if (data->layers[i].type == type) {
2597  data->layers[i].active_rnd = n - layer_index;
2598  }
2599  }
2600 }
2601 
2603 {
2604  const int layer_index = data->typemap[type];
2606 
2607  for (int i = 0; i < data->totlayer; i++) {
2608  if (data->layers[i].type == type) {
2609  data->layers[i].active_clone = n - layer_index;
2610  }
2611  }
2612 }
2613 
2615 {
2616  const int layer_index = data->typemap[type];
2618 
2619  for (int i = 0; i < data->totlayer; i++) {
2620  if (data->layers[i].type == type) {
2621  data->layers[i].active_mask = n - layer_index;
2622  }
2623  }
2624 }
2625 
2627 {
2628  for (int i = 0; i < data->totlayer; i++) {
2629  if (data->layers[i].type == type) {
2630  data->layers[i].flag |= flag;
2631  }
2632  }
2633 }
2634 
2636 {
2637  const int nflag = ~flag;
2638 
2639  for (int i = 0; i < data->totlayer; i++) {
2640  if (data->layers[i].type == type) {
2641  data->layers[i].flag &= nflag;
2642  }
2643  }
2644 }
2645 
2646 static bool customData_resize(CustomData *data, int amount)
2647 {
2648  CustomDataLayer *tmp = static_cast<CustomDataLayer *>(
2649  MEM_calloc_arrayN((data->maxlayer + amount), sizeof(*tmp), __func__));
2650  if (!tmp) {
2651  return false;
2652  }
2653 
2654  data->maxlayer += amount;
2655  if (data->layers) {
2656  memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer);
2657  MEM_freeN(data->layers);
2658  }
2659  data->layers = tmp;
2660 
2661  return true;
2662 }
2663 
2665  int type,
2666  eCDAllocType alloctype,
2667  void *layerdata,
2668  int totelem,
2669  const char *name)
2670 {
2671  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
2672  int flag = 0, index = data->totlayer;
2673  void *newlayerdata = nullptr;
2674 
2675  /* Passing a layer-data to copy from with an alloctype that won't copy is
2676  * most likely a bug */
2677  BLI_assert(!layerdata || ELEM(alloctype, CD_ASSIGN, CD_DUPLICATE, CD_REFERENCE));
2678 
2679  if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
2680  return &data->layers[CustomData_get_layer_index(data, type)];
2681  }
2682 
2683  if (ELEM(alloctype, CD_ASSIGN, CD_REFERENCE)) {
2684  newlayerdata = layerdata;
2685  }
2686  else if (totelem > 0 && typeInfo->size > 0) {
2687  if (alloctype == CD_DUPLICATE && layerdata) {
2688  newlayerdata = MEM_malloc_arrayN((size_t)totelem, typeInfo->size, layerType_getName(type));
2689  }
2690  else {
2691  newlayerdata = MEM_calloc_arrayN((size_t)totelem, typeInfo->size, layerType_getName(type));
2692  }
2693 
2694  if (!newlayerdata) {
2695  return nullptr;
2696  }
2697  }
2698 
2699  if (alloctype == CD_DUPLICATE && layerdata) {
2700  if (totelem > 0) {
2701  if (typeInfo->copy) {
2702  typeInfo->copy(layerdata, newlayerdata, totelem);
2703  }
2704  else {
2705  memcpy(newlayerdata, layerdata, (size_t)totelem * typeInfo->size);
2706  }
2707  }
2708  }
2709  else if (alloctype == CD_DEFAULT) {
2710  if (typeInfo->set_default) {
2711  typeInfo->set_default(newlayerdata, totelem);
2712  }
2713  }
2714  else if (alloctype == CD_REFERENCE) {
2715  flag |= CD_FLAG_NOFREE;
2716  }
2717 
2718  if (index >= data->maxlayer) {
2720  if (newlayerdata != layerdata) {
2721  MEM_freeN(newlayerdata);
2722  }
2723  return nullptr;
2724  }
2725  }
2726 
2727  data->totlayer++;
2728 
2729  /* keep layers ordered by type */
2730  for (; index > 0 && data->layers[index - 1].type > type; index--) {
2731  data->layers[index] = data->layers[index - 1];
2732  }
2733 
2734  /* Clear remaining data on the layer. The original data on the layer has been moved to another
2735  * index. Without this, it can happen that information from the previous layer at that index
2736  * leaks into the new layer. */
2737  memset(data->layers + index, 0, sizeof(CustomDataLayer));
2738 
2739  data->layers[index].type = type;
2740  data->layers[index].flag = flag;
2741  data->layers[index].data = newlayerdata;
2742 
2743  /* Set default name if none exists. Note we only call DATA_() once
2744  * we know there is a default name, to avoid overhead of locale lookups
2745  * in the depsgraph. */
2746  if (!name && typeInfo->defaultname) {
2747  name = DATA_(typeInfo->defaultname);
2748  }
2749 
2750  if (name) {
2751  BLI_strncpy(data->layers[index].name, name, sizeof(data->layers[index].name));
2753  }
2754  else {
2755  data->layers[index].name[0] = '\0';
2756  }
2757 
2758  if (index > 0 && data->layers[index - 1].type == type) {
2759  data->layers[index].active = data->layers[index - 1].active;
2760  data->layers[index].active_rnd = data->layers[index - 1].active_rnd;
2761  data->layers[index].active_clone = data->layers[index - 1].active_clone;
2762  data->layers[index].active_mask = data->layers[index - 1].active_mask;
2763  }
2764  else {
2765  data->layers[index].active = 0;
2766  data->layers[index].active_rnd = 0;
2767  data->layers[index].active_clone = 0;
2768  data->layers[index].active_mask = 0;
2769  }
2770 
2772 
2773  return &data->layers[index];
2774 }
2775 
2777  CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem)
2778 {
2779  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
2780 
2782  data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
2784 
2785  if (layer) {
2786  return layer->data;
2787  }
2788 
2789  return nullptr;
2790 }
2791 
2793  int type,
2794  eCDAllocType alloctype,
2795  void *layerdata,
2796  int totelem,
2797  const char *name)
2798 {
2800  data, type, alloctype, layerdata, totelem, name);
2802 
2803  if (layer) {
2804  return layer->data;
2805  }
2806 
2807  return nullptr;
2808 }
2809 
2811  int type,
2812  eCDAllocType alloctype,
2813  void *layerdata,
2814  int totelem,
2815  const AnonymousAttributeID *anonymous_id)
2816 {
2817  const char *name = BKE_anonymous_attribute_id_internal_name(anonymous_id);
2819  data, type, alloctype, layerdata, totelem, name);
2821 
2822  if (layer == nullptr) {
2823  return nullptr;
2824  }
2825 
2827  layer->anonymous_id = anonymous_id;
2828  return layer->data;
2829 }
2830 
2831 bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
2832 {
2833  const int index_first = CustomData_get_layer_index(data, type);
2834  const int n = index - index_first;
2835 
2836  BLI_assert(index >= index_first);
2837  if ((index_first == -1) || (n < 0)) {
2838  return false;
2839  }
2840  BLI_assert(data->layers[index].type == type);
2841 
2842  customData_free_layer__internal(&data->layers[index], totelem);
2843 
2844  for (int i = index + 1; i < data->totlayer; i++) {
2845  data->layers[i - 1] = data->layers[i];
2846  }
2847 
2848  data->totlayer--;
2849 
2850  /* if layer was last of type in array, set new active layer */
2852 
2853  if (i != -1) {
2854  /* don't decrement zero index */
2855  const int index_nonzero = n ? n : 1;
2856  CustomDataLayer *layer;
2857 
2858  for (layer = &data->layers[i]; i < data->totlayer && layer->type == type; i++, layer++) {
2859  if (layer->active >= index_nonzero) {
2860  layer->active--;
2861  }
2862  if (layer->active_rnd >= index_nonzero) {
2863  layer->active_rnd--;
2864  }
2865  if (layer->active_clone >= index_nonzero) {
2866  layer->active_clone--;
2867  }
2868  if (layer->active_mask >= index_nonzero) {
2869  layer->active_mask--;
2870  }
2871  }
2872  }
2873 
2874  if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
2876  }
2877 
2879 
2880  return true;
2881 }
2882 
2883 bool CustomData_free_layer_named(CustomData *data, const char *name, const int totelem)
2884 {
2885  for (const int i : IndexRange(data->totlayer)) {
2886  const CustomDataLayer &layer = data->layers[i];
2887  if (StringRef(layer.name) == name) {
2888  CustomData_free_layer(data, layer.type, totelem, i);
2889  return true;
2890  }
2891  }
2892  return false;
2893 }
2894 
2896 {
2897  const int index = CustomData_get_active_layer_index(data, type);
2898  if (index == -1) {
2899  return false;
2900  }
2901  return CustomData_free_layer(data, type, totelem, index);
2902 }
2903 
2904 void CustomData_free_layers(CustomData *data, int type, int totelem)
2905 {
2906  const int index = CustomData_get_layer_index(data, type);
2907  while (CustomData_free_layer(data, type, totelem, index)) {
2908  /* pass */
2909  }
2910 }
2911 
2913 {
2914  return (CustomData_get_layer_index(data, type) != -1);
2915 }
2916 
2918 {
2919  int number = 0;
2920 
2921  for (int i = 0; i < data->totlayer; i++) {
2922  if (data->layers[i].type == type) {
2923  number++;
2924  }
2925  }
2926 
2927  return number;
2928 }
2929 
2931 {
2932  int number = 0;
2933 
2934  for (int i = 0; i < data->totlayer; i++) {
2935  if (mask & CD_TYPE_AS_MASK(data->layers[i].type)) {
2936  number++;
2937  }
2938  }
2939 
2940  return number;
2941 }
2942 
2944  const int layer_index,
2945  const int totelem)
2946 {
2947  if (layer_index == -1) {
2948  return nullptr;
2949  }
2950 
2951  CustomDataLayer *layer = &data->layers[layer_index];
2952 
2953  if (layer->flag & CD_FLAG_NOFREE) {
2954  /* MEM_dupallocN won't work in case of complex layers, like e.g.
2955  * CD_MDEFORMVERT, which has pointers to allocated data...
2956  * So in case a custom copy function is defined, use it!
2957  */
2958  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
2959 
2960  if (typeInfo->copy) {
2961  void *dst_data = MEM_malloc_arrayN(
2962  (size_t)totelem, typeInfo->size, "CD duplicate ref layer");
2963  typeInfo->copy(layer->data, dst_data, totelem);
2964  layer->data = dst_data;
2965  }
2966  else {
2967  layer->data = MEM_dupallocN(layer->data);
2968  }
2969 
2970  layer->flag &= ~CD_FLAG_NOFREE;
2971  }
2972 
2973  return layer->data;
2974 }
2975 
2976 void *CustomData_duplicate_referenced_layer(CustomData *data, const int type, const int totelem)
2977 {
2978  /* get the layer index of the first layer of type */
2979  int layer_index = CustomData_get_active_layer_index(data, type);
2980 
2981  return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
2982 }
2983 
2985  const int type,
2986  const int n,
2987  const int totelem)
2988 {
2989  /* get the layer index of the desired layer */
2990  int layer_index = CustomData_get_layer_index_n(data, type, n);
2991 
2992  return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
2993 }
2994 
2996  const int type,
2997  const char *name,
2998  const int totelem)
2999 {
3000  /* get the layer index of the desired layer */
3001  int layer_index = CustomData_get_named_layer_index(data, type, name);
3002 
3003  return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
3004 }
3005 
3007  const int UNUSED(type),
3008  const AnonymousAttributeID *anonymous_id,
3009  const int totelem)
3010 {
3011  for (int i = 0; i < data->totlayer; i++) {
3012  if (data->layers[i].anonymous_id == anonymous_id) {
3014  }
3015  }
3017  return nullptr;
3018 }
3019 
3021 {
3022  for (int i = 0; i < data->totlayer; i++) {
3023  CustomDataLayer *layer = &data->layers[i];
3025  }
3026 }
3027 
3029 {
3030  /* get the layer index of the first layer of type */
3031  int layer_index = CustomData_get_active_layer_index(data, type);
3032  if (layer_index == -1) {
3033  return false;
3034  }
3035 
3036  CustomDataLayer *layer = &data->layers[layer_index];
3037 
3038  return (layer->flag & CD_FLAG_NOFREE) != 0;
3039 }
3040 
3042 {
3043  int i, j;
3044  bool changed = false;
3045  for (i = 0, j = 0; i < data->totlayer; i++) {
3046  CustomDataLayer *layer = &data->layers[i];
3047 
3048  if (i != j) {
3049  data->layers[j] = data->layers[i];
3050  }
3051 
3052  if ((layer->flag & CD_FLAG_TEMPORARY) == CD_FLAG_TEMPORARY) {
3053  customData_free_layer__internal(layer, totelem);
3054  changed = true;
3055  }
3056  else {
3057  j++;
3058  }
3059  }
3060 
3061  data->totlayer = j;
3062 
3063  if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
3065  changed = true;
3066  }
3067 
3068  if (changed) {
3070  }
3071 }
3072 
3074 {
3075  for (int i = 0; i < data->totlayer; i++) {
3076  if (!(mask & CD_TYPE_AS_MASK(data->layers[i].type))) {
3077  data->layers[i].flag |= CD_FLAG_NOCOPY;
3078  }
3079  }
3080 }
3081 
3082 void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
3083 {
3084  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3085 
3086  if (typeInfo->copy) {
3087  typeInfo->copy(src_data_ofs, dst_data_ofs, count);
3088  }
3089  else {
3090  memcpy(dst_data_ofs, src_data_ofs, (size_t)count * typeInfo->size);
3091  }
3092 }
3093 
3095  CustomData *dest,
3096  int src_layer_index,
3097  int dst_layer_index,
3098  int src_index,
3099  int dst_index,
3100  int count)
3101 {
3102  const LayerTypeInfo *typeInfo;
3103 
3104  const void *src_data = source->layers[src_layer_index].data;
3105  void *dst_data = dest->layers[dst_layer_index].data;
3106 
3107  typeInfo = layerType_getInfo(source->layers[src_layer_index].type);
3108 
3109  const size_t src_offset = (size_t)src_index * typeInfo->size;
3110  const size_t dst_offset = (size_t)dst_index * typeInfo->size;
3111 
3112  if (!count || !src_data || !dst_data) {
3113  if (count && !(src_data == nullptr && dst_data == nullptr)) {
3114  CLOG_WARN(&LOG,
3115  "null data for %s type (%p --> %p), skipping",
3116  layerType_getName(source->layers[src_layer_index].type),
3117  (void *)src_data,
3118  (void *)dst_data);
3119  }
3120  return;
3121  }
3122 
3123  if (typeInfo->copy) {
3124  typeInfo->copy(
3125  POINTER_OFFSET(src_data, src_offset), POINTER_OFFSET(dst_data, dst_offset), count);
3126  }
3127  else {
3128  memcpy(POINTER_OFFSET(dst_data, dst_offset),
3129  POINTER_OFFSET(src_data, src_offset),
3130  (size_t)count * typeInfo->size);
3131  }
3132 }
3133 
3135  const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
3136 {
3137  /* copies a layer at a time */
3138  for (int src_i = 0; src_i < source->totlayer; src_i++) {
3139 
3140  int dest_i = CustomData_get_named_layer_index(
3141  dest, source->layers[src_i].type, source->layers[src_i].name);
3142 
3143  /* if we found a matching layer, copy the data */
3144  if (dest_i != -1) {
3145  CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
3146  }
3147  }
3148 }
3149 
3151  const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
3152 {
3153  /* copies a layer at a time */
3154  int dest_i = 0;
3155  for (int src_i = 0; src_i < source->totlayer; src_i++) {
3156 
3157  /* find the first dest layer with type >= the source type
3158  * (this should work because layers are ordered by type)
3159  */
3160  while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
3161  dest_i++;
3162  }
3163 
3164  /* if there are no more dest layers, we're done */
3165  if (dest_i >= dest->totlayer) {
3166  return;
3167  }
3168 
3169  /* if we found a matching layer, copy the data */
3170  if (dest->layers[dest_i].type == source->layers[src_i].type) {
3171  CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
3172 
3173  /* if there are multiple source & dest layers of the same type,
3174  * we don't want to copy all source layers to the same dest, so
3175  * increment dest_i
3176  */
3177  dest_i++;
3178  }
3179  }
3180 }
3181 
3183  CustomData *destination,
3184  int type,
3185  int source_index,
3186  int destination_index,
3187  int count)
3188 {
3189  const int source_layer_index = CustomData_get_layer_index(source, type);
3190  if (source_layer_index == -1) {
3191  return;
3192  }
3193  const int destinaiton_layer_index = CustomData_get_layer_index(destination, type);
3194  if (destinaiton_layer_index == -1) {
3195  return;
3196  }
3198  destination,
3199  source_layer_index,
3200  destinaiton_layer_index,
3201  source_index,
3202  destination_index,
3203  count);
3204 }
3205 
3207 {
3208  for (int i = 0; i < data->totlayer; i++) {
3209  if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
3210  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3211 
3212  if (typeInfo->free) {
3213  size_t offset = (size_t)index * typeInfo->size;
3214 
3215  typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
3216  }
3217  }
3218  }
3219 }
3220 
3221 #define SOURCE_BUF_SIZE 100
3222 
3223 void CustomData_interp(const CustomData *source,
3224  CustomData *dest,
3225  const int *src_indices,
3226  const float *weights,
3227  const float *sub_weights,
3228  int count,
3229  int dest_index)
3230 {
3231  if (count <= 0) {
3232  return;
3233  }
3234 
3235  const void *source_buf[SOURCE_BUF_SIZE];
3236  const void **sources = source_buf;
3237 
3238  /* Slow fallback in case we're interpolating a ridiculous number of elements. */
3239  if (count > SOURCE_BUF_SIZE) {
3240  sources = static_cast<const void **>(MEM_malloc_arrayN(count, sizeof(*sources), __func__));
3241  }
3242 
3243  /* If no weights are given, generate default ones to produce an average result. */
3244  float default_weights_buf[SOURCE_BUF_SIZE];
3245  float *default_weights = nullptr;
3246  if (weights == nullptr) {
3247  default_weights = (count > SOURCE_BUF_SIZE) ?
3248  static_cast<float *>(
3249  MEM_mallocN(sizeof(*weights) * (size_t)count, __func__)) :
3250  default_weights_buf;
3251  copy_vn_fl(default_weights, count, 1.0f / count);
3252  weights = default_weights;
3253  }
3254 
3255  /* interpolates a layer at a time */
3256  int dest_i = 0;
3257  for (int src_i = 0; src_i < source->totlayer; src_i++) {
3258  const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
3259  if (!typeInfo->interp) {
3260  continue;
3261  }
3262 
3263  /* find the first dest layer with type >= the source type
3264  * (this should work because layers are ordered by type)
3265  */
3266  while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
3267  dest_i++;
3268  }
3269 
3270  /* if there are no more dest layers, we're done */
3271  if (dest_i >= dest->totlayer) {
3272  break;
3273  }
3274 
3275  /* if we found a matching layer, copy the data */
3276  if (dest->layers[dest_i].type == source->layers[src_i].type) {
3277  void *src_data = source->layers[src_i].data;
3278 
3279  for (int j = 0; j < count; j++) {
3280  sources[j] = POINTER_OFFSET(src_data, (size_t)src_indices[j] * typeInfo->size);
3281  }
3282 
3283  typeInfo->interp(
3284  sources,
3285  weights,
3286  sub_weights,
3287  count,
3288  POINTER_OFFSET(dest->layers[dest_i].data, (size_t)dest_index * typeInfo->size));
3289 
3290  /* if there are multiple source & dest layers of the same type,
3291  * we don't want to copy all source layers to the same dest, so
3292  * increment dest_i
3293  */
3294  dest_i++;
3295  }
3296  }
3297 
3298  if (count > SOURCE_BUF_SIZE) {
3299  MEM_freeN((void *)sources);
3300  }
3301  if (!ELEM(default_weights, nullptr, default_weights_buf)) {
3302  MEM_freeN(default_weights);
3303  }
3304 }
3305 
3306 void CustomData_swap_corners(CustomData *data, int index, const int *corner_indices)
3307 {
3308  for (int i = 0; i < data->totlayer; i++) {
3309  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3310 
3311  if (typeInfo->swap) {
3312  const size_t offset = (size_t)index * typeInfo->size;
3313 
3314  typeInfo->swap(POINTER_OFFSET(data->layers[i].data, offset), corner_indices);
3315  }
3316  }
3317 }
3318 
3319 void CustomData_swap(CustomData *data, const int index_a, const int index_b)
3320 {
3321  char buff_static[256];
3322 
3323  if (index_a == index_b) {
3324  return;
3325  }
3326 
3327  for (int i = 0; i < data->totlayer; i++) {
3328  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3329  const size_t size = typeInfo->size;
3330  const size_t offset_a = size * index_a;
3331  const size_t offset_b = size * index_b;
3332 
3333  void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__);
3334  memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size);
3335  memcpy(POINTER_OFFSET(data->layers[i].data, offset_a),
3336  POINTER_OFFSET(data->layers[i].data, offset_b),
3337  size);
3338  memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size);
3339 
3340  if (buff != buff_static) {
3341  MEM_freeN(buff);
3342  }
3343  }
3344 }
3345 
3346 void *CustomData_get(const CustomData *data, int index, int type)
3347 {
3348  BLI_assert(index >= 0);
3349 
3350  /* get the layer index of the active layer of type */
3351  int layer_index = CustomData_get_active_layer_index(data, type);
3352  if (layer_index == -1) {
3353  return nullptr;
3354  }
3355 
3356  /* get the offset of the desired element */
3357  const size_t offset = (size_t)index * layerType_getInfo(type)->size;
3358 
3359  return POINTER_OFFSET(data->layers[layer_index].data, offset);
3360 }
3361 
3362 void *CustomData_get_n(const CustomData *data, int type, int index, int n)
3363 {
3364  BLI_assert(index >= 0 && n >= 0);
3365 
3366  /* get the layer index of the first layer of type */
3367  int layer_index = data->typemap[type];
3368  if (layer_index == -1) {
3369  return nullptr;
3370  }
3371 
3372  const size_t offset = (size_t)index * layerType_getInfo(type)->size;
3373  return POINTER_OFFSET(data->layers[layer_index + n].data, offset);
3374 }
3375 
3377 {
3378  /* get the layer index of the active layer of type */
3379  int layer_index = CustomData_get_active_layer_index(data, type);
3380  if (layer_index == -1) {
3381  return nullptr;
3382  }
3383 
3384  return data->layers[layer_index].data;
3385 }
3386 
3387 void *CustomData_get_layer_n(const CustomData *data, int type, int n)
3388 {
3389  /* get the layer index of the active layer of type */
3390  int layer_index = CustomData_get_layer_index_n(data, type, n);
3391  if (layer_index == -1) {
3392  return nullptr;
3393  }
3394 
3395  return data->layers[layer_index].data;
3396 }
3397 
3398 void *CustomData_get_layer_named(const CustomData *data, int type, const char *name)
3399 {
3400  int layer_index = CustomData_get_named_layer_index(data, type, name);
3401  if (layer_index == -1) {
3402  return nullptr;
3403  }
3404 
3405  return data->layers[layer_index].data;
3406 }
3407 
3409 {
3410  /* get the layer index of the active layer of type */
3411  int layer_index = CustomData_get_active_layer_index(data, type);
3412  if (layer_index == -1) {
3413  return -1;
3414  }
3415 
3416  return data->layers[layer_index].offset;
3417 }
3418 
3419 int CustomData_get_offset_named(const CustomData *data, int type, const char *name)
3420 {
3421  /* get the layer index of the active layer of type */
3422  int layer_index = CustomData_get_named_layer_index(data, type, name);
3423  if (layer_index == -1) {
3424  return -1;
3425  }
3426 
3427  return data->layers[layer_index].offset;
3428 }
3429 
3431 {
3432  /* get the layer index of the active layer of type */
3433  int layer_index = CustomData_get_layer_index_n(data, type, n);
3434  if (layer_index == -1) {
3435  return -1;
3436  }
3437 
3438  return data->layers[layer_index].offset;
3439 }
3440 
3441 bool CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
3442 {
3443  /* get the layer index of the first layer of type */
3444  const int layer_index = CustomData_get_layer_index_n(data, type, n);
3445 
3446  if ((layer_index == -1) || !name) {
3447  return false;
3448  }
3449 
3450  BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
3451 
3452  return true;
3453 }
3454 
3455 const char *CustomData_get_layer_name(const CustomData *data, int type, int n)
3456 {
3457  const int layer_index = CustomData_get_layer_index_n(data, type, n);
3458 
3459  return (layer_index == -1) ? nullptr : data->layers[layer_index].name;
3460 }
3461 
3462 void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
3463 {
3464  /* get the layer index of the first layer of type */
3465  int layer_index = CustomData_get_active_layer_index(data, type);
3466 
3467  if (layer_index == -1) {
3468  return nullptr;
3469  }
3470 
3471  data->layers[layer_index].data = ptr;
3472 
3473  return ptr;
3474 }
3475 
3476 void *CustomData_set_layer_n(const CustomData *data, int type, int n, void *ptr)
3477 {
3478  /* get the layer index of the first layer of type */
3479  int layer_index = CustomData_get_layer_index_n(data, type, n);
3480  if (layer_index == -1) {
3481  return nullptr;
3482  }
3483 
3484  data->layers[layer_index].data = ptr;
3485 
3486  return ptr;
3487 }
3488 
3489 void CustomData_set(const CustomData *data, int index, int type, const void *source)
3490 {
3491  void *dest = CustomData_get(data, index, type);
3492  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3493 
3494  if (!dest) {
3495  return;
3496  }
3497 
3498  if (typeInfo->copy) {
3499  typeInfo->copy(source, dest, 1);
3500  }
3501  else {
3502  memcpy(dest, source, typeInfo->size);
3503  }
3504 }
3505 
3506 /* BMesh functions */
3507 
3509 {
3510  int act;
3511 
3512  if (CustomData_has_layer(ldata, CD_MLOOPUV)) {
3515 
3518 
3519  act = CustomData_get_clone_layer(ldata, CD_MLOOPUV);
3521 
3524  }
3525 
3528  CustomData_set_layer_active(fdata, CD_MCOL, act);
3529 
3531  CustomData_set_layer_render(fdata, CD_MCOL, act);
3532 
3534  CustomData_set_layer_clone(fdata, CD_MCOL, act);
3535 
3538  }
3539 }
3540 
3541 void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype)
3542 {
3543  int chunksize;
3544 
3545  /* Dispose old pools before calling here to avoid leaks */
3546  BLI_assert(data->pool == nullptr);
3547 
3548  switch (htype) {
3549  case BM_VERT:
3550  chunksize = bm_mesh_chunksize_default.totvert;
3551  break;
3552  case BM_EDGE:
3553  chunksize = bm_mesh_chunksize_default.totedge;
3554  break;
3555  case BM_LOOP:
3556  chunksize = bm_mesh_chunksize_default.totloop;
3557  break;
3558  case BM_FACE:
3559  chunksize = bm_mesh_chunksize_default.totface;
3560  break;
3561  default:
3563  chunksize = 512;
3564  break;
3565  }
3566 
3567  /* If there are no layers, no pool is needed just yet */
3568  if (data->totlayer) {
3569  data->pool = BLI_mempool_create(data->totsize, totelem, chunksize, BLI_MEMPOOL_NOP);
3570  }
3571 }
3572 
3574  CustomData *dest,
3576  eCDAllocType alloctype,
3577  BMesh *bm,
3578  const char htype)
3579 {
3580 
3581  if (CustomData_number_of_layers_typemask(source, mask) == 0) {
3582  return false;
3583  }
3584 
3585  /* copy old layer description so that old data can be copied into
3586  * the new allocation */
3587  CustomData destold = *dest;
3588  if (destold.layers) {
3589  destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
3590  }
3591 
3592  if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
3593  if (destold.layers) {
3594  MEM_freeN(destold.layers);
3595  }
3596  return false;
3597  }
3598 
3599  int iter_type;
3600  int totelem;
3601  switch (htype) {
3602  case BM_VERT:
3603  iter_type = BM_VERTS_OF_MESH;
3604  totelem = bm->totvert;
3605  break;
3606  case BM_EDGE:
3607  iter_type = BM_EDGES_OF_MESH;
3608  totelem = bm->totedge;
3609  break;
3610  case BM_LOOP:
3611  iter_type = BM_LOOPS_OF_FACE;
3612  totelem = bm->totloop;
3613  break;
3614  case BM_FACE:
3615  iter_type = BM_FACES_OF_MESH;
3616  totelem = bm->totface;
3617  break;
3618  default: /* should never happen */
3619  BLI_assert_msg(0, "invalid type given");
3620  iter_type = BM_VERTS_OF_MESH;
3621  totelem = bm->totvert;
3622  break;
3623  }
3624 
3625  dest->pool = nullptr;
3626  CustomData_bmesh_init_pool(dest, totelem, htype);
3627 
3628  if (iter_type != BM_LOOPS_OF_FACE) {
3629  BMHeader *h;
3630  BMIter iter;
3631  /* Ensure all current elements follow new customdata layout. */
3632  BM_ITER_MESH (h, &iter, bm, iter_type) {
3633  void *tmp = nullptr;
3634  CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
3635  CustomData_bmesh_free_block(&destold, &h->data);
3636  h->data = tmp;
3637  }
3638  }
3639  else {
3640  BMFace *f;
3641  BMLoop *l;
3642  BMIter iter;
3643  BMIter liter;
3644 
3645  /* Ensure all current elements follow new customdata layout. */
3646  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3647  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
3648  void *tmp = nullptr;
3649  CustomData_bmesh_copy_data(&destold, dest, l->head.data, &tmp);
3650  CustomData_bmesh_free_block(&destold, &l->head.data);
3651  l->head.data = tmp;
3652  }
3653  }
3654  }
3655 
3656  if (destold.pool) {
3657  BLI_mempool_destroy(destold.pool);
3658  }
3659  if (destold.layers) {
3660  MEM_freeN(destold.layers);
3661  }
3662  return true;
3663 }
3664 
3666 {
3667  if (*block == nullptr) {
3668  return;
3669  }
3670 
3671  for (int i = 0; i < data->totlayer; i++) {
3672  if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
3673  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3674 
3675  if (typeInfo->free) {
3676  int offset = data->layers[i].offset;
3677  typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
3678  }
3679  }
3680  }
3681 
3682  if (data->totsize) {
3683  BLI_mempool_free(data->pool, *block);
3684  }
3685 
3686  *block = nullptr;
3687 }
3688 
3690 {
3691  if (block == nullptr) {
3692  return;
3693  }
3694  for (int i = 0; i < data->totlayer; i++) {
3695  if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
3696  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3697  if (typeInfo->free) {
3698  const size_t offset = data->layers[i].offset;
3699  typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
3700  }
3701  }
3702  }
3703  if (data->totsize) {
3704  memset(block, 0, data->totsize);
3705  }
3706 }
3707 
3708 static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
3709 {
3710  if (*block) {
3712  }
3713 
3714  if (data->totsize > 0) {
3715  *block = BLI_mempool_alloc(data->pool);
3716  }
3717  else {
3718  *block = nullptr;
3719  }
3720 }
3721 
3723  void *block,
3724  const eCustomDataMask mask_exclude)
3725 {
3726  if (block == nullptr) {
3727  return;
3728  }
3729  for (int i = 0; i < data->totlayer; i++) {
3730  if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
3731  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3732  const size_t offset = data->layers[i].offset;
3733  if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
3734  if (typeInfo->free) {
3735  typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
3736  }
3737  }
3738  memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
3739  }
3740  }
3741 }
3742 
3743 static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
3744 {
3745  int offset = data->layers[n].offset;
3746  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
3747 
3748  if (typeInfo->set_default) {
3749  typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
3750  }
3751  else {
3752  memset(POINTER_OFFSET(*block, offset), 0, typeInfo->size);
3753  }
3754 }
3755 
3757 {
3758  if (*block == nullptr) {
3760  }
3761 
3762  for (int i = 0; i < data->totlayer; i++) {
3764  }
3765 }
3766 
3768  CustomData *dest,
3769  void *src_block,
3770  void **dest_block,
3771  const eCustomDataMask mask_exclude)
3772 {
3773  /* Note that having a version of this function without a 'mask_exclude'
3774  * would cause too much duplicate code, so add a check instead. */
3775  const bool no_mask = (mask_exclude == 0);
3776 
3777  if (*dest_block == nullptr) {
3778  CustomData_bmesh_alloc_block(dest, dest_block);
3779  if (*dest_block) {
3780  memset(*dest_block, 0, dest->totsize);
3781  }
3782  }
3783 
3784  /* copies a layer at a time */
3785  int dest_i = 0;
3786  for (int src_i = 0; src_i < source->totlayer; src_i++) {
3787 
3788  /* find the first dest layer with type >= the source type
3789  * (this should work because layers are ordered by type)
3790  */
3791  while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
3792  CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
3793  dest_i++;
3794  }
3795 
3796  /* if there are no more dest layers, we're done */
3797  if (dest_i >= dest->totlayer) {
3798  return;
3799  }
3800 
3801  /* if we found a matching layer, copy the data */
3802  if (dest->layers[dest_i].type == source->layers[src_i].type &&
3803  STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
3804  if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
3805  const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
3806  void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
3807  const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
3808  if (typeInfo->copy) {
3809  typeInfo->copy(src_data, dest_data, 1);
3810  }
3811  else {
3812  memcpy(dest_data, src_data, typeInfo->size);
3813  }
3814  }
3815 
3816  /* if there are multiple source & dest layers of the same type,
3817  * we don't want to copy all source layers to the same dest, so
3818  * increment dest_i
3819  */
3820  dest_i++;
3821  }
3822  }
3823 
3824  while (dest_i < dest->totlayer) {
3825  CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
3826  dest_i++;
3827  }
3828 }
3829 
3831  CustomData *dest,
3832  void *src_block,
3833  void **dest_block)
3834 {
3835  CustomData_bmesh_copy_data_exclude_by_type(source, dest, src_block, dest_block, 0);
3836 }
3837 
3838 void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
3839 {
3840  /* get the layer index of the first layer of type */
3841  int layer_index = CustomData_get_active_layer_index(data, type);
3842  if (layer_index == -1) {
3843  return nullptr;
3844  }
3845 
3846  return POINTER_OFFSET(block, data->layers[layer_index].offset);
3847 }
3848 
3849 void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
3850 {
3851  /* get the layer index of the first layer of type */
3852  int layer_index = CustomData_get_layer_index(data, type);
3853  if (layer_index == -1) {
3854  return nullptr;
3855  }
3856 
3857  return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
3858 }
3859 
3860 void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
3861 {
3862  if (n < 0 || n >= data->totlayer) {
3863  return nullptr;
3864  }
3865 
3866  return POINTER_OFFSET(block, data->layers[n].offset);
3867 }
3868 
3869 bool CustomData_layer_has_math(const CustomData *data, int layer_n)
3870 {
3871  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type);
3872 
3873  if (typeInfo->equal && typeInfo->add && typeInfo->multiply && typeInfo->initminmax &&
3874  typeInfo->dominmax) {
3875  return true;
3876  }
3877 
3878  return false;
3879 }
3880 
3882 {
3883  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type);
3884 
3885  if (typeInfo->interp) {
3886  return true;
3887  }
3888 
3889  return false;
3890 }
3891 
3893 {
3894  /* interpolates a layer at a time */
3895  for (int i = 0; i < data->totlayer; i++) {
3896  if (CustomData_layer_has_math(data, i)) {
3897  return true;
3898  }
3899  }
3900 
3901  return false;
3902 }
3903 
3905 {
3906  for (int i = 0; i < data->totlayer; i++) {
3907  if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
3908  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
3909  if (typeInfo->free) {
3910  return true;
3911  }
3912  }
3913  }
3914  return false;
3915 }
3916 
3918 {
3919  /* interpolates a layer at a time */
3920  for (int i = 0; i < data->totlayer; i++) {
3922  return true;
3923  }
3924  }
3925 
3926  return false;
3927 }
3928 
3930 {
3931  for (int i = 0; i < data->totlayer; i++) {
3932  if (data->layers[i].flag & CD_FLAG_NOFREE) {
3933  return true;
3934  }
3935  }
3936  return false;
3937 }
3938 
3939 void CustomData_data_copy_value(int type, const void *source, void *dest)
3940 {
3941  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3942 
3943  if (!dest) {
3944  return;
3945  }
3946 
3947  if (typeInfo->copyvalue) {
3948  typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f);
3949  }
3950  else {
3951  memcpy(dest, source, typeInfo->size);
3952  }
3953 }
3954 
3956  int type, const void *source, void *dest, const int mixmode, const float mixfactor)
3957 {
3958  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3959 
3960  if (!dest) {
3961  return;
3962  }
3963 
3964  if (typeInfo->copyvalue) {
3965  typeInfo->copyvalue(source, dest, mixmode, mixfactor);
3966  }
3967  else {
3968  /* Mere copy if no advanced interpolation is supported. */
3969  memcpy(dest, source, typeInfo->size);
3970  }
3971 }
3972 
3973 bool CustomData_data_equals(int type, const void *data1, const void *data2)
3974 {
3975  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3976 
3977  if (typeInfo->equal) {
3978  return typeInfo->equal(data1, data2);
3979  }
3980 
3981  return !memcmp(data1, data2, typeInfo->size);
3982 }
3983 
3984 void CustomData_data_initminmax(int type, void *min, void *max)
3985 {
3986  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3987 
3988  if (typeInfo->initminmax) {
3989  typeInfo->initminmax(min, max);
3990  }
3991 }
3992 
3993 void CustomData_data_dominmax(int type, const void *data, void *min, void *max)
3994 {
3995  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
3996 
3997  if (typeInfo->dominmax) {
3998  typeInfo->dominmax(data, min, max);
3999  }
4000 }
4001 
4002 void CustomData_data_multiply(int type, void *data, float fac)
4003 {
4004  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4005 
4006  if (typeInfo->multiply) {
4007  typeInfo->multiply(data, fac);
4008  }
4009 }
4010 
4011 void CustomData_data_add(int type, void *data1, const void *data2)
4012 {
4013  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4014 
4015  if (typeInfo->add) {
4016  typeInfo->add(data1, data2);
4017  }
4018 }
4019 
4020 void CustomData_bmesh_set(const CustomData *data, void *block, int type, const void *source)
4021 {
4022  void *dest = CustomData_bmesh_get(data, block, type);
4023  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4024 
4025  if (!dest) {
4026  return;
4027  }
4028 
4029  if (typeInfo->copy) {
4030  typeInfo->copy(source, dest, 1);
4031  }
4032  else {
4033  memcpy(dest, source, typeInfo->size);
4034  }
4035 }
4036 
4037 void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, const void *source)
4038 {
4039  void *dest = CustomData_bmesh_get_n(data, block, type, n);
4040  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4041 
4042  if (!dest) {
4043  return;
4044  }
4045 
4046  if (typeInfo->copy) {
4047  typeInfo->copy(source, dest, 1);
4048  }
4049  else {
4050  memcpy(dest, source, typeInfo->size);
4051  }
4052 }
4053 
4054 void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, const void *source)
4055 {
4056  void *dest = CustomData_bmesh_get_layer_n(data, block, n);
4057  const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
4058 
4059  if (!dest) {
4060  return;
4061  }
4062 
4063  if (typeInfo->copy) {
4064  typeInfo->copy(source, dest, 1);
4065  }
4066  else {
4067  memcpy(dest, source, typeInfo->size);
4068  }
4069 }
4070 
4072  const void **src_blocks_ofs,
4073  const float *weights,
4074  const float *sub_weights,
4075  int count,
4076  void *dst_block_ofs,
4077  int n)
4078 {
4079  BLI_assert(weights != nullptr);
4080  BLI_assert(count > 0);
4081 
4082  CustomDataLayer *layer = &data->layers[n];
4083  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4084 
4085  typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
4086 }
4087 
4089  const void **src_blocks,
4090  const float *weights,
4091  const float *sub_weights,
4092  int count,
4093  void *dst_block)
4094 {
4095  if (count <= 0) {
4096  return;
4097  }
4098 
4099  void *source_buf[SOURCE_BUF_SIZE];
4100  const void **sources = (const void **)source_buf;
4101 
4102  /* Slow fallback in case we're interpolating a ridiculous number of elements. */
4103  if (count > SOURCE_BUF_SIZE) {
4104  sources = (const void **)MEM_malloc_arrayN(count, sizeof(*sources), __func__);
4105  }
4106 
4107  /* If no weights are given, generate default ones to produce an average result. */
4108  float default_weights_buf[SOURCE_BUF_SIZE];
4109  float *default_weights = nullptr;
4110  if (weights == nullptr) {
4111  default_weights = (count > SOURCE_BUF_SIZE) ?
4112  (float *)MEM_mallocN(sizeof(*weights) * (size_t)count, __func__) :
4113  default_weights_buf;
4114  copy_vn_fl(default_weights, count, 1.0f / count);
4115  weights = default_weights;
4116  }
4117 
4118  /* interpolates a layer at a time */
4119  for (int i = 0; i < data->totlayer; i++) {
4120  CustomDataLayer *layer = &data->layers[i];
4121  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4122  if (typeInfo->interp) {
4123  for (int j = 0; j < count; j++) {
4124  sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
4125  }
4127  data, sources, weights, sub_weights, count, POINTER_OFFSET(dst_block, layer->offset), i);
4128  }
4129  }
4130 
4131  if (count > SOURCE_BUF_SIZE) {
4132  MEM_freeN((void *)sources);
4133  }
4134  if (!ELEM(default_weights, nullptr, default_weights_buf)) {
4135  MEM_freeN(default_weights);
4136  }
4137 }
4138 
4140  CustomData *dest,
4141  int src_index,
4142  void **dest_block,
4143  bool use_default_init)
4144 {
4145  if (*dest_block == nullptr) {
4146  CustomData_bmesh_alloc_block(dest, dest_block);
4147  }
4148 
4149  /* copies a layer at a time */
4150  int dest_i = 0;
4151  for (int src_i = 0; src_i < source->totlayer; src_i++) {
4152 
4153  /* find the first dest layer with type >= the source type
4154  * (this should work because layers are ordered by type)
4155  */
4156  while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
4157  if (use_default_init) {
4158  CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
4159  }
4160  dest_i++;
4161  }
4162 
4163  /* if there are no more dest layers, we're done */
4164  if (dest_i >= dest->totlayer) {
4165  break;
4166  }
4167 
4168  /* if we found a matching layer, copy the data */
4169  if (dest->layers[dest_i].type == source->layers[src_i].type) {
4170  int offset = dest->layers[dest_i].offset;
4171  const void *src_data = source->layers[src_i].data;
4172  void *dest_data = POINTER_OFFSET(*dest_block, offset);
4173 
4174  const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
4175  const size_t src_offset = (size_t)src_index * typeInfo->size;
4176 
4177  if (typeInfo->copy) {
4178  typeInfo->copy(POINTER_OFFSET(src_data, src_offset), dest_data, 1);
4179  }
4180  else {
4181  memcpy(dest_data, POINTER_OFFSET(src_data, src_offset), typeInfo->size);
4182  }
4183 
4184  /* if there are multiple source & dest layers of the same type,
4185  * we don't want to copy all source layers to the same dest, so
4186  * increment dest_i
4187  */
4188  dest_i++;
4189  }
4190  }
4191 
4192  if (use_default_init) {
4193  while (dest_i < dest->totlayer) {
4194  CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
4195  dest_i++;
4196  }
4197  }
4198 }
4199 
4201  CustomData *dest,
4202  void *src_block,
4203  int dest_index)
4204 {
4205  /* copies a layer at a time */
4206  int dest_i = 0;
4207  for (int src_i = 0; src_i < source->totlayer; src_i++) {
4208 
4209  /* find the first dest layer with type >= the source type
4210  * (this should work because layers are ordered by type)
4211  */
4212  while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
4213  dest_i++;
4214  }
4215 
4216  /* if there are no more dest layers, we're done */
4217  if (dest_i >= dest->totlayer) {
4218  return;
4219  }
4220 
4221  /* if we found a matching layer, copy the data */
4222  if (dest->layers[dest_i].type == source->layers[src_i].type) {
4223  const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
4224  int offset = source->layers[src_i].offset;
4225  const void *src_data = POINTER_OFFSET(src_block, offset);
4226  void *dst_data = POINTER_OFFSET(dest->layers[dest_i].data,
4227  (size_t)dest_index * typeInfo->size);
4228 
4229  if (typeInfo->copy) {
4230  typeInfo->copy(src_data, dst_data, 1);
4231  }
4232  else {
4233  memcpy(dst_data, src_data, typeInfo->size);
4234  }
4235 
4236  /* if there are multiple source & dest layers of the same type,
4237  * we don't want to copy all source layers to the same dest, so
4238  * increment dest_i
4239  */
4240  dest_i++;
4241  }
4242  }
4243 }
4244 
4245 void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num)
4246 {
4247  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4248 
4249  *r_struct_name = typeInfo->structname;
4250  *r_struct_num = typeInfo->structnum;
4251 }
4252 
4254 {
4255  for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
4256  if (layer.flag & CD_FLAG_NOCOPY) {
4257  continue;
4258  }
4259  if (layer.anonymous_id != nullptr) {
4260  continue;
4261  }
4262  layers_to_write.append(layer);
4263  }
4264  data.totlayer = layers_to_write.size();
4265  data.maxlayer = data.totlayer;
4266 }
4267 
4269 {
4270  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4271 
4272  return typeInfo->size;
4273 }
4274 
4276 {
4277  return layerType_getName(type);
4278 }
4279 
4281 {
4282  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4283  return typeInfo->defaultname == nullptr;
4284 }
4285 
4287 {
4288  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4289 
4290  return (typeInfo->free != nullptr);
4291 }
4292 
4294 {
4295  const LayerTypeInfo *typeInfo = layerType_getInfo(type);
4296 
4297  /* Same test as for singleton above. */
4298  if (typeInfo->defaultname == nullptr) {
4299  return 1;
4300  }
4301  if (typeInfo->layers_max == nullptr) {
4302  return -1;
4303  }
4304 
4305  return typeInfo->layers_max();
4306 }
4307 
4308 static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
4309 {
4310  /* see if there is a duplicate */
4311  for (int i = 0; i < data->totlayer; i++) {
4312  if (i != index) {
4313  CustomDataLayer *layer = &data->layers[i];
4314 
4316  if ((CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) && STREQ(layer->name, name)) {
4317  return true;
4318  }
4319  }
4320  else {
4321  if (i != index && layer->type == type && STREQ(layer->name, name)) {
4322  return true;
4323  }
4324  }
4325  }
4326  }
4327 
4328  return false;
4329 }
4330 
4333  int type;
4334  int index;
4335 };
4336 
4337 static bool customdata_unique_check(void *arg, const char *name)
4338 {
4339  CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg);
4340  return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
4341 }
4342 
4344 {
4345  CustomDataLayer *nlayer = &data->layers[index];
4346  const LayerTypeInfo *typeInfo = layerType_getInfo(nlayer->type);
4347 
4348  CustomDataUniqueCheckData data_arg{data, nlayer->type, index};
4349 
4350  if (!typeInfo->defaultname) {
4351  return;
4352  }
4353 
4354  /* Set default name if none specified. Note we only call DATA_() when
4355  * needed to avoid overhead of locale lookups in the depsgraph. */
4356  if (nlayer->name[0] == '\0') {
4357  STRNCPY(nlayer->name, DATA_(typeInfo->defaultname));
4358  }
4359 
4361  customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, sizeof(nlayer->name));
4362 }
4363 
4365  int type,
4366  const char *name,
4367  char *outname)
4368 {
4369  int index = -1;
4370 
4371  /* if a layer name was given, try to find that layer */
4372  if (name[0]) {
4373  index = CustomData_get_named_layer_index(data, type, name);
4374  }
4375 
4376  if (index == -1) {
4377  /* either no layer was specified, or the layer we want has been
4378  * deleted, so assign the active layer to name
4379  */
4381  BLI_strncpy(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
4382  }
4383  else {
4384  BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
4385  }
4386 }
4387 
4389 {
4390  const LayerTypeInfo *typeInfo;
4391  CustomDataLayer *layer = &data->layers[index];
4392  bool keeplayer = true;
4393 
4394  if (layer->type >= CD_NUMTYPES) {
4395  keeplayer = false; /* unknown layer type from future version */
4396  }
4397  else {
4398  typeInfo = layerType_getInfo(layer->type);
4399 
4400  if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) {
4401  keeplayer = false; /* multiple layers of which we only support one */
4402  }
4403  /* This is a preemptive fix for cases that should not happen
4404  * (layers that should not be written in .blend files),
4405  * but can happen due to bugs (see e.g. T62318).
4406  * Also for forward compatibility, in future,
4407  * we may put into `.blend` file some currently un-written data types,
4408  * this should cover that case as well.
4409  * Better to be safe here, and fix issue on the fly rather than crash... */
4410  /* 0 structnum is used in writing code to tag layer types that should not be written. */
4411  else if (typeInfo->structnum == 0 &&
4412  /* XXX Not sure why those three are exception, maybe that should be fixed? */
4413  !ELEM(layer->type,
4414  CD_PAINT_MASK,
4415  CD_FACEMAP,
4416  CD_MTEXPOLY,
4418  CD_CREASE)) {
4419  keeplayer = false;
4420  CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
4421  }
4422  }
4423 
4424  if (!keeplayer) {
4425  for (int i = index + 1; i < data->totlayer; i++) {
4426  data->layers[i - 1] = data->layers[i];
4427  }
4428  data->totlayer--;
4429  }
4430 
4431  return keeplayer;
4432 }
4433 
4435 {
4436  BLI_assert(layer);
4437  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4438  BLI_assert(typeInfo);
4439 
4440  if (layer->data || count == 0) {
4441  return false;
4442  }
4443 
4444  switch (layer->type) {
4445  /* When more instances of corrupt files are found, add them here. */
4446  case CD_PROP_BOOL: /* See T84935. */
4447  case CD_MLOOPUV: /* See T90620. */
4448  layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type));
4449  BLI_assert(layer->data);
4450  if (typeInfo->set_default) {
4451  typeInfo->set_default(layer->data, count);
4452  }
4453  return true;
4454  break;
4455 
4456  case CD_MTEXPOLY:
4457  /* TODO: Investigate multiple test failures on cycles, e.g. cycles_shadow_catcher_cpu. */
4458  break;
4459 
4460  default:
4461  /* Log an error so we can collect instances of bad files. */
4462  CLOG_WARN(&LOG, "CustomDataLayer->data is NULL for type %d.", layer->type);
4463  break;
4464  }
4465  return false;
4466 }
4467 
4468 bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
4469 {
4470  BLI_assert(layer);
4471  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4472  BLI_assert(typeInfo);
4473 
4474  if (do_fixes) {
4475  CustomData_layer_ensure_data_exists(layer, totitems);
4476  }
4477 
4478  BLI_assert((totitems == 0) || layer->data);
4479  BLI_assert(MEM_allocN_len(layer->data) >= totitems * typeInfo->size);
4480 
4481  if (typeInfo->validate != nullptr) {
4482  return typeInfo->validate(layer->data, totitems, do_fixes);
4483  }
4484 
4485  return false;
4486 }
4487 
4489 {
4490  printf("{\n");
4491 
4492  int i;
4493  const CustomDataLayer *layer;
4494  for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
4495  const char *name = CustomData_layertype_name(layer->type);
4496  const int size = CustomData_sizeof(layer->type);
4497  const char *structname;
4498  int structnum;
4499  CustomData_file_write_info(layer->type, &structname, &structnum);
4500  printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
4501  name,
4502  structname,
4503  layer->type,
4504  (const void *)layer->data,
4505  size,
4506  (int)(MEM_allocN_len(layer->data) / size));
4507  }
4508 
4509  printf("}\n");
4510 }
4511 
4514 /* -------------------------------------------------------------------- */
4518 static void customdata_external_filename(char filepath[FILE_MAX],
4519  ID *id,
4520  CustomDataExternal *external)
4521 {
4522  BLI_strncpy(filepath, external->filepath, FILE_MAX);
4523  BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(id));
4524 }
4525 
4527  ID *UNUSED(id),
4529  int totelem)
4530 {
4531  for (int i = 0; i < data->totlayer; i++) {
4532  CustomDataLayer *layer = &data->layers[i];
4533  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4534 
4535  if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4536  /* pass */
4537  }
4538  else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) {
4539  if (typeInfo->free) {
4540  typeInfo->free(layer->data, totelem, typeInfo->size);
4541  }
4542  layer->flag &= ~CD_FLAG_IN_MEMORY;
4543  }
4544  }
4545 }
4546 
4548 {
4549  CustomDataExternal *external = data->external;
4550  CustomDataLayer *layer;
4551  char filepath[FILE_MAX];
4552  int update = 0;
4553 
4554  if (!external) {
4555  return;
4556  }
4557 
4558  for (int i = 0; i < data->totlayer; i++) {
4559  layer = &data->layers[i];
4560  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4561 
4562  if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4563  /* pass */
4564  }
4565  else if (layer->flag & CD_FLAG_IN_MEMORY) {
4566  /* pass */
4567  }
4568  else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
4569  update = 1;
4570  }
4571  }
4572 
4573  if (!update) {
4574  return;
4575  }
4576 
4577  customdata_external_filename(filepath, id, external);
4578 
4580  if (!cdf_read_open(cdf, filepath)) {
4581  cdf_free(cdf);
4582  CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filepath);
4583  return;
4584  }
4585 
4586  for (int i = 0; i < data->totlayer; i++) {
4587  layer = &data->layers[i];
4588  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4589 
4590  if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4591  /* pass */
4592  }
4593  else if (layer->flag & CD_FLAG_IN_MEMORY) {
4594  /* pass */
4595  }
4596  else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
4597  CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
4598 
4599  if (blay) {
4600  if (cdf_read_layer(cdf, blay)) {
4601  if (typeInfo->read(cdf, layer->data, totelem)) {
4602  /* pass */
4603  }
4604  else {
4605  break;
4606  }
4607  layer->flag |= CD_FLAG_IN_MEMORY;
4608  }
4609  else {
4610  break;
4611  }
4612  }
4613  }
4614  }
4615 
4616  cdf_read_close(cdf);
4617  cdf_free(cdf);
4618 }
4619 
4621  CustomData *data, ID *id, eCustomDataMask mask, int totelem, int free)
4622 {
4623  CustomDataExternal *external = data->external;
4624  int update = 0;
4625  char filepath[FILE_MAX];
4626 
4627  if (!external) {
4628  return;
4629  }
4630 
4631  /* test if there is anything to write */
4632  for (int i = 0; i < data->totlayer; i++) {
4633  CustomDataLayer *layer = &data->layers[i];
4634  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4635 
4636  if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
4637  /* pass */
4638  }
4639  else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4640  update = 1;
4641  }
4642  }
4643 
4644  if (!update) {
4645  return;
4646  }
4647 
4648  /* make sure data is read before we try to write */
4649  CustomData_external_read(data, id, mask, totelem);
4650  customdata_external_filename(filepath, id, external);
4651 
4653 
4654  for (int i = 0; i < data->totlayer; i++) {
4655  CustomDataLayer *layer = &data->layers[i];
4656  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4657 
4658  if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
4659  if (layer->flag & CD_FLAG_IN_MEMORY) {
4660  cdf_layer_add(
4661  cdf, layer->type, layer->name, typeInfo->filesize(cdf, layer->data, totelem));
4662  }
4663  else {
4664  cdf_free(cdf);
4665  return; /* read failed for a layer! */
4666  }
4667  }
4668  }
4669 
4670  if (!cdf_write_open(cdf, filepath)) {
4671  CLOG_ERROR(&LOG, "Failed to open %s for writing.", filepath);
4672  cdf_free(cdf);
4673  return;
4674  }
4675 
4676  int i;
4677  for (i = 0; i < data->totlayer; i++) {
4678  CustomDataLayer *layer = &data->layers[i];
4679  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4680 
4681  if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4682  CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
4683 
4684  if (cdf_write_layer(cdf, blay)) {
4685  if (typeInfo->write(cdf, layer->data, totelem)) {
4686  /* pass */
4687  }
4688  else {
4689  break;
4690  }
4691  }
4692  else {
4693  break;
4694  }
4695  }
4696  }
4697 
4698  if (i != data->totlayer) {
4699  CLOG_ERROR(&LOG, "Failed to write data to %s.", filepath);
4700  cdf_write_close(cdf);
4701  cdf_free(cdf);
4702  return;
4703  }
4704 
4705  for (i = 0; i < data->totlayer; i++) {
4706  CustomDataLayer *layer = &data->layers[i];
4707  const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
4708 
4709  if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
4710  if (free) {
4711  if (typeInfo->free) {
4712  typeInfo->free(layer->data, totelem, typeInfo->size);
4713  }
4714  layer->flag &= ~CD_FLAG_IN_MEMORY;
4715  }
4716  }
4717  }
4718 
4719  cdf_write_close(cdf);
4720  cdf_free(cdf);
4721 }
4722 
4724  CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filepath)
4725 {
4726  CustomDataExternal *external = data->external;
4727 
4728  int layer_index = CustomData_get_active_layer_index(data, type);
4729  if (layer_index == -1) {
4730  return;
4731  }
4732 
4733  CustomDataLayer *layer = &data->layers[layer_index];
4734 
4735  if (layer->flag & CD_FLAG_EXTERNAL) {
4736  return;
4737  }
4738 
4739  if (!external) {
4740  external = MEM_cnew<CustomDataExternal>(__func__);
4741  data->external = external;
4742  }
4743  BLI_strncpy(external->filepath, filepath, sizeof(external->filepath));
4744 
4746 }
4747 
4748 void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem)
4749 {
4750  CustomDataExternal *external = data->external;
4751 
4752  int layer_index = CustomData_get_active_layer_index(data, type);
4753  if (layer_index == -1) {
4754  return;
4755  }
4756 
4757  CustomDataLayer *layer = &data->layers[layer_index];
4758 
4759  if (!external) {
4760  return;
4761  }
4762 
4763  if (layer->flag & CD_FLAG_EXTERNAL) {
4764  if (!(layer->flag & CD_FLAG_IN_MEMORY)) {
4765  CustomData_external_read(data, id, CD_TYPE_AS_MASK(layer->type), totelem);
4766  }
4767 
4768  layer->flag &= ~CD_FLAG_EXTERNAL;
4769  }
4770 }
4771 
4773 {
4774  int layer_index = CustomData_get_active_layer_index(data, type);
4775  if (layer_index == -1) {
4776  return false;
4777  }
4778 
4779  CustomDataLayer *layer = &data->layers[layer_index];
4780  return (layer->flag & CD_FLAG_EXTERNAL) != 0;
4781 }
4782 
4785 /* -------------------------------------------------------------------- */
4789 static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
4790 {
4791 #define COPY_BIT_FLAG(_type, _dst, _src, _f) \
4792  { \
4793  const _type _val = *((_type *)(_src)) & ((_type)(_f)); \
4794  *((_type *)(_dst)) &= ~((_type)(_f)); \
4795  *((_type *)(_dst)) |= _val; \
4796  } \
4797  (void)0
4798 
4799  switch (data_size) {
4800  case 1:
4801  COPY_BIT_FLAG(uint8_t, dst, src, flag);
4802  break;
4803  case 2:
4804  COPY_BIT_FLAG(uint16_t, dst, src, flag);
4805  break;
4806  case 4:
4807  COPY_BIT_FLAG(uint32_t, dst, src, flag);
4808  break;
4809  case 8:
4810  COPY_BIT_FLAG(uint64_t, dst, src, flag);
4811  break;
4812  default:
4813  // CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
4814  break;
4815  }
4816 
4817 #undef COPY_BIT_FLAG
4818 }
4819 
4820 static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
4821 {
4822  switch (data_size) {
4823  case 1:
4824  return ((*((uint8_t *)data) & ((uint8_t)flag)) != 0);
4825  case 2:
4826  return ((*((uint16_t *)data) & ((uint16_t)flag)) != 0);
4827  case 4:
4828  return ((*((uint32_t *)data) & ((uint32_t)flag)) != 0);
4829  case 8:
4830  return ((*((uint64_t *)data) & ((uint64_t)flag)) != 0);
4831  default:
4832  // CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
4833  return false;
4834  }
4835 }
4836 
4838  void *data_dst,
4839  const void **sources,
4840  const float *weights,
4841  const int count,
4842  const float mix_factor)
4843 {
4844  BLI_assert(weights != nullptr);
4845  BLI_assert(count > 0);
4846 
4847  /* Fake interpolation, we actually copy highest weighted source to dest.
4848  * Note we also handle bitflags here,
4849  * in which case we rather choose to transfer value of elements totaling
4850  * more than 0.5 of weight. */
4851  int best_src_idx = 0;
4852 
4853  const int data_type = laymap->data_type;
4854  const int mix_mode = laymap->mix_mode;
4855 
4856  size_t data_size;
4857  const uint64_t data_flag = laymap->data_flag;
4858 
4859  cd_interp interp_cd = nullptr;
4860  cd_copy copy_cd = nullptr;
4861 
4862  if (!sources) {
4863  /* Not supported here, abort. */
4864  return;
4865  }
4866 
4867  if (data_type & CD_FAKE) {
4868  data_size = laymap->data_size;
4869  }
4870  else {
4871  const LayerTypeInfo *type_info = layerType_getInfo(data_type);
4872 
4873  data_size = (size_t)type_info->size;
4874  interp_cd = type_info->interp;
4875  copy_cd = type_info->copy;
4876  }
4877 
4878  void *tmp_dst = MEM_mallocN(data_size, __func__);
4879 
4880  if (count > 1 && !interp_cd) {
4881  if (data_flag) {
4882  /* Boolean case, we can 'interpolate' in two groups,
4883  * and choose value from highest weighted group. */
4884  float tot_weight_true = 0.0f;
4885  int item_true_idx = -1, item_false_idx = -1;
4886 
4887  for (int i = 0; i < count; i++) {
4888  if (check_bit_flag(sources[i], data_size, data_flag)) {
4889  tot_weight_true += weights[i];
4890  item_true_idx = i;
4891  }
4892  else {
4893  item_false_idx = i;
4894  }
4895  }
4896  best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
4897  }
4898  else {
4899  /* We just choose highest weighted source. */
4900  float max_weight = 0.0f;
4901 
4902  for (int i = 0; i < count; i++) {
4903  if (weights[i] > max_weight) {
4904  max_weight = weights[i];
4905  best_src_idx = i;
4906  }
4907  }
4908  }
4909  }
4910 
4911  BLI_assert(best_src_idx >= 0);
4912 
4913  if (interp_cd) {
4914  interp_cd(sources, weights, nullptr, count, tmp_dst);
4915  }
4916  else if (data_flag) {
4917  copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
4918  }
4919  /* No interpolation, just copy highest weight source element's data. */
4920  else if (copy_cd) {
4921  copy_cd(sources[best_src_idx], tmp_dst, 1);
4922  }
4923  else {
4924  memcpy(tmp_dst, sources[best_src_idx], data_size);
4925  }
4926 
4927  if (data_flag) {
4928  /* Bool flags, only copy if dest data is set (resp. unset) -
4929  * only 'advanced' modes we can support here! */
4930  if (mix_factor >= 0.5f && ((mix_mode == CDT_MIX_TRANSFER) ||
4931  (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD &&
4932  check_bit_flag(data_dst, data_size, data_flag)) ||
4933  (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD &&
4934  !check_bit_flag(data_dst, data_size, data_flag)))) {
4935  copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
4936  }
4937  }
4938  else if (!(data_type & CD_FAKE)) {
4939  CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
4940  }
4941  /* Else we can do nothing by default, needs custom interp func!
4942  * Note this is here only for sake of consistency, not expected to be used much actually? */
4943  else {
4944  if (mix_factor >= 0.5f) {
4945  memcpy(data_dst, tmp_dst, data_size);
4946  }
4947  }
4948 
4949  MEM_freeN(tmp_dst);
4950 }
4951 
4953  void *data_dst,
4954  const void **sources,
4955  const float *weights,
4956  const int count,
4957  const float mix_factor)
4958 {
4959  BLI_assert(weights != nullptr);
4960  BLI_assert(count > 0);
4961 
4962  const int data_type = laymap->data_type;
4963  const int mix_mode = laymap->mix_mode;
4964 
4965  SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
4966 
4967  const LayerTypeInfo *type_info = layerType_getInfo(data_type);
4968  cd_interp interp_cd = type_info->interp;
4969 
4970  float tmp_dst[3];
4971 
4972  BLI_assert(data_type == CD_NORMAL);
4973 
4974  if (!sources) {
4975  /* Not supported here, abort. */
4976  return;
4977  }
4978 
4979  interp_cd(sources, weights, nullptr, count, tmp_dst);
4980  if (space_transform) {
4981  /* tmp_dst is in source space so far, bring it back in destination space. */
4982  BLI_space_transform_invert_normal(space_transform, tmp_dst);
4983  }
4984 
4985  CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
4986 }
4987 
4989  const CustomDataTransferLayerMap *laymap)
4990 {
4991  MeshPairRemapItem *mapit = me_remap->items;
4992  const int totelem = me_remap->items_num;
4993 
4994  const int data_type = laymap->data_type;
4995  const void *data_src = laymap->data_src;
4996  void *data_dst = laymap->data_dst;
4997 
4998  size_t data_step;
4999  size_t data_size;
5000  size_t data_offset;
5001 
5002  cd_datatransfer_interp interp = nullptr;
5003 
5004  size_t tmp_buff_size = 32;
5005  const void **tmp_data_src = nullptr;
5006 
5007  /* NOTE: null data_src may happen and be valid (see vgroups...). */
5008  if (!data_dst) {
5009  return;
5010  }
5011 
5012  if (data_src) {
5013  tmp_data_src = (const void **)MEM_malloc_arrayN(
5014  tmp_buff_size, sizeof(*tmp_data_src), __func__);
5015  }
5016 
5017  if (data_type & CD_FAKE) {
5018  data_step = laymap->elem_size;
5019  data_size = laymap->data_size;
5020  data_offset = laymap->data_offset;
5021  }
5022  else {
5023  const LayerTypeInfo *type_info = layerType_getInfo(data_type);
5024 
5025  /* NOTE: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/. */
5026  data_size = (size_t)type_info->size;
5027  data_step = laymap->elem_size ? laymap->elem_size : data_size;
5028  data_offset = laymap->data_offset;
5029  }
5030 
5032 
5033  for (int i = 0; i < totelem; i++, data_dst = POINTER_OFFSET(data_dst, data_step), mapit++) {
5034  const int sources_num = mapit->sources_num;
5035  const float mix_factor = laymap->mix_factor *
5036  (laymap->mix_weights ? laymap->mix_weights[i] : 1.0f);
5037 
5038  if (!sources_num) {
5039  /* No sources for this element, skip it. */
5040  continue;
5041  }
5042 
5043  if (tmp_data_src) {
5044  if (UNLIKELY(sources_num > tmp_buff_size)) {
5045  tmp_buff_size = (size_t)sources_num;
5046  tmp_data_src = (const void **)MEM_reallocN((void *)tmp_data_src,
5047  sizeof(*tmp_data_src) * tmp_buff_size);
5048  }
5049 
5050  for (int j = 0; j < sources_num; j++) {
5051  const size_t src_idx = (size_t)mapit->indices_src[j];
5052  tmp_data_src[j] = POINTER_OFFSET(data_src, (data_step * src_idx) + data_offset);
5053  }
5054  }
5055 
5056  interp(laymap,
5057  POINTER_OFFSET(data_dst, data_offset),
5058  tmp_data_src,
5059  mapit->weights_src,
5060  sources_num,
5061  mix_factor);
5062  }
5063 
5064  MEM_SAFE_FREE(tmp_data_src);
5065 }
5066 
5069 /* -------------------------------------------------------------------- */
5073 static void write_mdisps(BlendWriter *writer, int count, const MDisps *mdlist, int external)
5074 {
5075  if (mdlist) {
5076  BLO_write_struct_array(writer, MDisps, count, mdlist);
5077  for (int i = 0; i < count; i++) {
5078  const MDisps *md = &mdlist[i];
5079  if (md->disps) {
5080  if (!external) {
5081  BLO_write_float3_array(writer, md->totdisp, &md->disps[0][0]);
5082  }
5083  }
5084 
5085  if (md->hidden) {
5086  BLO_write_raw(writer, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
5087  }
5088  }
5089  }
5090 }
5091 
5093  int count,
5094  const GridPaintMask *grid_paint_mask)
5095 {
5096  if (grid_paint_mask) {
5097  BLO_write_struct_array(writer, GridPaintMask, count, grid_paint_mask);
5098  for (int i = 0; i < count; i++) {
5099  const GridPaintMask *gpm = &grid_paint_mask[i];
5100  if (gpm->data) {
5101  const int gridsize = BKE_ccg_gridsize(gpm->level);
5102  BLO_write_raw(writer, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
5103  }
5104  }
5105  }
5106 }
5107 
5109  CustomData *data,
5110  Span<CustomDataLayer> layers_to_write,
5111  int count,
5112  eCustomDataMask cddata_mask,
5113  ID *id)
5114 {
5115  /* write external customdata (not for undo) */
5116  if (data->external && !BLO_write_is_undo(writer)) {
5117  CustomData_external_write(data, id, cddata_mask, count, 0);
5118  }
5119 
5121  writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
5122 
5123  for (const CustomDataLayer &layer : layers_to_write) {
5124  switch (layer.type) {
5125  case CD_MDEFORMVERT:
5126  BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
5127  break;
5128  case CD_MDISPS:
5129  write_mdisps(
5130  writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
5131  break;
5132  case CD_PAINT_MASK:
5133  BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
5134  break;
5135  case CD_SCULPT_FACE_SETS:
5136  BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
5137  break;
5138  case CD_GRID_PAINT_MASK:
5139  write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
5140  break;
5141  case CD_FACEMAP:
5142  BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
5143  break;
5144  case CD_PROP_BOOL:
5145  BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
5146  break;
5147  case CD_CREASE:
5148  BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
5149  break;
5150  default: {
5151  const char *structname;
5152  int structnum;
5153  CustomData_file_write_info(layer.type, &structname, &structnum);
5154  if (structnum) {
5155  int datasize = structnum * count;
5156  BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
5157  }
5158  else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
5159  printf("%s error: layer '%s':%d - can't be written to file\n",
5160  __func__,
5161  structname,
5162  layer.type);
5163  }
5164  }
5165  }
5166  }
5167 
5168  if (data->external) {
5169  BLO_write_struct(writer, CustomDataExternal, data->external);
5170  }
5171 }
5172 
5173 static void blend_read_mdisps(BlendDataReader *reader, int count, MDisps *mdisps, int external)
5174 {
5175  if (mdisps) {
5176  for (int i = 0; i < count; i++) {
5177  BLO_read_data_address(reader, &mdisps[i].disps);
5178  BLO_read_data_address(reader, &mdisps[i].hidden);
5179 
5180  if (mdisps[i].totdisp && !mdisps[i].level) {
5181  /* this calculation is only correct for loop mdisps;
5182  * if loading pre-BMesh face mdisps this will be
5183  * overwritten with the correct value in
5184  * bm_corners_to_loops() */
5185  float gridsize = sqrtf(mdisps[i].totdisp);
5186  mdisps[i].level = (int)(logf(gridsize - 1.0f) / (float)M_LN2) + 1;
5187  }
5188 
5189  if (BLO_read_requires_endian_switch(reader) && (mdisps[i].disps)) {
5190  /* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
5191  /* this does swap for data written at write_mdisps() - readfile.c */
5192  BLI_endian_switch_float_array(*mdisps[i].disps, mdisps[i].totdisp * 3);
5193  }
5194  if (!external && !mdisps[i].disps) {
5195  mdisps[i].totdisp = 0;
5196  }
5197  }
5198  }
5199 }
5200 
5202  int count,
5203  GridPaintMask *grid_paint_mask)
5204 {
5205  if (grid_paint_mask) {
5206  for (int i = 0; i < count; i++) {
5207  GridPaintMask *gpm = &grid_paint_mask[i];
5208  if (gpm->data) {
5209  BLO_read_data_address(reader, &gpm->data);
5210  }
5211  }
5212  }
5213 }
5214 
5216 {
5217  BLO_read_data_address(reader, &data->layers);
5218 
5219  /* Annoying workaround for bug T31079 loading legacy files with
5220  * no polygons _but_ have stale custom-data. */
5221  if (UNLIKELY(count == 0 && data->layers == nullptr && data->totlayer != 0)) {
5223  return;
5224  }
5225 
5226  BLO_read_data_address(reader, &data->external);
5227 
5228  int i = 0;
5229  while (i < data->totlayer) {
5230  CustomDataLayer *layer = &data->layers[i];
5231 
5232  if (layer->flag & CD_FLAG_EXTERNAL) {
5233  layer->flag &= ~CD_FLAG_IN_MEMORY;
5234  }
5235 
5236  layer->flag &= ~CD_FLAG_NOFREE;
5237 
5238  if (CustomData_verify_versions(data, i)) {
5239  BLO_read_data_address(reader, &layer->data);
5241  /* Under normal operations, this shouldn't happen, but...
5242  * For a CD_PROP_BOOL example, see T84935.
5243  * For a CD_MLOOPUV example, see T90620. */
5244  CLOG_WARN(&LOG,
5245  "Allocated custom data layer that was not saved correctly for layer->type = %d.",
5246  layer->type);
5247  }
5248 
5249  if (layer->type == CD_MDISPS) {
5251  reader, count, static_cast<MDisps *>(layer->data), layer->flag & CD_FLAG_EXTERNAL);
5252  }
5253  else if (layer->type == CD_GRID_PAINT_MASK) {
5254  blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer->data));
5255  }
5256  i++;
5257  }
5258  }
5259 
5260  /* Ensure allocated size is set to the size of the read array. While this should always be the
5261  * case (see #CustomData_blend_write_prepare), there can be some corruption in rare cases (e.g.
5262  * files saved between ff3d535bc2a63092 and 945f32e66d6ada2a). */
5263  data->maxlayer = data->totlayer;
5264 
5266 }
5267 
5270 /* -------------------------------------------------------------------- */
5274 #ifndef NDEBUG
5275 
5276 void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
5277 {
5278  for (int type = 0; type < CD_NUMTYPES; type++) {
5279  if (CustomData_has_layer(data, type)) {
5280  /* NOTE: doesn't account for multiple layers. */
5281  const char *name = CustomData_layertype_name(type);
5282  const int size = CustomData_sizeof(type);
5283  const void *pt = CustomData_get_layer(data, type);
5284  const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
5285  const char *structname;
5286  int structnum;
5287  CustomData_file_write_info(type, &structname, &structnum);
5289  dynstr,
5290  "%sdict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
5291  indent,
5292  name,
5293  structname,
5294  type,
5295  (const void *)pt,
5296  size,
5297  pt_size);
5298  }
5299  }
5300 }
5301 
5302 #endif /* NDEBUG */
5303 
5306 namespace blender::bke {
5307 
5308 /* -------------------------------------------------------------------- */
5313 {
5314  switch (type) {
5315  case CD_PROP_FLOAT:
5316  return &CPPType::get<float>();
5317  case CD_PROP_FLOAT2:
5318  return &CPPType::get<float2>();
5319  case CD_PROP_FLOAT3:
5320  return &CPPType::get<float3>();
5321  case CD_PROP_INT32:
5322  return &CPPType::get<int>();
5323  case CD_PROP_COLOR:
5324  return &CPPType::get<ColorGeometry4f>();
5325  case CD_PROP_BOOL:
5326  return &CPPType::get<bool>();
5327  case CD_PROP_INT8:
5328  return &CPPType::get<int8_t>();
5329  case CD_PROP_BYTE_COLOR:
5330  return &CPPType::get<ColorGeometry4b>();
5331  default:
5332  return nullptr;
5333  }
5334  return nullptr;
5335 }
5336 
5338 {
5339  if (type.is<float>()) {
5340  return CD_PROP_FLOAT;
5341  }
5342  if (type.is<float2>()) {
5343  return CD_PROP_FLOAT2;
5344  }
5345  if (type.is<float3>()) {
5346  return CD_PROP_FLOAT3;
5347  }
5348  if (type.is<int>()) {
5349  return CD_PROP_INT32;
5350  }
5351  if (type.is<ColorGeometry4f>()) {
5352  return CD_PROP_COLOR;
5353  }
5354  if (type.is<bool>()) {
5355  return CD_PROP_BOOL;
5356  }
5357  if (type.is<int8_t>()) {
5358  return CD_PROP_INT8;
5359  }
5360  if (type.is<ColorGeometry4b>()) {
5361  return CD_PROP_BYTE_COLOR;
5362  }
5363  return static_cast<eCustomDataType>(-1);
5364 }
5365 
5368 } // namespace blender::bke
typedef float(TangentPoint)[2]
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id)
const char * BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id)
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id)
CustomData interface, see also DNA_customdata_types.h.
eCDAllocType
@ CD_REFERENCE
@ CD_ASSIGN
@ CD_DUPLICATE
@ CD_DEFAULT
void(* cd_datatransfer_interp)(const struct CustomDataTransferLayerMap *laymap, void *dest, const void **sources, const float *weights, int count, float mix_factor)
uint64_t eCustomDataMask
#define ORIGINDEX_NONE
bool(* cd_validate)(void *item, uint totitems, bool do_fixes)
@ CD_FAKE
@ 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(* cd_copy)(const void *source, void *dest, int count)
#define CD_TYPE_AS_MASK(_type)
void(* cd_interp)(const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
bool cdf_write_open(CDataFile *cdf, const char *filepath)
bool cdf_read_data(CDataFile *cdf, unsigned int size, void *data)
#define CDF_TYPE_MESH
void cdf_read_close(CDataFile *cdf)
CDataFile * cdf_create(int type)
void cdf_write_close(CDataFile *cdf)
void cdf_free(CDataFile *cdf)
bool cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
CDataFileLayer * cdf_layer_add(CDataFile *cdf, int type, const char *name, size_t datasize)
CDataFileLayer * cdf_layer_find(CDataFile *cdf, int type, const char *name)
bool cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay)
bool cdf_read_open(CDataFile *cdf, const char *filepath)
bool cdf_write_data(CDataFile *cdf, unsigned int size, void *data)
support for deformation groups and hooks.
void BKE_defvert_blend_write(struct BlendWriter *writer, int count, const struct MDeformVert *dvlist)
int multires_mdisp_corners(const struct MDisps *s)
int BKE_ccg_gridsize(int level)
Definition: CCGSubSurf.c:23
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define BLI_BITMAP_SIZE(_num)
Definition: BLI_bitmap.h:35
A dynamically sized string ADT.
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_endian_switch_float_array(float *val, int size) ATTR_NONNULL(1)
Definition: endian_switch.c:51
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
#define M_LN2
Definition: BLI_math_base.h:53
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_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float t)
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_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 mul_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3(float r[3])
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)
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], float t)
Definition: math_vector.c:14
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)
Definition: math_vector.c:1259
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:92
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
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])
bool is_finite_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:344
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])
Definition: math_vector.c:838
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void copy_vn_i(int *array_tar, int size, int val)
Definition: math_vector.c:1223
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)
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:99
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
Definition: BLI_mempool.c:253
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition: BLI_mempool.c:319
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
#define FILE_MAX
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
Definition: string_utils.c:233
unsigned int uint
Definition: BLI_sys_types.h:67
#define INIT_MINMAX2(min, max)
#define ARRAY_SIZE(arr)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
#define BLO_read_data_address(reader, ptr_p)
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr)
Definition: writefile.c:1596
#define BLO_write_struct_array_at_address(writer, struct_name, array_size, address, data_ptr)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, int array_size, const void *data_ptr)
Definition: writefile.c:1499
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
Definition: readfile.c:5143
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
Definition: writefile.c:1489
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1608
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:189
ID and Library types, which are fundamental for sdna.
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:561
#define CD_MASK_SCULPT_FACE_SETS
#define CD_MASK_BM_ELEM_PYPTR
#define MAX_CUSTOMDATA_LAYER_NAME
#define CD_MASK_MLOOP
#define CD_MASK_NORMAL
#define CD_MASK_BWEIGHT
@ CD_FLAG_NOCOPY
@ CD_FLAG_IN_MEMORY
@ CD_FLAG_COLOR_RENDER
@ CD_FLAG_TEMPORARY
@ CD_FLAG_NOFREE
@ CD_FLAG_COLOR_ACTIVE
@ CD_FLAG_EXTERNAL
#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_PREVIEW_MCOL
#define CD_MASK_TANGENT
#define CD_MASK_FREESTYLE_FACE
#define CD_MASK_MEDGE
#define CD_MASK_SHAPE_KEYINDEX
#define CD_MASK_MTFACE
#define CD_MASK_ORIGSPACE_MLOOP
#define CD_MASK_MPOLY
eCustomDataType
@ CD_PROP_BYTE_COLOR
@ CD_FACEMAP
@ CD_PAINT_MASK
@ CD_PROP_FLOAT
@ CD_MTFACE
@ CD_PROP_FLOAT3
@ CD_MDEFORMVERT
@ CD_PROP_COLOR
@ CD_NUMTYPES
@ CD_PROP_INT8
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_BOOL
@ CD_SCULPT_FACE_SETS
@ CD_GRID_PAINT_MASK
@ CD_MLOOPUV
#define CD_MASK_CLOTH_ORCO
#define CD_MASK_PREVIEW_MLOOPCOL
#define CD_MASK_GRID_PAINT_MASK
#define CD_MASK_CUSTOMLOOPNORMAL
#define CD_MASK_MVERT
#define CD_MASK_CREASE
#define CD_MASK_SHAPEKEY
#define CD_MASK_FACEMAP
#define CD_MASK_MLOOPUV
#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 CD_MASK_PAINT_MASK
struct MLoop MLoop
struct FreestyleEdge FreestyleEdge
struct MDisps MDisps
struct MEdge MEdge
struct MVertSkin MVertSkin
struct MStringProperty MStringProperty
struct GridPaintMask GridPaintMask
struct MRecast MRecast
struct MDeformVert MDeformVert
struct MTFace MTFace
struct OrigSpaceFace OrigSpaceFace
struct OrigSpaceLoop OrigSpaceLoop
struct MIntProperty MIntProperty
@ MVERT_SKIN_ROOT
struct MLoopCol MLoopCol
struct MPoly MPoly
struct MFloatProperty MFloatProperty
struct MPropCol MPropCol
struct MFace MFace
struct MLoopUV MLoopUV
struct FreestyleFace FreestyleFace
struct MVert MVert
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
#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:24
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
constexpr const T * data() const
Definition: BLI_span.hh:203
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
#define logf(x)
Definition: cuda/compat.h:105
void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
Definition: customdata.cc:5276
static void layerDefault_origindex(void *data, int count)
Definition: customdata.cc:1230
bool CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
Definition: customdata.cc:3441
static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
Definition: customdata.cc:2338
static int layerMaxNum_tface()
Definition: customdata.cc:469
static void layerInterp_mdeformvert(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:253
static void layerAdd_mloopuv(void *data1, const void *data2)
Definition: customdata.cc:1038
void CustomData_swap(CustomData *data, const int index_a, const int index_b)
Definition: customdata.cc:3319
static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
Definition: customdata.cc:1439
const CustomData_MeshMasks CD_MASK_EVERYTHING
Definition: customdata.cc:2101
static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
Definition: customdata.cc:1115
void CustomData_bmesh_set(const CustomData *data, void *block, int type, const void *source)
Definition: customdata.cc:4020
int CustomData_get_layer_index_n(const CustomData *data, int type, int n)
Definition: customdata.cc:2442
void CustomData_set(const CustomData *data, int index, int type, const void *source)
Definition: customdata.cc:3489
static void write_mdisps(BlendWriter *writer, int count, const MDisps *mdlist, int external)
Definition: customdata.cc:5073
static void layerSwap_flnor(void *data, const int *corner_indices)
Definition: customdata.cc:1331
static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes)
Definition: customdata.cc:1071
void CustomData_set_only_copy(const CustomData *data, eCustomDataMask mask)
Definition: customdata.cc:3073
void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, const void *source)
Definition: customdata.cc:4037
void * CustomData_duplicate_referenced_layer(CustomData *data, const int type, const int totelem)
Definition: customdata.cc:2976
bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
Definition: customdata.cc:2895
void * CustomData_add_layer(CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem)
Definition: customdata.cc:2776
static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
Definition: customdata.cc:3708
void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filepath)
Definition: customdata.cc:4723
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
Definition: customdata.cc:923
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX
Definition: customdata.cc:2058
void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest, void *src_block, void **dest_block)
Definition: customdata.cc:3830
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES]
Definition: customdata.cc:1607
bool CustomData_layer_has_interp(const CustomData *data, int layer_n)
Definition: customdata.cc:3881
void CustomData_free_layers(CustomData *data, int type, int totelem)
Definition: customdata.cc:2904
static bool layerRead_mdisps(CDataFile *cdf, void *data, int count)
Definition: customdata.cc:694
static void layerMultiply_mloopuv(void *data, float fac)
Definition: customdata.cc:1014
bool CustomData_merge(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.cc:2220
static bool layerEqual_mloopuv(const void *data1, const void *data2)
Definition: customdata.cc:1006
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)
Definition: customdata.cc:4952
static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
Definition: customdata.cc:4820
static void layerInterp_mcol(const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
Definition: customdata.cc:1160
void CustomData_blend_write(BlendWriter *writer, CustomData *data, Span< CustomDataLayer > layers_to_write, int count, eCustomDataMask cddata_mask, ID *id)
Definition: customdata.cc:5108
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, int totelem)
Definition: customdata.cc:4547
void CustomData_interp(const CustomData *source, CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
Definition: customdata.cc:3223
void * CustomData_add_layer_anonymous(CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem, const AnonymousAttributeID *anonymous_id)
Definition: customdata.cc:2810
static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
Definition: customdata.cc:1100
bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
Definition: customdata.cc:2831
static void layerCopy_propString(const void *source, void *dest, int count)
Definition: customdata.cc:550
static void blend_read_mdisps(BlendDataReader *reader, int count, MDisps *mdisps, int external)
Definition: customdata.cc:5173
static void layerInterp_paint_mask(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:744
static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax)
Definition: customdata.cc:1029
void * CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
Definition: customdata.cc:3849
static int CustomData_get_layer_index__notypemap(const CustomData *data, int type)
Definition: customdata.cc:2422
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *UNUSED(self))
Definition: customdata.cc:237
void CustomData_data_mix_value(int type, const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:3955
void CustomData_bmesh_free_block(CustomData *data, void **block)
Definition: customdata.cc:3665
static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t count)
Definition: customdata.cc:4434
static void layerDefault_mvert_skin(void *data, int count)
Definition: customdata.cc:1288
void CustomData_set_layer_render(CustomData *data, int type, int n)
Definition: customdata.cc:2551
int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
Definition: customdata.cc:2455
static void layerDefault_tface(void *data, int count)
Definition: customdata.cc:459
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)
Definition: customdata.cc:4837
static const LayerTypeInfo * layerType_getInfo(int type)
Definition: customdata.cc:2122
static void * customData_duplicate_referenced_layer_index(CustomData *data, const int layer_index, const int totelem)
Definition: customdata.cc:2943
int CustomData_get_layer_index(const CustomData *data, int type)
Definition: customdata.cc:2436
const char * CustomData_get_layer_name(const CustomData *data, int type, int n)
Definition: customdata.cc:3455
int CustomData_get_stencil_layer_index(const CustomData *data, int type)
Definition: customdata.cc:2489
int CustomData_number_of_layers_typemask(const CustomData *data, eCustomDataMask mask)
Definition: customdata.cc:2930
bool CustomData_layertype_is_singleton(int type)
Definition: customdata.cc:4280
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition: customdata.cc:77
void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype)
Definition: customdata.cc:3541
void CustomData_set_layer_stencil_index(CustomData *data, int type, int n)
Definition: customdata.cc:2614
static void layerCopy_propInt(const void *source, void *dest, int count)
Definition: customdata.cc:523
static bool layerWrite_mdisps(CDataFile *cdf, const void *data, int count)
Definition: customdata.cc:712
const char * CustomData_get_active_layer_name(const CustomData *data, const int type)
Definition: customdata.cc:2535
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
Definition: customdata.cc:3743
int CustomData_get_active_layer(const CustomData *data, int type)
Definition: customdata.cc:2507
bool CustomData_data_equals(int type, const void *data1, const void *data2)
Definition: customdata.cc:3973
static void layerCopy_mvert_skin(const void *source, void *dest, int count)
Definition: customdata.cc:1298
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data, void *block, const eCustomDataMask mask_exclude)
Definition: customdata.cc:3722
void customData_mask_layers__print(const CustomData_MeshMasks *mask)
Definition: customdata.cc:2140
void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, const void *source)
Definition: customdata.cc:4054
void CustomData_reset(CustomData *data)
Definition: customdata.cc:2367
void * CustomData_get_n(const CustomData *data, int type, int index, int n)
Definition: customdata.cc:3362
bool CustomData_layer_has_math(const CustomData *data, int layer_n)
Definition: customdata.cc:3869
void * CustomData_set_layer_n(const CustomData *data, int type, int n, void *ptr)
Definition: customdata.cc:3476
void * CustomData_bmesh_get(const CustomData *data, void *block, int type)
Definition: customdata.cc:3838
#define SOURCE_BUF_SIZE
Definition: customdata.cc:3221
static void write_grid_paint_mask(BlendWriter *writer, int count, const GridPaintMask *grid_paint_mask)
Definition: customdata.cc:5092
int CustomData_get_offset_named(const CustomData *data, int type, const char *name)
Definition: customdata.cc:3419
static bool customdata_unique_check(void *arg, const char *name)
Definition: customdata.cc:4337
static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
Definition: customdata.cc:1123
static void layerSwap_tface(void *data, const int *corner_indices)
Definition: customdata.cc:446
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref, const CustomData_MeshMasks *mask_required)
Definition: customdata.cc:87
void CustomData_data_add(int type, void *data1, const void *data2)
Definition: customdata.cc:4011
void CustomData_copy_data_layer(const CustomData *source, CustomData *dest, int src_layer_index, int dst_layer_index, int src_index, int dst_index, int count)
Definition: customdata.cc:3094
bool CustomData_has_interp(const CustomData *data)
Definition: customdata.cc:3917
static void layerCopy_tface(const void *source, void *dest, int count)
Definition: customdata.cc:409
void * CustomData_duplicate_referenced_layer_n(CustomData *data, const int type, const int n, const int totelem)
Definition: customdata.cc:2984
static const char * layerType_getName(int type)
Definition: customdata.cc:2131
bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
Definition: customdata.cc:4468
void CustomData_bmesh_interp(CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block)
Definition: customdata.cc:4088
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.cc:2051
static void layerFree_mdisps(void *data, int count, int UNUSED(size))
Definition: customdata.cc:676
bool CustomData_has_layer(const CustomData *data, int type)
Definition: customdata.cc:2912
static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
Definition: customdata.cc:1021
static void customData_update_offsets(CustomData *data)
Definition: customdata.cc:2405
static void layerInterp_shapekey(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1258
static void layerAdd_mloopcol(void *data1, const void *data2)
Definition: customdata.cc:880
static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
Definition: customdata.cc:4789
static bool customData_resize(CustomData *data, int amount)
Definition: customdata.cc:2646
void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem)
Definition: customdata.cc:4748
bool CustomData_is_referenced_layer(CustomData *data, int type)
Definition: customdata.cc:3028
static void layerDefault_propcol(void *data, int count)
Definition: customdata.cc:1456
static void layerCopy_propFloat(const void *source, void *dest, int count)
Definition: customdata.cc:480
static void layerAdd_mloop_origspace(void *data1, const void *data2)
Definition: customdata.cc:1132
void CustomData_set_layer_render_index(CustomData *data, int type, int n)
Definition: customdata.cc:2590
static void layerSwap_origspace_face(void *data, const int *corner_indices)
Definition: customdata.cc:598
void CustomData_set_layer_active(CustomData *data, int type, int n)
Definition: customdata.cc:2542
static void layerMultiply_propfloat3(void *data, float fac)
Definition: customdata.cc:1503
static void layerInterp_propfloat2(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1541
bool CustomData_layertype_is_dynamic(int type)
Definition: customdata.cc:4286
void * CustomData_get_layer(const CustomData *data, int type)
Definition: customdata.cc:3376
static void layerCopy_mdeformvert(const void *source, void *dest, int count)
Definition: customdata.cc:190
static void layerMultiply_mloop_origspace(void *data, float fac)
Definition: customdata.cc:1108
static bool layerEqual_propcol(const void *data1, const void *data2)
Definition: customdata.cc:1412
int CustomData_layertype_layers_max(const int type)
Definition: customdata.cc:4293
static void layerInitMinMax_propcol(void *vmin, void *vmax)
Definition: customdata.cc:1447
void CustomData_free(CustomData *data, int totelem)
Definition: customdata.cc:2373
static void layerFree_mdeformvert(void *data, int count, int size)
Definition: customdata.cc:212
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)
Definition: customdata.cc:4071
static void layerCopy_mdisps(const void *source, void *dest, int count)
Definition: customdata.cc:655
static void layerCopyValue_mloopuv(const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:987
void CustomData_data_copy_value(int type, const void *source, void *dest)
Definition: customdata.cc:3939
static void layerAdd_propfloat3(void *data1, const void *data2)
Definition: customdata.cc:1511
bool CustomData_free_layer_named(CustomData *data, const char *name, const int totelem)
Definition: customdata.cc:2883
bool CustomData_verify_versions(CustomData *data, int index)
Definition: customdata.cc:4388
static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
Definition: customdata.cc:1520
void CustomData_external_reload(CustomData *data, ID *UNUSED(id), eCustomDataMask mask, int totelem)
Definition: customdata.cc:4526
int CustomData_get_n_offset(const CustomData *data, int type, int n)
Definition: customdata.cc:3430
void CustomData_clear_layer_flag(CustomData *data, int type, int flag)
Definition: customdata.cc:2635
void CustomData_free_temporary(CustomData *data, int totelem)
Definition: customdata.cc:3041
int CustomData_get_stencil_layer(const CustomData *data, int type)
Definition: customdata.cc:2528
static void layerInterp_mloopuv(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1046
int CustomData_get_clone_layer(const CustomData *data, int type)
Definition: customdata.cc:2521
static void blend_read_paint_mask(BlendDataReader *reader, int count, GridPaintMask *grid_paint_mask)
Definition: customdata.cc:5201
static void layerCopy_grid_paint_mask(const void *source, void *dest, int count)
Definition: customdata.cc:765
void CustomData_free_typemask(CustomData *data, int totelem, eCustomDataMask mask)
Definition: customdata.cc:2387
const CustomData_MeshMasks CD_MASK_BMESH
Definition: customdata.cc:2090
static void layerCopy_origspace_face(const void *source, void *dest, int count)
Definition: customdata.cc:561
void CustomData_update_typemap(CustomData *data)
Definition: customdata.cc:2193
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
Definition: customdata.cc:5215
void CustomData_data_multiply(int type, void *data, float fac)
Definition: customdata.cc:4002
void CustomData_bmesh_set_default(CustomData *data, void **block)
Definition: customdata.cc:3756
const char * CustomData_layertype_name(int type)
Definition: customdata.cc:4275
static void layerAdd_propcol(void *data1, const void *data2)
Definition: customdata.cc:1432
void * CustomData_get(const CustomData *data, int index, int type)
Definition: customdata.cc:3346
static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int count)
Definition: customdata.cc:726
static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, int count)
Definition: customdata.cc:226
bool CustomData_bmesh_merge(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, BMesh *bm, const char htype)
Definition: customdata.cc:3573
static void CustomData_external_free(CustomData *data)
Definition: customdata.cc:2359
static void layerInterp_propInt(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:528
void CustomData_layers__print(CustomData *data)
Definition: customdata.cc:4488
static void layerAdd_propfloat2(void *data1, const void *data2)
Definition: customdata.cc:1563
static CustomDataLayer * customData_add_layer__internal(CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem, const char *name)
Definition: customdata.cc:2664
static bool customdata_typemap_is_valid(const CustomData *data)
Definition: customdata.cc:2212
bool CustomData_has_referenced(const CustomData *data)
Definition: customdata.cc:3929
void CustomData_copy(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.cc:2323
static bool layerEqual_mloopcol(const void *data1, const void *data2)
Definition: customdata.cc:856
void CustomData_validate_layer_name(const CustomData *data, int type, const char *name, char *outname)
Definition: customdata.cc:4364
void * CustomData_add_layer_named(CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem, const char *name)
Definition: customdata.cc:2792
void * CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
Definition: customdata.cc:3860
void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
Definition: customdata.cc:4988
void CustomData_blend_write_prepare(CustomData &data, Vector< CustomDataLayer, 16 > &layers_to_write)
Definition: customdata.cc:4253
void CustomData_data_initminmax(int type, void *min, void *max)
Definition: customdata.cc:3984
static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size)
Definition: customdata.cc:243
int CustomData_number_of_layers(const CustomData *data, int type)
Definition: customdata.cc:2917
int CustomData_get_active_layer_index(const CustomData *data, int type)
Definition: customdata.cc:2468
void * CustomData_get_layer_n(const CustomData *data, int type, int n)
Definition: customdata.cc:3387
void CustomData_set_layer_clone(CustomData *data, int type, int n)
Definition: customdata.cc:2560
int CustomData_sizeof(int type)
Definition: customdata.cc:4268
void CustomData_set_layer_unique_name(CustomData *data, int index)
Definition: customdata.cc:4343
static void layerInterp_propfloat3(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1488
void CustomData_set_layer_active_index(CustomData *data, int type, int n)
Definition: customdata.cc:2578
static void layerDefault_mcol(void *data, int count)
Definition: customdata.cc:1220
static void layerMultiply_propcol(void *data, float fac)
Definition: customdata.cc:1426
static void customdata_external_filename(char filepath[FILE_MAX], ID *id, CustomDataExternal *external)
Definition: customdata.cc:4518
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num)
Definition: customdata.cc:4245
bool CustomData_bmesh_has_free(const CustomData *data)
Definition: customdata.cc:3904
void CustomData_free_elem(CustomData *data, int index, int count)
Definition: customdata.cc:3206
static void layerInterp_origspace_face(const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
Definition: customdata.cc:571
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
Definition: customdata.cc:3150
static void layerInterp_mvert_skin(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1303
int CustomData_get_offset(const CustomData *data, int type)
Definition: customdata.cc:3408
bool CustomData_external_test(CustomData *data, int type)
Definition: customdata.cc:4772
static void layerCopyValue_propcol(const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:1364
static void layerDefault_origspace_face(void *data, int count)
Definition: customdata.cc:609
void CustomData_realloc(CustomData *data, int totelem)
Definition: customdata.cc:2307
void * CustomData_set_layer(const CustomData *data, int type, void *ptr)
Definition: customdata.cc:3462
static void layerInterp_propcol(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1466
void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source, CustomData *dest, void *src_block, void **dest_block, const eCustomDataMask mask_exclude)
Definition: customdata.cc:3767
static void layerSwap_mcol(void *data, const int *corner_indices)
Definition: customdata.cc:1208
static void layerMultiply_propfloat2(void *data, float fac)
Definition: customdata.cc:1556
static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
Definition: customdata.cc:500
static CLG_LogRef LOG
Definition: customdata.cc:71
static void layerInterp_propFloat(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:485
int CustomData_get_render_layer(const CustomData *data, int type)
Definition: customdata.cc:2514
const CustomData_MeshMasks CD_MASK_DERIVEDMESH
Definition: customdata.cc:2077
static void layerInterp_normal(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:347
static void layerInterp_mloopcol(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:948
static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:366
static void layerInterp_propbool(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1592
void CustomData_external_write(CustomData *data, ID *id, eCustomDataMask mask, int totelem, int free)
Definition: customdata.cc:4620
static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
Definition: customdata.cc:4308
static void layerDefault_fmap(void *data, int count)
Definition: customdata.cc:1350
static void layerCopyValue_mloop_origspace(const void *source, void *dest, const int UNUSED(mixmode), const float UNUSED(mixfactor))
Definition: customdata.cc:1089
void * CustomData_get_layer_named(const CustomData *data, int type, const char *name)
Definition: customdata.cc:3398
static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
Definition: customdata.cc:891
void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest, void *src_block, int dest_index)
Definition: customdata.cc:4200
int CustomData_get_clone_layer_index(const CustomData *data, int type)
Definition: customdata.cc:2482
static void layerInterp_bweight(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1235
static const char * LAYERTYPENAMES[CD_NUMTYPES]
Definition: customdata.cc:1994
int CustomData_get_render_layer_index(const CustomData *data, int type)
Definition: customdata.cc:2475
void CustomData_set_layer_clone_index(CustomData *data, int type, int n)
Definition: customdata.cc:2602
void CustomData_copy_data_named(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
Definition: customdata.cc:3134
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
Definition: customdata.cc:3082
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem)
Definition: customdata.cc:3020
void CustomData_data_dominmax(int type, const void *data, void *min, void *max)
Definition: customdata.cc:3993
void * CustomData_duplicate_referenced_layer_named(CustomData *data, const int type, const char *name, const int totelem)
Definition: customdata.cc:2995
bool CustomData_has_math(const CustomData *data)
Definition: customdata.cc:3892
static void layerInterp_mloop_origspace(const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest)
Definition: customdata.cc:1140
BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *) nullptr) ->typemap)==CD_NUMTYPES, "size mismatch")
int CustomData_get_named_layer(const CustomData *data, int type, const char *name)
Definition: customdata.cc:2499
static void layerDefault_mloopcol(void *data, int count)
Definition: customdata.cc:939
void CustomData_set_layer_flag(CustomData *data, int type, int flag)
Definition: customdata.cc:2626
void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, int src_index, void **dest_block, bool use_default_init)
Definition: customdata.cc:4139
#define CUSTOMDATA_GROW
Definition: customdata.cc:66
static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
Definition: customdata.cc:1571
void CustomData_copy_layer_type_data(const CustomData *source, CustomData *destination, int type, int source_index, int destination_index, int count)
Definition: customdata.cc:3182
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.cc:2065
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
Definition: customdata.cc:3689
#define COPY_BIT_FLAG(_type, _dst, _src, _f)
void CustomData_set_layer_stencil(CustomData *data, int type, int n)
Definition: customdata.cc:2569
static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
Definition: customdata.cc:782
static void layerCopyValue_mloopcol(const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:798
static void layerSwap_mdisps(void *data, const int *ci)
Definition: customdata.cc:625
void CustomData_swap_corners(CustomData *data, int index, const int *corner_indices)
Definition: customdata.cc:3306
static void layerMultiply_mloopcol(void *data, float fac)
Definition: customdata.cc:870
static void layerInterp_tface(const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
Definition: customdata.cc:418
void * CustomData_duplicate_referenced_layer_anonymous(CustomData *data, const int UNUSED(type), const AnonymousAttributeID *anonymous_id, const int totelem)
Definition: customdata.cc:3006
void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata)
Definition: customdata.cc:3508
OperationNode * node
SyclQueue void void * src
SyclQueue void void size_t num_bytes void
SyclQueue void * dest
static const float data2[18 *GP_PRIM_DATABUF_SIZE]
static const float data1[33 *GP_PRIM_DATABUF_SIZE]
uint col
int count
#define PRIx64
Definition: inttypes.h:133
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:26
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
Definition: math_float2.h:232
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static ulong * next
#define sqrtf(x)
Definition: metal/compat.h:243
bool isfinite(uchar)
Definition: scene/image.cpp:31
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
const blender::CPPType * custom_data_type_to_cpp_type(const eCustomDataType type)
Definition: customdata.cc:5312
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
Definition: customdata.cc:5337
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
static void update(bNodeTree *ntree)
static PropertyRNA * typemap[IDP_NUMTYPES]
Definition: rna_access.c:406
#define min(a, b)
Definition: sort.c:35
unsigned short uint16_t
Definition: stdint.h:79
unsigned int uint32_t
Definition: stdint.h:80
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90
signed char int8_t
Definition: stdint.h:75
void * data
Definition: bmesh_class.h:51
BMHeader head
Definition: bmesh_class.h:145
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
int totloop
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297
const struct AnonymousAttributeID * anonymous_id
cd_datatransfer_interp interp
struct BLI_mempool * pool
CustomDataLayer * layers
CustomDataExternal * external
unsigned int level
Definition: DNA_ID.h:368
bool(* write)(CDataFile *cdf, const void *data, int count)
Definition: customdata.cc:174
void(* set_default)(void *data, int count)
Definition: customdata.cc:157
void(* dominmax)(const void *data1, void *min, void *max)
Definition: customdata.cc:167
const char * defaultname
Definition: customdata.cc:117
cd_interp interp
Definition: customdata.cc:149
void(* free)(void *data, int count, int size)
Definition: customdata.cc:132
void(* add)(void *data1, const void *data2)
Definition: customdata.cc:166
size_t(* filesize)(CDataFile *cdf, const void *data, int count)
Definition: customdata.cc:177
const char * structname
Definition: customdata.cc:107
int(* layers_max)()
Definition: customdata.cc:181
void(* copyvalue)(const void *source, void *dest, const int mixmode, const float mixfactor)
Definition: customdata.cc:168
cd_copy copy
Definition: customdata.cc:124
bool(* read)(CDataFile *cdf, void *data, int count)
Definition: customdata.cc:171
void(* initminmax)(void *min, void *max)
Definition: customdata.cc:165
cd_validate validate
Definition: customdata.cc:160
void(* swap)(void *data, const int *corner_indices)
Definition: customdata.cc:152
bool(* equal)(const void *data1, const void *data2)
Definition: customdata.cc:163
void(* multiply)(void *data, float fac)
Definition: customdata.cc:164
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 color[4]
float uv[4][2]
MeshPairRemapItem * items
float x
Definition: DNA_vec_types.h:23
float y
Definition: DNA_vec_types.h:23
float x
Definition: DNA_vec_types.h:41
float z
Definition: DNA_vec_types.h:41
float y
Definition: DNA_vec_types.h:41
float max
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480