Blender  V3.3
attribute.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 
10 #include <cstring>
11 #include <optional>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_ID.h"
16 #include "DNA_curves_types.h"
17 #include "DNA_customdata_types.h"
18 #include "DNA_mesh_types.h"
19 #include "DNA_meshdata_types.h"
20 #include "DNA_pointcloud_types.h"
21 
22 #include "BLI_index_range.hh"
23 #include "BLI_string.h"
24 #include "BLI_string_utf8.h"
25 #include "BLI_string_utils.h"
26 
27 #include "BLT_translation.h"
28 
29 #include "BKE_attribute.h"
30 #include "BKE_attribute.hh"
31 #include "BKE_curves.hh"
32 #include "BKE_customdata.h"
33 #include "BKE_editmesh.h"
34 #include "BKE_pointcloud.h"
35 #include "BKE_report.h"
36 
37 #include "RNA_access.h"
38 
40 
41 struct DomainInfo {
43  int length;
44 };
45 
46 static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
47 {
48  memset(info, 0, sizeof(DomainInfo) * ATTR_DOMAIN_NUM);
49 
50  switch (GS(id->name)) {
51  case ID_PT: {
52  PointCloud *pointcloud = (PointCloud *)id;
53  info[ATTR_DOMAIN_POINT].customdata = &pointcloud->pdata;
54  info[ATTR_DOMAIN_POINT].length = pointcloud->totpoint;
55  break;
56  }
57  case ID_ME: {
58  Mesh *mesh = (Mesh *)id;
59  BMEditMesh *em = mesh->edit_mesh;
60  if (em != nullptr) {
61  BMesh *bm = em->bm;
62  info[ATTR_DOMAIN_POINT].customdata = &bm->vdata;
63  info[ATTR_DOMAIN_POINT].length = bm->totvert;
64  info[ATTR_DOMAIN_EDGE].customdata = &bm->edata;
65  info[ATTR_DOMAIN_EDGE].length = bm->totedge;
66  info[ATTR_DOMAIN_CORNER].customdata = &bm->ldata;
67  info[ATTR_DOMAIN_CORNER].length = bm->totloop;
68  info[ATTR_DOMAIN_FACE].customdata = &bm->pdata;
69  info[ATTR_DOMAIN_FACE].length = bm->totface;
70  }
71  else {
72  info[ATTR_DOMAIN_POINT].customdata = &mesh->vdata;
73  info[ATTR_DOMAIN_POINT].length = mesh->totvert;
74  info[ATTR_DOMAIN_EDGE].customdata = &mesh->edata;
75  info[ATTR_DOMAIN_EDGE].length = mesh->totedge;
76  info[ATTR_DOMAIN_CORNER].customdata = &mesh->ldata;
77  info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
78  info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata;
79  info[ATTR_DOMAIN_FACE].length = mesh->totpoly;
80  }
81  break;
82  }
83  case ID_CV: {
84  Curves *curves = (Curves *)id;
85  info[ATTR_DOMAIN_POINT].customdata = &curves->geometry.point_data;
86  info[ATTR_DOMAIN_POINT].length = curves->geometry.point_num;
87  info[ATTR_DOMAIN_CURVE].customdata = &curves->geometry.curve_data;
88  info[ATTR_DOMAIN_CURVE].length = curves->geometry.curve_num;
89  break;
90  }
91  default:
92  break;
93  }
94 }
95 
96 namespace blender::bke {
97 
98 static std::optional<blender::bke::MutableAttributeAccessor> get_attribute_accessor_for_write(
99  ID &id)
100 {
101  switch (GS(id.name)) {
102  case ID_ME: {
103  Mesh &mesh = reinterpret_cast<Mesh &>(id);
104  /* The attribute API isn't implemented for BMesh, so edit mode meshes are not supported. */
105  BLI_assert(mesh.edit_mesh == nullptr);
107  }
108  case ID_PT: {
109  PointCloud &pointcloud = reinterpret_cast<PointCloud &>(id);
110  return pointcloud_attributes_for_write(pointcloud);
111  }
112  case ID_CV: {
113  Curves &curves_id = reinterpret_cast<Curves &>(id);
115  return curves.attributes_for_write();
116  }
117  default: {
119  return {};
120  }
121  }
122 }
123 
124 } // namespace blender::bke
125 
127 {
129  get_domains(id, info);
130  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
131  if (info[domain].customdata) {
132  return true;
133  }
134  }
135  return false;
136 }
137 
138 bool BKE_attribute_allow_procedural_access(const char *attribute_name)
139 {
141 }
142 
144  const char *old_name,
145  const char *new_name,
146  ReportList *reports)
147 {
148  if (BKE_id_attribute_required(id, old_name)) {
149  BLI_assert_msg(0, "Required attribute name is not editable");
150  return false;
151  }
152  if (STREQ(new_name, "")) {
153  BKE_report(reports, RPT_ERROR, "Attribute name can not be empty");
154  return false;
155  }
156  if (STREQ(old_name, new_name)) {
157  return false;
158  }
159 
161  id, old_name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
162  if (layer == nullptr) {
163  BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
164  return false;
165  }
166 
167  char result_name[MAX_CUSTOMDATA_LAYER_NAME];
168  BKE_id_attribute_calc_unique_name(id, new_name, result_name);
169  BLI_strncpy_utf8(layer->name, result_name, sizeof(layer->name));
170 
171  return true;
172 }
173 
175  ID *id;
176 };
177 
178 static bool unique_name_cb(void *arg, const char *name)
179 {
181 
183  get_domains(data->id, info);
184 
185  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
186  if (!info[domain].customdata) {
187  continue;
188  }
189 
190  CustomData *cdata = info[domain].customdata;
191  for (int i = 0; i < cdata->totlayer; i++) {
192  CustomDataLayer *layer = cdata->layers + i;
193 
194  if (STREQ(layer->name, name)) {
195  return true;
196  }
197  }
198  }
199 
200  return false;
201 }
202 
203 bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
204 {
205  AttrUniqueData data{id};
206 
207  /* Set default name if none specified.
208  * NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
209  if (!name || name[0] == '\0') {
210  BLI_strncpy(outname, IFACE_("Attribute"), MAX_CUSTOMDATA_LAYER_NAME);
211  }
212  else {
214  }
215 
216  return BLI_uniquename_cb(
217  unique_name_cb, &data, nullptr, '.', outname, MAX_CUSTOMDATA_LAYER_NAME);
218 }
219 
221  ID *id, const char *name, const int type, const eAttrDomain domain, ReportList *reports)
222 {
223  using namespace blender::bke;
225  get_domains(id, info);
226 
227  CustomData *customdata = info[domain].customdata;
228  if (customdata == nullptr) {
229  BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type");
230  return nullptr;
231  }
232 
233  char uniquename[MAX_CUSTOMDATA_LAYER_NAME];
234  BKE_id_attribute_calc_unique_name(id, name, uniquename);
235 
236  if (GS(id->name) == ID_ME) {
237  Mesh *mesh = reinterpret_cast<Mesh *>(id);
238  if (BMEditMesh *em = mesh->edit_mesh) {
239  BM_data_layer_add_named(em->bm, customdata, type, uniquename);
240  const int index = CustomData_get_named_layer_index(customdata, type, uniquename);
241  return (index == -1) ? nullptr : &(customdata->layers[index]);
242  }
243  }
244 
245  std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
246  if (!attributes) {
247  return nullptr;
248  }
249 
250  attributes->add(uniquename, domain, eCustomDataType(type), AttributeInitDefault());
251 
252  const int index = CustomData_get_named_layer_index(customdata, type, uniquename);
253  return (index == -1) ? nullptr : &(customdata->layers[index]);
254 }
255 
256 CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports)
257 {
258  using namespace blender::bke;
259  char uniquename[MAX_CUSTOMDATA_LAYER_NAME];
260  BKE_id_attribute_calc_unique_name(id, name, uniquename);
261 
262  if (GS(id->name) == ID_ME) {
263  Mesh *mesh = reinterpret_cast<Mesh *>(id);
264  if (BMEditMesh *em = mesh->edit_mesh) {
266  UNUSED_VARS(em);
267  return nullptr;
268  }
269  }
270 
271  std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
272  if (!attributes) {
273  return nullptr;
274  }
275 
276  GAttributeReader src = attributes->lookup(name);
277  if (!src) {
278  BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
279  return nullptr;
280  }
281 
282  const eCustomDataType type = cpp_type_to_custom_data_type(src.varray.type());
283  attributes->add(uniquename, src.domain, type, AttributeInitVArray(src.varray));
284 
286 }
287 
288 bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
289 {
290  using namespace blender::bke;
291  if (!name || name[0] == '\0') {
292  BKE_report(reports, RPT_ERROR, "The attribute name must not be empty");
293  return false;
294  }
295  if (BKE_id_attribute_required(id, name)) {
296  BKE_report(reports, RPT_ERROR, "Attribute is required and can't be removed");
297  return false;
298  }
299 
301  get_domains(id, info);
302 
303  if (GS(id->name) == ID_ME) {
304  Mesh *mesh = reinterpret_cast<Mesh *>(id);
305  if (BMEditMesh *em = mesh->edit_mesh) {
306  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
307  if (CustomData *data = info[domain].customdata) {
308  if (BM_data_layer_free_named(em->bm, data, name)) {
309  return true;
310  }
311  }
312  }
313  return false;
314  }
315  }
316 
317  std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
318  if (!attributes) {
319  return false;
320  }
321 
322  return attributes->remove(name);
323 }
324 
326  const char *name,
327  const int type,
328  const eAttrDomain domain)
329 {
331  get_domains(id, info);
332 
333  CustomData *customdata = info[domain].customdata;
334  if (customdata == nullptr) {
335  return nullptr;
336  }
337 
338  for (int i = 0; i < customdata->totlayer; i++) {
339  CustomDataLayer *layer = &customdata->layers[i];
340  if (layer->type == type && STREQ(layer->name, name)) {
341  return layer;
342  }
343  }
344 
345  return nullptr;
346 }
347 
349  const char *name,
350  const eCustomDataMask type_mask,
351  const eAttrDomainMask domain_mask)
352 {
354  get_domains(id, info);
355 
356  for (eAttrDomain domain = ATTR_DOMAIN_POINT; domain < ATTR_DOMAIN_NUM;
357  domain = static_cast<eAttrDomain>((static_cast<int>(domain)) + 1)) {
358  if (!(domain_mask & ATTR_DOMAIN_AS_MASK(domain))) {
359  continue;
360  }
361 
362  CustomData *customdata = info[domain].customdata;
363  if (customdata == nullptr) {
364  continue;
365  }
366 
367  for (int i = 0; i < customdata->totlayer; i++) {
368  CustomDataLayer *layer = &customdata->layers[i];
369  if ((CD_TYPE_AS_MASK(layer->type) & type_mask) && STREQ(layer->name, name)) {
370  return layer;
371  }
372  }
373  }
374 
375  return nullptr;
376 }
377 
379 {
381  get_domains(id, info);
382 
383  int length = 0;
384 
385  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
386  CustomData *customdata = info[domain].customdata;
387 
388  if (customdata && ((1 << (int)domain) & domain_mask)) {
390  }
391  }
392 
393  return length;
394 }
395 
397 {
399  get_domains(id, info);
400 
401  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
402  CustomData *customdata = info[domain].customdata;
403  if (customdata &&
404  ARRAY_HAS_ITEM((CustomDataLayer *)layer, customdata->layers, customdata->totlayer)) {
405  return static_cast<eAttrDomain>(domain);
406  }
407  }
408 
409  BLI_assert_msg(0, "Custom data layer not found in geometry");
410  return static_cast<eAttrDomain>(ATTR_DOMAIN_POINT);
411 }
412 
414 {
415  /* When in mesh editmode, attributes point to bmesh customdata layers, the attribute data is
416  * empty since custom data is stored per element instead of a single array there (same es UVs
417  * etc.), see D11998. */
418  switch (GS(id->name)) {
419  case ID_ME: {
420  Mesh *mesh = (Mesh *)id;
421  if (mesh->edit_mesh != nullptr) {
422  return 0;
423  }
424  }
425  default:
426  break;
427  }
428 
430  get_domains(id, info);
431 
432  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
433  CustomData *customdata = info[domain].customdata;
434  if (customdata &&
435  ARRAY_HAS_ITEM((CustomDataLayer *)layer, customdata->layers, customdata->totlayer)) {
436  return info[domain].length;
437  }
438  }
439 
440  BLI_assert_msg(0, "Custom data layer not found in geometry");
441  return 0;
442 }
443 
444 bool BKE_id_attribute_required(const ID *id, const char *name)
445 {
446  switch (GS(id->name)) {
447  case ID_PT: {
448  return BKE_pointcloud_customdata_required((const PointCloud *)id, name);
449  }
450  case ID_CV: {
451  return BKE_curves_customdata_required((const Curves *)id, name);
452  }
453  default:
454  return false;
455  }
456 }
457 
459 {
460  int active_index = *BKE_id_attributes_active_index_p(id);
462  active_index = 0;
463  }
464 
466  get_domains(id, info);
467 
468  int index = 0;
469 
470  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
471  CustomData *customdata = info[domain].customdata;
472  if (customdata) {
473  for (int i = 0; i < customdata->totlayer; i++) {
474  CustomDataLayer *layer = &customdata->layers[i];
475  if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
476  if (index == active_index && BKE_attribute_allow_procedural_access(layer->name)) {
477  return layer;
478  }
479  index++;
480  }
481  }
482  }
483  }
484 
485  return nullptr;
486 }
487 
489 {
491  get_domains(id, info);
492 
493  int index = 0;
494 
495  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
496  CustomData *customdata = info[domain].customdata;
497  if (customdata) {
498  for (int i = 0; i < customdata->totlayer; i++) {
499  CustomDataLayer *layer = &customdata->layers[i];
500  if (layer == active_layer) {
502  return;
503  }
504  if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
505  index++;
506  }
507  }
508  }
509  }
510 }
511 
513 {
514  switch (GS(id->name)) {
515  case ID_PT: {
516  return &((PointCloud *)id)->attributes_active_index;
517  }
518  case ID_ME: {
519  return &((Mesh *)id)->attributes_active_index;
520  }
521  case ID_CV: {
522  return &((Curves *)id)->attributes_active_index;
523  }
524  default:
525  return nullptr;
526  }
527 }
528 
530 {
532  get_domains(id, info);
533 
534  bool use_next = (layers == nullptr);
535 
536  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
537  CustomData *customdata = info[domain].customdata;
538  if (customdata && customdata->layers && customdata->totlayer) {
539  if (customdata->layers == layers) {
540  use_next = true;
541  }
542  else if (use_next) {
543  return customdata;
544  }
545  }
546  }
547 
548  return nullptr;
549 }
550 
552  int lookup_index,
553  eAttrDomainMask domain_mask,
554  eCustomDataMask layer_mask)
555 {
557  get_domains(id, info);
558 
559  int index = 0;
560  for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
561  CustomData *customdata = info[domain].customdata;
562 
563  if (!customdata || !((1 << (int)domain) & domain_mask)) {
564  continue;
565  }
566 
567  for (int i = 0; i < customdata->totlayer; i++) {
568  if (!(layer_mask & CD_TYPE_AS_MASK(customdata->layers[i].type)) ||
569  (customdata->layers[i].flag & CD_FLAG_TEMPORARY)) {
570  continue;
571  }
572 
573  if (index == lookup_index) {
574  return customdata->layers + i;
575  }
576 
577  index++;
578  }
579  }
580 
581  return nullptr;
582 }
583 
588 {
589  for (const int i : IndexRange(ATTR_DOMAIN_NUM)) {
590  domains[i] = static_cast<eAttrDomain>(i);
591  }
592 
593  /* Swap corner and face. */
595 }
596 
598  const CustomDataLayer *layer,
599  eAttrDomainMask domain_mask,
600  eCustomDataMask layer_mask)
601 {
602  if (!layer) {
603  return -1;
604  }
605 
607  eAttrDomain domains[ATTR_DOMAIN_NUM];
608  get_domains_types(domains);
609  get_domains(id, info);
610 
611  int index = 0;
612  for (int i = 0; i < ATTR_DOMAIN_NUM; i++) {
613  if (!(domain_mask & (1 << domains[i])) || !info[domains[i]].customdata) {
614  continue;
615  }
616 
617  const CustomData *cdata = info[domains[i]].customdata;
618  for (int j = 0; j < cdata->totlayer; j++) {
619  const CustomDataLayer *layer_iter = cdata->layers + j;
620 
621  if (!(CD_TYPE_AS_MASK(layer_iter->type) & layer_mask) ||
622  (layer_iter->flag & CD_FLAG_TEMPORARY)) {
623  continue;
624  }
625 
626  if (layer == layer_iter) {
627  return index;
628  }
629 
630  index++;
631  }
632  }
633 
634  return -1;
635 }
636 
638  int active_flag,
639  eAttrDomainMask domain_mask,
641 {
643  eAttrDomain domains[ATTR_DOMAIN_NUM];
644 
645  get_domains_types(domains);
646  get_domains(id, info);
647 
648  CustomDataLayer *candidate = nullptr;
649  for (int i = 0; i < ARRAY_SIZE(domains); i++) {
650  if (!((1 << domains[i]) & domain_mask) || !info[domains[i]].customdata) {
651  continue;
652  }
653 
654  CustomData *cdata = info[domains[i]].customdata;
655 
656  for (int j = 0; j < cdata->totlayer; j++) {
657  CustomDataLayer *layer = cdata->layers + j;
658 
659  if (!(CD_TYPE_AS_MASK(layer->type) & mask) || (layer->flag & CD_FLAG_TEMPORARY)) {
660  continue;
661  }
662 
663  if (layer->flag & active_flag) {
664  return layer;
665  }
666 
667  candidate = layer;
668  }
669  }
670 
671  return candidate;
672 }
673 
675  CustomDataLayer *layer,
676  int active_flag,
677  eAttrDomainMask domain_mask,
679 {
681  eAttrDomain domains[ATTR_DOMAIN_NUM];
682 
683  get_domains_types(domains);
684  get_domains(id, info);
685 
686  for (int i = 0; i < ATTR_DOMAIN_NUM; i++) {
687  eAttrDomainMask domain_mask2 = (eAttrDomainMask)(1 << domains[i]);
688 
689  if (!(domain_mask2 & domain_mask) || !info[domains[i]].customdata) {
690  continue;
691  }
692 
693  CustomData *cdata = info[domains[i]].customdata;
694 
695  for (int j = 0; j < cdata->totlayer; j++) {
696  CustomDataLayer *layer_iter = cdata->layers + j;
697 
698  if (!(CD_TYPE_AS_MASK(layer_iter->type) & mask) || (layer_iter->flag & CD_FLAG_TEMPORARY)) {
699  continue;
700  }
701 
702  layer_iter->flag &= ~active_flag;
703  }
704  }
705 
706  layer->flag |= active_flag;
707 }
708 
710 {
713 }
714 
716 {
719 }
720 
722 {
725 }
726 
728 {
731 }
732 
733 CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name)
734 {
736  if (layer == nullptr) {
738  }
739  if (layer == nullptr) {
741  }
742  if (layer == nullptr) {
744  }
745 
746  return layer;
747 }
748 
750  const CustomData *vdata,
751  const CustomData *edata,
752  const CustomData *ldata,
753  const CustomData *pdata,
754  const CustomData *cdata,
755  ID *r_id)
756 {
758 
760 
761  switch (id_type) {
762  case ID_ME: {
763  Mesh *me = (Mesh *)r_id;
764  memset((void *)me, 0, sizeof(*me));
765 
766  me->edit_mesh = nullptr;
767 
768  me->vdata = vdata ? *vdata : reset;
769  me->edata = edata ? *edata : reset;
770  me->ldata = ldata ? *ldata : reset;
771  me->pdata = pdata ? *pdata : reset;
772 
773  break;
774  }
775  case ID_PT: {
776  PointCloud *pointcloud = (PointCloud *)r_id;
777 
778  memset((void *)pointcloud, 0, sizeof(*pointcloud));
779 
780  pointcloud->pdata = vdata ? *vdata : reset;
781  break;
782  }
783  case ID_CV: {
784  Curves *curves = (Curves *)r_id;
785 
786  memset((void *)curves, 0, sizeof(*curves));
787 
788  curves->geometry.point_data = vdata ? *vdata : reset;
789  curves->geometry.curve_data = cdata ? *cdata : reset;
790  break;
791  }
792  default:
793  break;
794  }
795 
796  *((short *)r_id->name) = id_type;
797 }
Generic geometry attributes built on CustomData.
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_CURVE
Definition: BKE_attribute.h:31
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
@ ATTR_DOMAIN_FACE
Definition: BKE_attribute.h:29
@ ATTR_DOMAIN_CORNER
Definition: BKE_attribute.h:30
@ ATTR_DOMAIN_EDGE
Definition: BKE_attribute.h:28
eAttrDomainMask
Definition: BKE_attribute.h:36
@ ATTR_DOMAIN_MASK_ALL
Definition: BKE_attribute.h:42
#define ATTR_DOMAIN_MASK_COLOR
Definition: BKE_attribute.h:48
#define ATTR_DOMAIN_AS_MASK(domain)
Definition: BKE_attribute.h:45
#define ATTR_DOMAIN_NUM
Definition: BKE_attribute.h:34
bool BKE_curves_customdata_required(const struct Curves *curves, const char *name)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
uint64_t eCustomDataMask
#define CD_TYPE_AS_MASK(_type)
int CustomData_number_of_layers_typemask(const struct CustomData *data, eCustomDataMask mask)
void CustomData_reset(struct CustomData *data)
Definition: customdata.cc:2367
General operations for point clouds.
bool BKE_pointcloud_customdata_required(const struct PointCloud *pointcloud, const char *name)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#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
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(1
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
#define ARRAY_SIZE(arr)
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len)
#define STREQ(a, b)
#define IFACE_(msgid)
ID and Library types, which are fundamental for sdna.
@ ID_CV
Definition: DNA_ID_enums.h:81
@ ID_ME
Definition: DNA_ID_enums.h:48
@ ID_PT
Definition: DNA_ID_enums.h:82
#define MAX_CUSTOMDATA_LAYER_NAME
@ CD_FLAG_COLOR_RENDER
@ CD_FLAG_TEMPORARY
@ CD_FLAG_COLOR_ACTIVE
#define CD_MASK_PROP_ALL
#define CD_MASK_COLOR_ALL
eCustomDataType
@ CD_PROP_BYTE_COLOR
@ CD_PROP_COLOR
_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.
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 curves
CustomDataLayer * BKE_id_attributes_color_find(const ID *id, const char *name)
Definition: attribute.cc:733
CustomDataLayer * BKE_id_attribute_find(const ID *id, const char *name, const int type, const eAttrDomain domain)
Definition: attribute.cc:325
void BKE_id_attribute_subset_active_set(ID *id, CustomDataLayer *layer, int active_flag, eAttrDomainMask domain_mask, eCustomDataMask mask)
Definition: attribute.cc:674
eAttrDomain BKE_id_attribute_domain(const ID *id, const CustomDataLayer *layer)
Definition: attribute.cc:396
CustomDataLayer * BKE_id_attribute_new(ID *id, const char *name, const int type, const eAttrDomain domain, ReportList *reports)
Definition: attribute.cc:220
CustomDataLayer * BKE_id_attribute_from_index(ID *id, int lookup_index, eAttrDomainMask domain_mask, eCustomDataMask layer_mask)
Definition: attribute.cc:551
bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
Definition: attribute.cc:288
int BKE_id_attributes_length(const ID *id, eAttrDomainMask domain_mask, eCustomDataMask mask)
Definition: attribute.cc:378
int BKE_id_attribute_to_index(const ID *id, const CustomDataLayer *layer, eAttrDomainMask domain_mask, eCustomDataMask layer_mask)
Definition: attribute.cc:597
void BKE_id_attributes_render_color_set(ID *id, CustomDataLayer *active_layer)
Definition: attribute.cc:727
bool BKE_attribute_allow_procedural_access(const char *attribute_name)
Definition: attribute.cc:138
CustomDataLayer * BKE_id_attributes_active_color_get(const ID *id)
Definition: attribute.cc:709
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
Definition: attribute.cc:203
bool BKE_id_attribute_rename(ID *id, const char *old_name, const char *new_name, ReportList *reports)
Definition: attribute.cc:143
static void get_domains_types(eAttrDomain domains[ATTR_DOMAIN_NUM])
Definition: attribute.cc:587
CustomDataLayer * BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports)
Definition: attribute.cc:256
int BKE_id_attribute_data_length(ID *id, CustomDataLayer *layer)
Definition: attribute.cc:413
CustomDataLayer * BKE_id_attributes_active_get(ID *id)
Definition: attribute.cc:458
void BKE_id_attributes_active_color_set(ID *id, CustomDataLayer *active_layer)
Definition: attribute.cc:715
static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
Definition: attribute.cc:46
int * BKE_id_attributes_active_index_p(ID *id)
Definition: attribute.cc:512
CustomDataLayer * BKE_id_attribute_search(ID *id, const char *name, const eCustomDataMask type_mask, const eAttrDomainMask domain_mask)
Definition: attribute.cc:348
CustomDataLayer * BKE_id_attribute_subset_active_get(const ID *id, int active_flag, eAttrDomainMask domain_mask, eCustomDataMask mask)
Definition: attribute.cc:637
bool BKE_id_attribute_required(const ID *id, const char *name)
Definition: attribute.cc:444
void BKE_id_attributes_active_set(ID *id, CustomDataLayer *active_layer)
Definition: attribute.cc:488
bool BKE_id_attributes_supported(const ID *id)
Definition: attribute.cc:126
CustomData * BKE_id_attributes_iterator_next_domain(ID *id, CustomDataLayer *layers)
Definition: attribute.cc:529
static bool unique_name_cb(void *arg, const char *name)
Definition: attribute.cc:178
CustomDataLayer * BKE_id_attributes_render_color_get(const ID *id)
Definition: attribute.cc:721
void BKE_id_attribute_copy_domains_temp(short id_type, const CustomData *vdata, const CustomData *edata, const CustomData *ldata, const CustomData *pdata, const CustomData *cdata, ID *r_id)
Definition: attribute.cc:749
bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
Definition: bmesh_interp.c:897
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
Definition: bmesh_interp.c:857
ATTR_WARN_UNUSED_RESULT BMesh * bm
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
SyclQueue void void * src
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global float int int int int float bool reset
clear internal cached data and reset random seed
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
bool allow_procedural_attribute_access(StringRef attribute_name)
static std::optional< blender::bke::MutableAttributeAccessor > get_attribute_accessor_for_write(ID &id)
Definition: attribute.cc:98
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
Definition: customdata.cc:5337
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
T length(const vec_base< T, Size > &a)
struct BMesh * bm
Definition: BKE_editmesh.h:40
int totvert
Definition: bmesh_class.h:297
CustomData vdata
Definition: bmesh_class.h:337
int totedge
Definition: bmesh_class.h:297
CustomData edata
Definition: bmesh_class.h:337
int totloop
Definition: bmesh_class.h:297
CustomData pdata
Definition: bmesh_class.h:337
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
CurvesGeometry geometry
CustomDataLayer * layers
CustomData * customdata
Definition: attribute.cc:42
int length
Definition: attribute.cc:43
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
struct BMEditMesh * edit_mesh
CustomData vdata
int totedge
int totvert
CustomData pdata
int totpoly
CustomData edata
int totloop
CustomData ldata
struct CustomData pdata