From 9c28f0eb37aebd6e5eae0763b008ef02d5ce081b Mon Sep 17 00:00:00 2001 From: Dennis Ranish Date: Wed, 8 Jun 2022 12:10:32 -0700 Subject: D14823: Adds operator to duplicate the active color attribute layer Fixes T97706 Adds operator to duplicate the active color attribute layer. Adds `"Color Attribute Specials"` menu to color attribute ui to access the `"geometry.color_attribute_duplicate"` operator. Internally adds a function that duplicates a referenced CustomDataLayer - `BKE_id_attribute_duplicate` mostly copies the existing `BKE_id_attribute_new` - but gets the type and domain from the referenced layer - and copies the data from the old layer into the new layer Reviewed By: Joseph Eagar & Hans Goudey & Julien Kaspar Differential Revision: https://developer.blender.org/D14823 Ref D14823 --- source/blender/blenkernel/BKE_attribute.h | 7 ++++ source/blender/blenkernel/intern/attribute.cc | 53 ++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 52a3e01026c..5755ddb3018 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -60,6 +60,13 @@ struct CustomDataLayer *BKE_id_attribute_new( struct ID *id, const char *name, int type, eAttrDomain domain, struct ReportList *reports); bool BKE_id_attribute_remove(struct ID *id, const char *name, struct ReportList *reports); +/** + * Creates a duplicate attribute layer. + */ +struct CustomDataLayer *BKE_id_attribute_duplicate(struct ID *id, + struct CustomDataLayer *layer, + struct ReportList *reports); + struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id, const char *name, int type, diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index eac42d19b52..b2ea8b833b3 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -208,6 +208,55 @@ CustomDataLayer *BKE_id_attribute_new( return (index == -1) ? nullptr : &(customdata->layers[index]); } +CustomDataLayer *BKE_id_attribute_duplicate(ID *id, CustomDataLayer *layer, ReportList *reports) +{ + DomainInfo info[ATTR_DOMAIN_NUM]; + get_domains(id, info); + + eCustomDataType type = (eCustomDataType)layer->type; + eAttrDomain domain = BKE_id_attribute_domain(id, layer); + + CustomData *customdata = info[domain].customdata; + if (customdata == nullptr) { + BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type"); + return nullptr; + } + + char name[MAX_CUSTOMDATA_LAYER_NAME]; + char uniquename[MAX_CUSTOMDATA_LAYER_NAME]; + + /* Make a copy of name in case CustomData API reallocates the layers. */ + BLI_strncpy(name, layer->name, MAX_CUSTOMDATA_LAYER_NAME); + BKE_id_attribute_calc_unique_name(id, layer->name, uniquename); + + switch (GS(id->name)) { + case ID_ME: { + Mesh *me = (Mesh *)id; + BMEditMesh *em = me->edit_mesh; + if (em != nullptr) { + BM_data_layer_add_named(em->bm, customdata, type, uniquename); + } + else { + CustomData_add_layer_named( + customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename); + } + break; + } + default: { + CustomData_add_layer_named( + customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename); + break; + } + } + + int from_index = CustomData_get_named_layer_index(customdata, type, name); + int to_index = CustomData_get_named_layer_index(customdata, type, uniquename); + CustomData_copy_data_layer( + customdata, customdata, from_index, to_index, 0, 0, info[domain].length); + + return (to_index == -1) ? nullptr : &(customdata->layers[to_index]); +} + bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) { if (BKE_id_attribute_required(id, name)) { @@ -283,7 +332,7 @@ CustomDataLayer *BKE_id_attribute_search(const ID *id, } CustomData *customdata = info[domain].customdata; - if (customdata == NULL) { + if (customdata == nullptr) { continue; } @@ -295,7 +344,7 @@ CustomDataLayer *BKE_id_attribute_search(const ID *id, } } - return NULL; + return nullptr; } int BKE_id_attributes_length(const ID *id, eAttrDomainMask domain_mask, eCustomDataMask mask) -- cgit v1.2.3