diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 3f4981993eb..eef1459be81 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -105,16 +105,6 @@ int BKE_id_attribute_to_index(const struct ID *id, eAttrDomainMask domain_mask, eCustomDataMask layer_mask); -struct CustomDataLayer *BKE_id_attribute_subset_active_get(const struct ID *id, - int active_flag, - eAttrDomainMask domain_mask, - eCustomDataMask mask); -void BKE_id_attribute_subset_active_set(struct ID *id, - struct CustomDataLayer *layer, - int active_flag, - eAttrDomainMask domain_mask, - eCustomDataMask mask); - /** * Sets up a temporary ID with arbitrary CustomData domains. `r_id` will * be zero initialized with ID type id_type and any non-nullptr @@ -130,10 +120,13 @@ void BKE_id_attribute_copy_domains_temp(short id_type, const struct CustomData *cdata, struct ID *r_id); +const char *BKE_id_attributes_active_color_name(const struct ID *id); +const char *BKE_id_attributes_default_color_name(const struct ID *id); + struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID *id); -void BKE_id_attributes_active_color_set(struct ID *id, struct CustomDataLayer *active_layer); -struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID *id); -void BKE_id_attributes_render_color_set(struct ID *id, struct CustomDataLayer *active_layer); +void BKE_id_attributes_active_color_set(struct ID *id, const char *name); +struct CustomDataLayer *BKE_id_attributes_default_color_get(const struct ID *id); +void BKE_id_attributes_default_color_set(struct ID *id, const char *name); struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name); bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname); diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index e46942aa9e9..65804e9ac24 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -85,6 +85,9 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(struct Mesh *mesh); /** Convert from runtime loose edge cache to legacy edge flag. */ void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh); +void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh); +void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh); + #endif /** diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index 80647362826..58990c5c024 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -145,6 +145,7 @@ bool BKE_id_attribute_rename(ID *id, const char *new_name, ReportList *reports) { + using namespace blender; if (BKE_id_attribute_required(id, old_name)) { BLI_assert_msg(0, "Required attribute name is not editable"); return false; @@ -166,6 +167,14 @@ bool BKE_id_attribute_rename(ID *id, char result_name[MAX_CUSTOMDATA_LAYER_NAME]; BKE_id_attribute_calc_unique_name(id, new_name, result_name); + + if (StringRef(old_name) == BKE_id_attributes_active_color_name(id)) { + BKE_id_attributes_active_color_set(id, result_name); + } + if (StringRef(old_name) == BKE_id_attributes_default_color_name(id)) { + BKE_id_attributes_default_color_set(id, result_name); + } + BLI_strncpy_utf8(layer->name, result_name, sizeof(layer->name)); return true; @@ -287,6 +296,7 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) { + using namespace blender; using namespace blender::bke; if (!name || name[0] == '\0') { BKE_report(reports, RPT_ERROR, "The attribute name must not be empty"); @@ -306,6 +316,12 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) { if (CustomData *data = info[domain].customdata) { if (BM_data_layer_free_named(em->bm, data, name)) { + if (name == StringRef(mesh->active_color_attribute)) { + MEM_SAFE_FREE(mesh->active_color_attribute); + } + else if (name == StringRef(mesh->default_color_attribute)) { + MEM_SAFE_FREE(mesh->default_color_attribute); + } return true; } } @@ -327,6 +343,9 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id, const int type, const eAttrDomain domain) { + if (!name) { + return nullptr; + } DomainInfo info[ATTR_DOMAIN_NUM]; get_domains(id, info); @@ -350,6 +369,9 @@ CustomDataLayer *BKE_id_attribute_search(ID *id, const eCustomDataMask type_mask, const eAttrDomainMask domain_mask) { + if (!name) { + return nullptr; + } DomainInfo info[ATTR_DOMAIN_NUM]; get_domains(id, info); @@ -633,104 +655,69 @@ int BKE_id_attribute_to_index(const ID *id, return -1; } -CustomDataLayer *BKE_id_attribute_subset_active_get(const ID *id, - int active_flag, - eAttrDomainMask domain_mask, - eCustomDataMask mask) +const char *BKE_id_attributes_active_color_name(const ID *id) { - DomainInfo info[ATTR_DOMAIN_NUM]; - eAttrDomain domains[ATTR_DOMAIN_NUM]; - - get_domains_types(domains); - get_domains(id, info); - - CustomDataLayer *candidate = nullptr; - for (int i = 0; i < ARRAY_SIZE(domains); i++) { - if (!((1 << domains[i]) & domain_mask) || !info[domains[i]].customdata) { - continue; - } - - CustomData *cdata = info[domains[i]].customdata; - - for (int j = 0; j < cdata->totlayer; j++) { - CustomDataLayer *layer = cdata->layers + j; - - if (!(CD_TYPE_AS_MASK(layer->type) & mask) || (layer->flag & CD_FLAG_TEMPORARY)) { - continue; - } - - if (layer->flag & active_flag) { - return layer; - } - - candidate = layer; - } + if (GS(id->name) == ID_ME) { + return reinterpret_cast(id)->active_color_attribute; } - - return candidate; + return nullptr; } -void BKE_id_attribute_subset_active_set(ID *id, - CustomDataLayer *layer, - int active_flag, - eAttrDomainMask domain_mask, - eCustomDataMask mask) +const char *BKE_id_attributes_default_color_name(const ID *id) { - DomainInfo info[ATTR_DOMAIN_NUM]; - eAttrDomain domains[ATTR_DOMAIN_NUM]; - - get_domains_types(domains); - get_domains(id, info); - - for (int i = 0; i < ATTR_DOMAIN_NUM; i++) { - eAttrDomainMask domain_mask2 = (eAttrDomainMask)(1 << domains[i]); - - if (!(domain_mask2 & domain_mask) || !info[domains[i]].customdata) { - continue; - } - - CustomData *cdata = info[domains[i]].customdata; - - for (int j = 0; j < cdata->totlayer; j++) { - CustomDataLayer *layer_iter = cdata->layers + j; - - if (!(CD_TYPE_AS_MASK(layer_iter->type) & mask) || (layer_iter->flag & CD_FLAG_TEMPORARY)) { - continue; - } - - layer_iter->flag &= ~active_flag; - } + if (GS(id->name) == ID_ME) { + return reinterpret_cast(id)->default_color_attribute; } - - layer->flag |= active_flag; + return nullptr; } CustomDataLayer *BKE_id_attributes_active_color_get(const ID *id) { - return BKE_id_attribute_subset_active_get( - id, CD_FLAG_COLOR_ACTIVE, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + return BKE_id_attributes_color_find(id, BKE_id_attributes_active_color_name(id)); } -void BKE_id_attributes_active_color_set(ID *id, CustomDataLayer *active_layer) +void BKE_id_attributes_active_color_set(ID *id, const char *name) { - BKE_id_attribute_subset_active_set( - id, active_layer, CD_FLAG_COLOR_ACTIVE, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + switch (GS(id->name)) { + case ID_ME: { + Mesh *mesh = reinterpret_cast(id); + MEM_SAFE_FREE(mesh->active_color_attribute); + if (name) { + mesh->active_color_attribute = BLI_strdup(name); + } + break; + } + default: + break; + } } -CustomDataLayer *BKE_id_attributes_render_color_get(const ID *id) +CustomDataLayer *BKE_id_attributes_default_color_get(const ID *id) { - return BKE_id_attribute_subset_active_get( - id, CD_FLAG_COLOR_RENDER, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + return BKE_id_attributes_color_find(id, BKE_id_attributes_default_color_name(id)); } -void BKE_id_attributes_render_color_set(ID *id, CustomDataLayer *active_layer) +void BKE_id_attributes_default_color_set(ID *id, const char *name) { - BKE_id_attribute_subset_active_set( - id, active_layer, CD_FLAG_COLOR_RENDER, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + switch (GS(id->name)) { + case ID_ME: { + Mesh *mesh = reinterpret_cast(id); + MEM_SAFE_FREE(mesh->default_color_attribute); + if (name) { + mesh->default_color_attribute = BLI_strdup(name); + } + break; + } + default: + break; + } } CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name) { + if (!name) { + return nullptr; + } CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT); if (layer == nullptr) { layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER); diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index c8d7c4f2fdc..cb22f4a650c 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2347,8 +2347,7 @@ bool CustomData_merge(const CustomData *source, newlayer->active_rnd = lastrender; newlayer->active_clone = lastclone; newlayer->active_mask = lastmask; - newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY | CD_FLAG_COLOR_ACTIVE | - CD_FLAG_COLOR_RENDER); + newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY); changed = true; if (layer->anonymous_id != nullptr) { diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 16858a70a0c..6ec171c4bcc 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -144,6 +144,10 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int mesh_dst->mat = (Material **)MEM_dupallocN(mesh_src->mat); BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names); + mesh_dst->active_color_attribute = static_cast( + MEM_dupallocN(mesh_src->active_color_attribute)); + mesh_dst->default_color_attribute = static_cast( + MEM_dupallocN(mesh_src->default_color_attribute)); const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert); @@ -253,6 +257,9 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address BKE_mesh_legacy_bevel_weight_from_layers(mesh); BKE_mesh_legacy_face_set_from_generic(mesh, poly_layers); BKE_mesh_legacy_edge_crease_from_layers(mesh); + BKE_mesh_legacy_attribute_strings_to_flags(mesh); + mesh->active_color_attribute = nullptr; + mesh->default_color_attribute = nullptr; BKE_mesh_legacy_convert_loose_edges_to_flag(mesh); /* When converting to the old mesh format, don't save redundant attributes. */ names_to_skip.add_multiple_new({".hide_vert", @@ -288,6 +295,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address } BKE_defbase_blend_write(writer, &mesh->vertex_group_names); + BLO_write_string(writer, mesh->active_color_attribute); + BLO_write_string(writer, mesh->default_color_attribute); BLO_write_pointer_array(writer, mesh->totcol, mesh->mat); BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect); @@ -337,6 +346,8 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) * Don't read them again if they were read as part of #CustomData. */ BKE_defvert_blend_read(reader, mesh->totvert, mesh->dvert); } + BLO_read_data_address(reader, &mesh->active_color_attribute); + BLO_read_data_address(reader, &mesh->default_color_attribute); mesh->texflag &= ~ME_AUTOSPACE_EVALUATED; mesh->edit_mesh = nullptr; @@ -893,6 +904,8 @@ static void mesh_clear_geometry(Mesh *mesh) mesh->totselect = 0; BLI_freelistN(&mesh->vertex_group_names); + MEM_SAFE_FREE(mesh->active_color_attribute); + MEM_SAFE_FREE(mesh->default_color_attribute); } void BKE_mesh_clear_geometry(Mesh *mesh) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 1673e972a32..a53b0e66924 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -525,7 +525,7 @@ static void convert_mfaces_to_mpolys(ID *id, #undef ME_FGON } -static void update_active_fdata_layers(CustomData *fdata, CustomData *ldata) +static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata) { int act; @@ -544,10 +544,10 @@ static void update_active_fdata_layers(CustomData *fdata, CustomData *ldata) } if (CustomData_has_layer(ldata, CD_PROP_BYTE_COLOR)) { - act = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR); + act = CustomData_get_named_layer(ldata, CD_PROP_BYTE_COLOR, mesh.active_color_attribute); CustomData_set_layer_active(fdata, CD_MCOL, act); - act = CustomData_get_render_layer(ldata, CD_PROP_BYTE_COLOR); + act = CustomData_get_named_layer(ldata, CD_PROP_BYTE_COLOR, mesh.default_color_attribute); CustomData_set_layer_render(fdata, CD_MCOL, act); act = CustomData_get_clone_layer(ldata, CD_PROP_BYTE_COLOR); @@ -599,7 +599,7 @@ static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ld } #endif -static void add_mface_layers(CustomData *fdata, CustomData *ldata, int total) +static void add_mface_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata, int total) { /* avoid accumulating extra layers */ BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false)); @@ -631,7 +631,7 @@ static void add_mface_layers(CustomData *fdata, CustomData *ldata, int total) } } - update_active_fdata_layers(fdata, ldata); + update_active_fdata_layers(mesh, fdata, ldata); } static void mesh_ensure_tessellation_customdata(Mesh *me) @@ -652,7 +652,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) { BKE_mesh_tessface_clear(me); - add_mface_layers(&me->fdata, &me->ldata, me->totface); + add_mface_layers(*me, &me->fdata, &me->ldata, me->totface); /* TODO: add some `--debug-mesh` option. */ if (G.debug & G_DEBUG) { @@ -931,7 +931,8 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, return nr; } -static int mesh_tessface_calc(CustomData *fdata, +static int mesh_tessface_calc(Mesh &mesh, + CustomData *fdata, CustomData *ldata, CustomData *pdata, MVert *mvert, @@ -1140,7 +1141,7 @@ static int mesh_tessface_calc(CustomData *fdata, /* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons * they are directly tessellated from. */ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface); - add_mface_layers(fdata, ldata, totface); + add_mface_layers(mesh, fdata, ldata, totface); /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx: * Polygons take care of their loops ordering, hence not of their vertices ordering. @@ -1178,7 +1179,8 @@ static int mesh_tessface_calc(CustomData *fdata, void BKE_mesh_tessface_calc(Mesh *mesh) { - mesh->totface = mesh_tessface_calc(&mesh->fdata, + mesh->totface = mesh_tessface_calc(*mesh, + &mesh->fdata, &mesh->ldata, &mesh->pdata, BKE_mesh_verts_for_write(mesh), @@ -1567,3 +1569,123 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(Mesh *mesh) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Attribute Active Flag to String Conversion + * \{ */ + +void BKE_mesh_legacy_attribute_flags_to_strings(Mesh *mesh) +{ + using namespace blender; + /* It's not clear whether the active/render status was stored in the dedicated flags or in the + * generic CustomData layer indices, so convert from both, preferring the explicit flags. */ + + auto active_from_flags = [&](const CustomData &data) { + if (!mesh->active_color_attribute) { + for (const int i : IndexRange(data.totlayer)) { + if (data.layers[i].flag & CD_FLAG_COLOR_ACTIVE) { + mesh->active_color_attribute = BLI_strdup(data.layers[i].name); + } + } + } + }; + auto active_from_indices = [&](const CustomData &data) { + if (!mesh->active_color_attribute) { + const int i = CustomData_get_active_layer_index(&data, CD_PROP_COLOR); + if (i != -1) { + mesh->active_color_attribute = BLI_strdup(data.layers[i].name); + } + } + if (!mesh->active_color_attribute) { + const int i = CustomData_get_active_layer_index(&data, CD_PROP_BYTE_COLOR); + if (i != -1) { + mesh->active_color_attribute = BLI_strdup(data.layers[i].name); + } + } + }; + auto default_from_flags = [&](const CustomData &data) { + if (!mesh->default_color_attribute) { + for (const int i : IndexRange(data.totlayer)) { + if (data.layers[i].flag & CD_FLAG_COLOR_RENDER) { + mesh->default_color_attribute = BLI_strdup(data.layers[i].name); + } + } + } + }; + auto default_from_indices = [&](const CustomData &data) { + if (!mesh->default_color_attribute) { + const int i = CustomData_get_render_layer_index(&data, CD_PROP_COLOR); + if (i != -1) { + mesh->default_color_attribute = BLI_strdup(data.layers[i].name); + } + } + if (!mesh->default_color_attribute) { + const int i = CustomData_get_render_layer_index(&data, CD_PROP_BYTE_COLOR); + if (i != -1) { + mesh->default_color_attribute = BLI_strdup(data.layers[i].name); + } + } + }; + + active_from_flags(mesh->vdata); + active_from_flags(mesh->ldata); + active_from_indices(mesh->vdata); + active_from_indices(mesh->ldata); + + default_from_flags(mesh->vdata); + default_from_flags(mesh->ldata); + default_from_indices(mesh->vdata); + default_from_indices(mesh->ldata); +} + +void BKE_mesh_legacy_attribute_strings_to_flags(Mesh *mesh) +{ + using namespace blender; + CustomData *vdata = &mesh->vdata; + CustomData *ldata = &mesh->ldata; + + CustomData_clear_layer_flag( + vdata, CD_PROP_BYTE_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER); + CustomData_clear_layer_flag(ldata, CD_PROP_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER); + + if (const char *name = mesh->active_color_attribute) { + int i; + if ((i = CustomData_get_named_layer_index(vdata, CD_PROP_BYTE_COLOR, name)) != -1) { + CustomData_set_layer_active_index(vdata, CD_PROP_BYTE_COLOR, i); + vdata->layers[i].flag |= CD_FLAG_COLOR_ACTIVE; + } + else if ((i = CustomData_get_named_layer_index(vdata, CD_PROP_COLOR, name)) != -1) { + CustomData_set_layer_active_index(vdata, CD_PROP_COLOR, i); + vdata->layers[i].flag |= CD_FLAG_COLOR_ACTIVE; + } + else if ((i = CustomData_get_named_layer_index(ldata, CD_PROP_BYTE_COLOR, name)) != -1) { + CustomData_set_layer_active_index(ldata, CD_PROP_BYTE_COLOR, i); + ldata->layers[i].flag |= CD_FLAG_COLOR_ACTIVE; + } + else if ((i = CustomData_get_named_layer_index(ldata, CD_PROP_COLOR, name)) != -1) { + CustomData_set_layer_active_index(ldata, CD_PROP_COLOR, i); + ldata->layers[i].flag |= CD_FLAG_COLOR_ACTIVE; + } + } + if (const char *name = mesh->default_color_attribute) { + int i; + if ((i = CustomData_get_named_layer_index(vdata, CD_PROP_BYTE_COLOR, name)) != -1) { + CustomData_set_layer_render_index(vdata, CD_PROP_BYTE_COLOR, i); + vdata->layers[i].flag |= CD_FLAG_COLOR_RENDER; + } + else if ((i = CustomData_get_named_layer_index(vdata, CD_PROP_COLOR, name)) != -1) { + CustomData_set_layer_render_index(vdata, CD_PROP_COLOR, i); + vdata->layers[i].flag |= CD_FLAG_COLOR_RENDER; + } + else if ((i = CustomData_get_named_layer_index(ldata, CD_PROP_BYTE_COLOR, name)) != -1) { + CustomData_set_layer_render_index(ldata, CD_PROP_BYTE_COLOR, i); + ldata->layers[i].flag |= CD_FLAG_COLOR_RENDER; + } + else if ((i = CustomData_get_named_layer_index(ldata, CD_PROP_COLOR, name)) != -1) { + CustomData_set_layer_render_index(ldata, CD_PROP_COLOR, i); + ldata->layers[i].flag |= CD_FLAG_COLOR_RENDER; + } + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 86c77327f98..a2916c75d51 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -494,21 +494,6 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) MEM_SAFE_FREE(target_lmap); MEM_SAFE_FREE(target_lmap_mem); free_bvhtree_from_mesh(&bvhtree); - - /* Transfer active/render color attributes */ - - CustomDataLayer *active_layer = BKE_id_attributes_active_color_get(&source->id); - CustomDataLayer *render_layer = BKE_id_attributes_render_color_get(&source->id); - - if (active_layer) { - BKE_id_attributes_active_color_set( - &target->id, BKE_id_attributes_color_find(&target->id, active_layer->name)); - } - - if (render_layer) { - BKE_id_attributes_render_color_set( - &target->id, BKE_id_attributes_color_find(&target->id, render_layer->name)); - } } struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh) diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index e6d61ddcdd3..ebbe3c2c4fa 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1919,32 +1919,24 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) void BKE_sculpt_color_layer_create_if_needed(Object *object) { + using namespace blender; + using namespace blender::bke; Mesh *orig_me = BKE_object_get_original_mesh(object); - int types[] = {CD_PROP_COLOR, CD_PROP_BYTE_COLOR}; - bool has_color = false; - - for (int i = 0; i < ARRAY_SIZE(types); i++) { - has_color = CustomData_has_layer(&orig_me->vdata, types[i]) || - CustomData_has_layer(&orig_me->ldata, types[i]); - - if (has_color) { - break; - } - } - - if (has_color) { + if (orig_me->attributes().contains(orig_me->active_color_attribute)) { return; } - CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_SET_DEFAULT, nullptr, orig_me->totvert); - CustomDataLayer *layer = orig_me->vdata.layers + - CustomData_get_layer_index(&orig_me->vdata, CD_PROP_COLOR); + char unique_name[MAX_CUSTOMDATA_LAYER_NAME]; + BKE_id_attribute_calc_unique_name(&orig_me->id, "Color", unique_name); + if (!orig_me->attributes_for_write().add( + unique_name, ATTR_DOMAIN_POINT, CD_PROP_COLOR, AttributeInitDefaultValue())) { + return; + } - BKE_mesh_tessface_clear(orig_me); - - BKE_id_attributes_active_color_set(&orig_me->id, layer); + BKE_id_attributes_active_color_set(&orig_me->id, unique_name); DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES); + BKE_mesh_tessface_clear(orig_me); if (object->sculpt && object->sculpt->pbvh) { BKE_pbvh_update_active_vcol(object->sculpt->pbvh, orig_me); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 35c2c660fd2..efaeb89c9a9 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -696,6 +696,9 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node) args->mpoly = pbvh->mpoly; args->vert_normals = pbvh->vert_normals; + args->active_color = pbvh->mesh->active_color_attribute; + args->render_color = pbvh->mesh->default_color_attribute; + args->prim_indices = node->prim_indices; args->face_sets = pbvh->face_sets; break; @@ -711,6 +714,9 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node) args->face_sets = pbvh->face_sets; args->mpoly = pbvh->mpoly; + args->active_color = pbvh->mesh->active_color_attribute; + args->render_color = pbvh->mesh->default_color_attribute; + args->mesh_grids_num = pbvh->totgrid; args->grids = pbvh->grids; args->gridfaces = pbvh->gridfaces; @@ -1588,7 +1594,7 @@ void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag) bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_attr) { - CustomDataLayer *layer = BKE_id_attributes_active_color_get((ID *)me); + CustomDataLayer *layer = BKE_id_attributes_color_find(&me->id, me->active_color_attribute); if (!layer || !ELEM(layer->type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) { *r_layer = NULL; @@ -1596,7 +1602,7 @@ bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, eAttrDo return false; } - eAttrDomain domain = BKE_id_attribute_domain((ID *)me, layer); + eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) { *r_layer = NULL; diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index c22c74ac237..79b1164c0dd 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3197,10 +3197,10 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) if (actlayer) { if (step) { - BKE_id_attributes_render_color_set(&me->id, actlayer); + BKE_id_attributes_default_color_set(&me->id, actlayer->name); } else { - BKE_id_attributes_active_color_set(&me->id, actlayer); + BKE_id_attributes_active_color_set(&me->id, actlayer->name); } } } @@ -3362,10 +3362,10 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) if (actlayer) { if (step) { - BKE_id_attributes_render_color_set(&me->id, actlayer); + BKE_id_attributes_default_color_set(&me->id, actlayer->name); } else { - BKE_id_attributes_active_color_set(&me->id, actlayer); + BKE_id_attributes_active_color_set(&me->id, actlayer->name); } } } diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 7edeb8a40a5..583e885a487 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -33,6 +33,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) BKE_mesh_legacy_bevel_weight_to_layers(&mesh); BKE_mesh_legacy_face_set_to_generic(&mesh); BKE_mesh_legacy_edge_crease_to_layers(&mesh); + BKE_mesh_legacy_attribute_flags_to_strings(&mesh); } static void version_motion_tracking_legacy_camera_object(MovieClip &movieclip) diff --git a/source/blender/draw/DRW_pbvh.h b/source/blender/draw/DRW_pbvh.h index 6f9daac0a35..6956b44c695 100644 --- a/source/blender/draw/DRW_pbvh.h +++ b/source/blender/draw/DRW_pbvh.h @@ -48,6 +48,9 @@ typedef struct PBVH_GPU_Args { struct CustomData *vdata, *ldata, *pdata; const float (*vert_normals)[3]; + const char *active_color; + const char *render_color; + int face_sets_color_seed, face_sets_color_default; int *face_sets; /* for PBVH_FACES and PBVH_GRIDS */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index bfec7cd6f7b..ba117a75be6 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -426,23 +426,8 @@ static void retrieve_active_attribute_names(MeshRenderData &mr, const Mesh &mesh) { const Mesh *mesh_final = editmesh_final_or_this(&object, &mesh); - const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(mesh_final); - const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(mesh_final); - - /* Necessary because which attributes are active/default is stored in #CustomData. */ - Mesh me_query = blender::dna::shallow_zero_initialize(); - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - - mr.active_color_name = nullptr; - mr.default_color_name = nullptr; - - if (const CustomDataLayer *active = BKE_id_attributes_active_color_get(&me_query.id)) { - mr.active_color_name = active->name; - } - if (const CustomDataLayer *render = BKE_id_attributes_render_color_get(&me_query.id)) { - mr.default_color_name = render->name; - } + mr.active_color_name = mesh_final->active_color_attribute; + mr.default_color_name = mesh_final->default_color_attribute; } MeshRenderData *mesh_render_data_create(Object *object, diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 927b72325ff..2f560d161d7 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -282,19 +282,13 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); const CustomData *cd_edata = mesh_cd_edata_get_from_mesh(me_final); - /* Create a mesh with final customdata domains - * we can query with attribute API. */ - Mesh me_query = blender::dna::shallow_zero_initialize(); - - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, cd_edata, cd_ldata, cd_pdata, nullptr, &me_query.id); - /* See: DM_vertex_attributes_from_gpu for similar logic */ DRW_MeshCDMask cd_used; mesh_cd_layers_type_clear(&cd_used); - const CustomDataLayer *default_color = BKE_id_attributes_render_color_get(&me_query.id); - const StringRefNull default_color_name = default_color ? default_color->name : ""; + const StringRefNull default_color_name = me_final->default_color_attribute ? + me_final->default_color_attribute : + ""; for (int i = 0; i < gpumat_array_len; i++) { GPUMaterial *gpumat = gpumat_array[i]; @@ -883,28 +877,21 @@ static void request_active_and_default_color_attributes(const Object &object, const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); - /* Necessary because which attributes are active/default is stored in #CustomData. */ - Mesh me_query = blender::dna::shallow_zero_initialize(); - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - auto request_color_attribute = [&](const char *name) { - int layer_index; - eCustomDataType type; - if (drw_custom_data_match_attribute(cd_vdata, name, &layer_index, &type)) { - drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_POINT); - } - else if (drw_custom_data_match_attribute(cd_ldata, name, &layer_index, &type)) { - drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_CORNER); + if (name) { + int layer_index; + eCustomDataType type; + if (drw_custom_data_match_attribute(cd_vdata, name, &layer_index, &type)) { + drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_POINT); + } + else if (drw_custom_data_match_attribute(cd_ldata, name, &layer_index, &type)) { + drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_CORNER); + } } }; - if (const CustomDataLayer *active = BKE_id_attributes_active_color_get(&me_query.id)) { - request_color_attribute(active->name); - } - if (const CustomDataLayer *render = BKE_id_attributes_render_color_get(&me_query.id)) { - request_color_attribute(render->name); - } + request_color_attribute(me_final->active_color_attribute); + request_color_attribute(me_final->default_color_attribute); } GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me) diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index cddab74c46f..e1d63158b0b 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -841,8 +841,16 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) { cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR); - active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR); - render_col = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR); + if (psmd->mesh_final->active_color_attribute != NULL) { + active_col = CustomData_get_named_layer(&psmd->mesh_final->ldata, + CD_PROP_BYTE_COLOR, + psmd->mesh_final->active_color_attribute); + } + if (psmd->mesh_final->default_color_attribute != NULL) { + render_col = CustomData_get_named_layer(&psmd->mesh_final->ldata, + CD_PROP_BYTE_COLOR, + psmd->mesh_final->default_color_attribute); + } } } @@ -1168,7 +1176,11 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit, } if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) { num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR); - active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR); + if (psmd->mesh_final->active_color_attribute != NULL) { + active_col = CustomData_get_named_layer(&psmd->mesh_final->ldata, + CD_PROP_BYTE_COLOR, + psmd->mesh_final->active_color_attribute); + } } } diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index d4ffd3f8691..c7b1ddffab3 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -1408,8 +1408,8 @@ void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Mesh *me = BKE_object_get_original_mesh(ob); if (use_color) { - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - + const CustomDataLayer *layer = BKE_id_attributes_color_find(&me->id, + me->active_color_attribute); if (layer) { eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index bc9c449544c..d62ace4fb57 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -24,6 +24,7 @@ #include "BLI_map.hh" #include "BLI_math_color.h" #include "BLI_math_vec_types.hh" +#include "BLI_string_ref.hh" #include "BLI_timeit.hh" #include "BLI_utildefines.h" #include "BLI_vector.hh" @@ -916,33 +917,9 @@ struct PBVHBatches { const char *prefix = "a"; if (ELEM(type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) { - Mesh query_mesh; - - /* Check if we have args->me; if not use get_cdata to build something we - * can query for color attributes. - */ - if (args->me) { - memcpy(static_cast(&query_mesh), - static_cast(args->me), - sizeof(Mesh)); - } - else { - BKE_id_attribute_copy_domains_temp(ID_ME, - get_cdata(ATTR_DOMAIN_POINT, args), - nullptr, - get_cdata(ATTR_DOMAIN_CORNER, args), - nullptr, - nullptr, - &query_mesh.id); - } - prefix = "c"; - - CustomDataLayer *render = BKE_id_attributes_render_color_get(&query_mesh.id); - CustomDataLayer *active = BKE_id_attributes_active_color_get(&query_mesh.id); - - is_render = render && layer && STREQ(render->name, layer->name); - is_active = active && layer && STREQ(active->name, layer->name); + is_active = blender::StringRef(args->active_color) == layer->name; + is_render = blender::StringRef(args->render_color) == layer->name; } else { switch (type) { diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index d4850f5c124..c4cf34b3b94 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -107,8 +107,9 @@ static int geometry_attribute_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void next_color_attribute(ID *id, CustomDataLayer *layer, bool is_render) +static void next_color_attribute(ID *id, const StringRefNull name, bool is_render) { + const CustomDataLayer *layer = BKE_id_attributes_color_find(id, name.c_str()); int index = BKE_id_attribute_to_index(id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); index++; @@ -122,18 +123,18 @@ static void next_color_attribute(ID *id, CustomDataLayer *layer, bool is_render) if (layer) { if (is_render) { - BKE_id_attributes_active_color_set(id, layer); + BKE_id_attributes_active_color_set(id, layer->name); } else { - BKE_id_attributes_render_color_set(id, layer); + BKE_id_attributes_default_color_set(id, layer->name); } } } -static void next_color_attributes(ID *id, CustomDataLayer *layer) +static void next_color_attributes(ID *id, const StringRefNull name) { - next_color_attribute(id, layer, false); /* active */ - next_color_attribute(id, layer, true); /* render */ + next_color_attribute(id, name, false); /* active */ + next_color_attribute(id, name, true); /* render */ } void GEOMETRY_OT_attribute_add(wmOperatorType *ot) @@ -181,7 +182,7 @@ static int geometry_attribute_remove_exec(bContext *C, wmOperator *op) ID *id = static_cast(ob->data); CustomDataLayer *layer = BKE_id_attributes_active_get(id); - next_color_attributes(id, layer); + next_color_attributes(id, layer->name); if (!BKE_id_attribute_remove(id, layer->name, op->reports)) { return OPERATOR_CANCELLED; @@ -231,10 +232,10 @@ static int geometry_color_attribute_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_id_attributes_active_color_set(id, layer); + BKE_id_attributes_active_color_set(id, layer->name); - if (!BKE_id_attributes_render_color_get(id)) { - BKE_id_attributes_render_color_set(id, layer); + if (!BKE_id_attributes_color_find(id, BKE_id_attributes_default_color_name(id))) { + BKE_id_attributes_default_color_set(id, layer->name); } BKE_object_attributes_active_color_fill(ob, color, false); @@ -411,13 +412,8 @@ static int geometry_color_attribute_set_render_exec(bContext *C, wmOperator *op) char name[MAX_NAME]; RNA_string_get(op->ptr, "name", name); - CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT); - layer = !layer ? BKE_id_attribute_find(id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_POINT) : layer; - layer = !layer ? BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER) : layer; - layer = !layer ? BKE_id_attribute_find(id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER) : layer; - - if (layer) { - BKE_id_attributes_render_color_set(id, layer); + if (BKE_id_attributes_color_find(id, name)) { + BKE_id_attributes_default_color_set(id, name); DEG_id_tag_update(id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -453,15 +449,14 @@ static int geometry_color_attribute_remove_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); ID *id = static_cast(ob->data); - CustomDataLayer *layer = BKE_id_attributes_active_color_get(id); - - if (layer == nullptr) { + const std::string active_name = StringRef(BKE_id_attributes_active_color_name(id)); + if (active_name.empty()) { return OPERATOR_CANCELLED; } - next_color_attributes(id, layer); + next_color_attributes(id, active_name); - if (!BKE_id_attribute_remove(id, layer->name, op->reports)) { + if (!BKE_id_attribute_remove(id, active_name.c_str(), op->reports)) { return OPERATOR_CANCELLED; } @@ -477,10 +472,10 @@ static bool geometry_color_attributes_remove_poll(bContext *C) return false; } - Object *ob = ED_object_context(C); - ID *data = ob ? static_cast(ob->data) : nullptr; + const Object *ob = ED_object_context(C); + const ID *data = static_cast(ob->data); - if (BKE_id_attributes_active_color_get(data) != nullptr) { + if (BKE_id_attributes_color_find(data, BKE_id_attributes_active_color_name(data))) { return true; } @@ -506,18 +501,17 @@ static int geometry_color_attribute_duplicate_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); ID *id = static_cast(ob->data); - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(id); - - if (layer == nullptr) { + const char *active_name = BKE_id_attributes_active_color_name(id); + if (active_name == nullptr) { return OPERATOR_CANCELLED; } - CustomDataLayer *new_layer = BKE_id_attribute_duplicate(id, layer->name, op->reports); + CustomDataLayer *new_layer = BKE_id_attribute_duplicate(id, active_name, op->reports); if (new_layer == nullptr) { return OPERATOR_CANCELLED; } - BKE_id_attributes_active_color_set(id, new_layer); + BKE_id_attributes_active_color_set(id, new_layer->name); DEG_id_tag_update(id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -535,10 +529,10 @@ static bool geometry_color_attributes_duplicate_poll(bContext *C) return false; } - Object *ob = ED_object_context(C); - ID *data = ob ? static_cast(ob->data) : nullptr; + const Object *ob = ED_object_context(C); + const ID *data = static_cast(ob->data); - if (BKE_id_attributes_active_color_get(data) != nullptr) { + if (BKE_id_attributes_color_find(data, BKE_id_attributes_active_color_name(data))) { return true; } diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index b2809030192..a2310dddc61 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -377,79 +377,71 @@ bool ED_mesh_uv_remove_named(Mesh *me, const char *name) return false; } -int ED_mesh_color_add(Mesh *me, - const char *name, - const bool active_set, - const bool do_init, - ReportList * /*reports*/) +int ED_mesh_color_add( + Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports) { - /* NOTE: keep in sync with #ED_mesh_uv_add. */ + /* If no name is supplied, provide a backwards compatible default. */ + if (!name) { + name = "Col"; + } - BMEditMesh *em; - int layernum; + if (const CustomDataLayer *layer = BKE_id_attribute_find( + &me->id, me->active_color_attribute, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER)) { + int dummy; + const CustomData *data = mesh_customdata_get_type(me, BM_LOOP, &dummy); + return CustomData_get_named_layer(data, CD_PROP_BYTE_COLOR, layer->name); + } - if (me->edit_mesh) { - em = me->edit_mesh; + CustomDataLayer *layer = BKE_id_attribute_new( + &me->id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER, reports); - layernum = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_BYTE_COLOR); - - /* CD_PROP_BYTE_COLOR */ - BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_PROP_BYTE_COLOR, name); - /* copy data from active vertex color layer */ - if (layernum && do_init) { - const int layernum_dst = CustomData_get_active_layer(&em->bm->ldata, CD_PROP_BYTE_COLOR); - BM_data_layer_copy(em->bm, &em->bm->ldata, CD_PROP_BYTE_COLOR, layernum_dst, layernum); - } - if (active_set || layernum == 0) { - CustomData_set_layer_active(&em->bm->ldata, CD_PROP_BYTE_COLOR, layernum); + if (do_init) { + const char *active_name = me->active_color_attribute; + if (const CustomDataLayer *active_layer = BKE_id_attributes_color_find(&me->id, active_name)) { + if (const BMEditMesh *em = me->edit_mesh) { + BMesh &bm = *em->bm; + const int src_i = CustomData_get_named_layer(&bm.ldata, CD_PROP_BYTE_COLOR, active_name); + const int dst_i = CustomData_get_named_layer(&bm.ldata, CD_PROP_BYTE_COLOR, layer->name); + BM_data_layer_copy(&bm, &bm.ldata, CD_PROP_BYTE_COLOR, src_i, dst_i); + } + else { + memcpy(layer->data, active_layer->data, CustomData_get_elem_size(layer) * me->totloop); + } } } - else { - layernum = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR); - if (CustomData_get_active_layer(&me->ldata, CD_PROP_BYTE_COLOR) != -1 && do_init) { - CustomData_add_layer_named(&me->ldata, - CD_PROP_BYTE_COLOR, - CD_DUPLICATE, - CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR), - me->totloop, - name); - } - else { - CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, name); - } - - if (active_set || layernum == 0) { - CustomData_set_layer_active(&me->ldata, CD_PROP_BYTE_COLOR, layernum); - } - - BKE_mesh_tessface_clear(me); + if (active_set) { + BKE_id_attributes_active_color_set(&me->id, layer->name); } DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); - return layernum; + int dummy; + const CustomData *data = mesh_customdata_get_type(me, BM_LOOP, &dummy); + return CustomData_get_named_layer(data, CD_PROP_BYTE_COLOR, layer->name); } bool ED_mesh_color_ensure(Mesh *me, const char *name) { + using namespace blender; BLI_assert(me->edit_mesh == nullptr); - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - - if (!layer) { - CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, name); - layer = me->ldata.layers + CustomData_get_layer_index(&me->ldata, CD_PROP_BYTE_COLOR); - - BKE_id_attributes_active_color_set(&me->id, layer); - BKE_mesh_tessface_clear(me); + if (me->attributes().contains(me->active_color_attribute)) { + return true; } + char unique_name[MAX_CUSTOMDATA_LAYER_NAME]; + BKE_id_attribute_calc_unique_name(&me->id, name, unique_name); + if (!me->attributes_for_write().add( + unique_name, ATTR_DOMAIN_CORNER, CD_PROP_BYTE_COLOR, bke::AttributeInitDefaultValue())) { + return false; + } + + BKE_id_attributes_active_color_set(&me->id, unique_name); + BKE_mesh_tessface_clear(me); DEG_id_tag_update(&me->id, 0); - return (layer != nullptr); + return true; } /*********************** General poll ************************/ @@ -464,57 +456,44 @@ static bool layers_poll(bContext *C) /*********************** Sculpt Vertex colors operators ************************/ -int ED_mesh_sculpt_color_add(Mesh *me, - const char *name, - const bool do_init, - ReportList * /*reports*/) +int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, ReportList *reports) { - /* NOTE: keep in sync with #ED_mesh_uv_add. */ - - BMEditMesh *em; - int layernum; - - if (me->edit_mesh) { - em = me->edit_mesh; - - layernum = CustomData_number_of_layers(&em->bm->vdata, CD_PROP_COLOR); - - /* CD_PROP_COLOR */ - BM_data_layer_add_named(em->bm, &em->bm->vdata, CD_PROP_COLOR, name); - /* copy data from active vertex color layer */ - if (layernum && do_init) { - const int layernum_dst = CustomData_get_active_layer(&em->bm->vdata, CD_PROP_COLOR); - BM_data_layer_copy(em->bm, &em->bm->vdata, CD_PROP_COLOR, layernum_dst, layernum); - } - if (layernum == 0) { - CustomData_set_layer_active(&em->bm->vdata, CD_PROP_COLOR, layernum); - } + /* If no name is supplied, provide a backwards compatible default. */ + if (!name) { + name = "Color"; } - else { - layernum = CustomData_number_of_layers(&me->vdata, CD_PROP_COLOR); - if (CustomData_has_layer(&me->vdata, CD_PROP_COLOR) && do_init) { - const MPropCol *color_data = (const MPropCol *)CustomData_get_layer(&me->vdata, - CD_PROP_COLOR); - CustomData_add_layer_named( - &me->vdata, CD_PROP_COLOR, CD_DUPLICATE, (MPropCol *)color_data, me->totvert, name); - } - else { - CustomData_add_layer_named( - &me->vdata, CD_PROP_COLOR, CD_SET_DEFAULT, nullptr, me->totvert, name); - } + if (const CustomDataLayer *layer = BKE_id_attribute_find( + &me->id, me->active_color_attribute, CD_PROP_COLOR, ATTR_DOMAIN_POINT)) { + int dummy; + const CustomData *data = mesh_customdata_get_type(me, BM_LOOP, &dummy); + return CustomData_get_named_layer(data, CD_PROP_BYTE_COLOR, layer->name); + } - if (layernum == 0) { - CustomData_set_layer_active(&me->vdata, CD_PROP_COLOR, layernum); - } + CustomDataLayer *layer = BKE_id_attribute_new( + &me->id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT, reports); - BKE_mesh_tessface_clear(me); + if (do_init) { + const char *active_name = me->active_color_attribute; + if (const CustomDataLayer *active_layer = BKE_id_attributes_color_find(&me->id, active_name)) { + if (const BMEditMesh *em = me->edit_mesh) { + BMesh &bm = *em->bm; + const int src_i = CustomData_get_named_layer(&bm.vdata, CD_PROP_COLOR, active_name); + const int dst_i = CustomData_get_named_layer(&bm.vdata, CD_PROP_COLOR, layer->name); + BM_data_layer_copy(&bm, &bm.vdata, CD_PROP_COLOR, src_i, dst_i); + } + else { + memcpy(layer->data, active_layer->data, CustomData_get_elem_size(layer) * me->totloop); + } + } } DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); - return layernum; + int dummy; + const CustomData *data = mesh_customdata_get_type(me, BM_VERT, &dummy); + return CustomData_get_named_layer(data, CD_PROP_COLOR, layer->name); } /*********************** UV texture operators ************************/ diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index d883388fbff..b2b24a88204 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -452,7 +452,7 @@ static bool bake_object_check(const Scene *scene, } if (target == R_BAKE_TARGET_VERTEX_COLORS) { - if (BKE_id_attributes_active_color_get(&me->id) == NULL) { + if (!BKE_id_attributes_color_find(&me->id, me->active_color_attribute)) { BKE_reportf(reports, RPT_ERROR, "Mesh does not have an active color attribute \"%s\"", @@ -950,7 +950,7 @@ static bool bake_targets_init_vertex_colors(Main *bmain, } Mesh *me = ob->data; - if (BKE_id_attributes_active_color_get(&me->id) == NULL) { + if (!BKE_id_attributes_color_find(&me->id, me->active_color_attribute)) { BKE_report(reports, RPT_ERROR, "No active color attribute to bake to"); return false; } @@ -1131,7 +1131,8 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) { Mesh *me = ob->data; BMEditMesh *em = me->edit_mesh; - CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id); + CustomDataLayer *active_color_layer = BKE_id_attributes_color_find(&me->id, + me->active_color_attribute); BLI_assert(active_color_layer != NULL); const eAttrDomain domain = BKE_id_attribute_domain(&me->id, active_color_layer); diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index 2401fdf2d93..3a98108989e 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -858,6 +858,28 @@ static bool modifier_apply_shape(Main *bmain, return true; } +static void remove_invalid_attribute_strings(Mesh &mesh) +{ + using namespace blender; + bke::AttributeAccessor attributes = mesh.attributes(); + if (mesh.active_color_attribute) { + const std::optional meta_data = attributes.lookup_meta_data( + mesh.active_color_attribute); + if (!meta_data || !(meta_data->domain & ATTR_DOMAIN_MASK_COLOR) || + !(meta_data->data_type & CD_MASK_COLOR_ALL)) { + MEM_freeN(mesh.active_color_attribute); + } + } + if (mesh.default_color_attribute) { + const std::optional meta_data = attributes.lookup_meta_data( + mesh.default_color_attribute); + if (!meta_data || !(meta_data->domain & ATTR_DOMAIN_MASK_COLOR) || + !(meta_data->data_type & CD_MASK_COLOR_ALL)) { + MEM_freeN(mesh.default_color_attribute); + } + } +} + static bool modifier_apply_obdata( ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval) { @@ -910,6 +932,9 @@ static bool modifier_apply_obdata( /* Anonymous attributes shouldn't be available on the applied geometry. */ me->attributes_for_write().remove_anonymous(); + /* Remove strings referring to attributes if they no longer exist. */ + remove_invalid_attribute_strings(*me); + if (md_eval->type == eModifierType_Multires) { multires_customdata_delete(me); } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index 3a13f212f0d..4eeeb760b23 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -6553,10 +6553,10 @@ static CustomDataLayer *proj_paint_color_attribute_create(wmOperator *op, Object return nullptr; } - BKE_id_attributes_active_color_set(id, layer); + BKE_id_attributes_active_color_set(id, layer->name); - if (!BKE_id_attributes_render_color_get(id)) { - BKE_id_attributes_render_color_set(id, layer); + if (!BKE_id_attributes_default_color_get(id)) { + BKE_id_attributes_default_color_set(id, layer->name); } BKE_object_attributes_active_color_fill(ob, color, false); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 6306e3b31a3..db23fc564f6 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -136,14 +136,14 @@ struct NormalAnglePrecalc { /* Returns number of elements. */ static int get_vcol_elements(Mesh *me, size_t *r_elem_size) { - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - const eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); + const std::optional meta_data = me->attributes().lookup_meta_data( + me->active_color_attribute); if (r_elem_size) { - *r_elem_size = layer->type == CD_PROP_COLOR ? sizeof(float) * 4ULL : 4ULL; + *r_elem_size = meta_data->data_type == CD_PROP_COLOR ? sizeof(float[4]) : 4ULL; } - switch (domain) { + switch (meta_data->domain) { case ATTR_DOMAIN_POINT: return me->totvert; case ATTR_DOMAIN_CORNER: @@ -234,15 +234,20 @@ static void paint_last_stroke_update(Scene *scene, const float location[3]) bool vertex_paint_mode_poll(bContext *C) { const Object *ob = CTX_data_active_object(C); + if (!ob) { + return false; + } + const Mesh *mesh = static_cast(ob->data); - if (!(ob && ob->mode == OB_MODE_VERTEX_PAINT && ((const Mesh *)ob->data)->totpoly)) { + if (!(ob->mode == OB_MODE_VERTEX_PAINT && mesh->totpoly)) { return false; } - const CustomDataLayer *layer = BKE_id_attributes_active_color_get( - static_cast(ob->data)); + if (!mesh->attributes().contains(mesh->active_color_attribute)) { + return false; + } - return layer != nullptr; + return true; } static bool vertex_paint_poll_ex(bContext *C, bool check_tool) @@ -2845,8 +2850,6 @@ static void *vpaint_init_vpaint(bContext *C, { VPaintData *vpd; - size_t elem_size; - int elem_num = get_vcol_elements(me, &elem_size); /* make mode data storage */ vpd = MEM_new>("VPaintData"); @@ -2870,12 +2873,11 @@ static void *vpaint_init_vpaint(bContext *C, vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex; if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) { - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); + const GVArray attribute = me->attributes().lookup(me->active_color_attribute, domain); + vpd->smear.color_prev = MEM_malloc_arrayN(attribute.size(), attribute.type().size(), __func__); + attribute.materialize(vpd->smear.color_prev); - vpd->smear.color_prev = MEM_malloc_arrayN(elem_num, elem_size, __func__); - memcpy(vpd->smear.color_prev, layer->data, elem_size * elem_num); - - vpd->smear.color_curr = (uint *)MEM_dupallocN(vpd->smear.color_prev); + vpd->smear.color_curr = MEM_dupallocN(vpd->smear.color_prev); } /* Create projection handle */ @@ -2908,30 +2910,31 @@ static bool vpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo ED_mesh_color_ensure(me, nullptr); - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - if (!layer) { + const std::optional meta_data = me->attributes().lookup_meta_data( + me->active_color_attribute); + + if (!meta_data) { return false; } - eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); void *vpd = nullptr; - if (domain == ATTR_DOMAIN_POINT) { - if (layer->type == CD_PROP_COLOR) { + if (meta_data->domain == ATTR_DOMAIN_POINT) { + if (meta_data->data_type == CD_PROP_COLOR) { vpd = vpaint_init_vpaint( C, op, scene, depsgraph, vp, ob, me, brush); } - else if (layer->type == CD_PROP_BYTE_COLOR) { + else if (meta_data->data_type == CD_PROP_BYTE_COLOR) { vpd = vpaint_init_vpaint( C, op, scene, depsgraph, vp, ob, me, brush); } } - else if (domain == ATTR_DOMAIN_CORNER) { - if (layer->type == CD_PROP_COLOR) { + else if (meta_data->domain == ATTR_DOMAIN_CORNER) { + if (meta_data->data_type == CD_PROP_COLOR) { vpd = vpaint_init_vpaint( C, op, scene, depsgraph, vp, ob, me, brush); } - else if (layer->type == CD_PROP_BYTE_COLOR) { + else if (meta_data->data_type == CD_PROP_BYTE_COLOR) { vpd = vpaint_init_vpaint( C, op, scene, depsgraph, vp, ob, me, brush); } @@ -3753,12 +3756,16 @@ static void vpaint_do_paint(bContext *C, int totnode; PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode); - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - Color *color_data = static_cast(layer->data); + bke::GSpanAttributeWriter attribute = me->attributes_for_write().lookup_for_write_span( + me->active_color_attribute); + BLI_assert(attribute.domain == domain); + + Color *color_data = static_cast(attribute.span.data()); /* Paint those leaves. */ vpaint_paint_leaves(C, sd, vp, vpd, ob, me, color_data, nodes, totnode); + attribute.finish(); if (nodes) { MEM_freeN(nodes); } @@ -4075,98 +4082,114 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) /** \name Set Vertex Colors Operator * \{ */ -template -static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLayer *layer) +template +static void fill_bm_face_or_corner_attribute(BMesh &bm, + const T &value, + const eAttrDomain domain, + const int cd_offset, + const bool use_vert_sel) { - Mesh *me; - if (((me = BKE_mesh_from_object(ob)) == nullptr) || - (ED_mesh_color_ensure(me, nullptr) == false)) { - return false; + BMFace *f; + BMIter iter; + BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) { + BMLoop *l = f->l_first; + do { + if (!(use_vert_sel && !BM_elem_flag_test(l->v, BM_ELEM_SELECT))) { + if (domain == ATTR_DOMAIN_CORNER) { + *static_cast(BM_ELEM_CD_GET_VOID_P(l, cd_offset)) = value; + } + else if (domain == ATTR_DOMAIN_POINT) { + *static_cast(BM_ELEM_CD_GET_VOID_P(l->v, cd_offset)) = value; + } + } + } while ((l = l->next) != f->l_first); } +} - const blender::VArray select_vert = me->attributes().lookup_or_default( +template +static void fill_mesh_face_or_corner_attribute(Mesh &mesh, + const T &value, + const eAttrDomain domain, + const MutableSpan data, + const bool use_vert_sel, + const bool use_face_sel) +{ + const VArray select_vert = mesh.attributes().lookup_or_default( ".select_vert", ATTR_DOMAIN_POINT, false); - const blender::VArray select_poly = me->attributes().lookup_or_default( + const VArray select_poly = mesh.attributes().lookup_or_default( ".select_poly", ATTR_DOMAIN_FACE, false); - Color paintcol = fromFloat(paintcol_in); + const Span polys = mesh.polys(); + const Span loops = mesh.loops(); - const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - - if (me->edit_mesh) { - BMesh *bm = me->edit_mesh->bm; - BMFace *f; - BMIter iter; - - int cd_offset = -1; - - /* Find customdata offset inside of bmesh. */ - CustomData *cdata = domain == ATTR_DOMAIN_POINT ? &bm->vdata : &bm->ldata; - - for (int i = 0; i < cdata->totlayer; i++) { - if (STREQ(cdata->layers[i].name, layer->name)) { - cd_offset = layer->offset; - } + for (const int i : polys.index_range()) { + if (use_face_sel && !select_poly[i]) { + continue; } + const MPoly &poly = polys[i]; - BLI_assert(cd_offset != -1); + int j = 0; + do { + uint vidx = loops[poly.loopstart + j].v; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - Color *color; - BMLoop *l = f->l_first; - - do { - if (!(use_vert_sel && !BM_elem_flag_test(l->v, BM_ELEM_SELECT))) { - if constexpr (domain == ATTR_DOMAIN_CORNER) { - color = static_cast(BM_ELEM_CD_GET_VOID_P(l, cd_offset)); - } - else { - color = static_cast(BM_ELEM_CD_GET_VOID_P(l->v, cd_offset)); - } - - *color = paintcol; + if (!(use_vert_sel && !(select_vert[vidx]))) { + if (domain == ATTR_DOMAIN_CORNER) { + data[poly.loopstart + j] = value; } - } while ((l = l->next) != f->l_first); + else { + data[vidx] = value; + } + } + j++; + } while (j < poly.totloop); + } + + BKE_mesh_tessface_clear(&mesh); +} + +static void fill_mesh_color(Mesh &mesh, + const ColorPaint4f &color, + const StringRef attribute_name, + const bool use_vert_sel, + const bool use_face_sel) +{ + if (mesh.edit_mesh) { + BMesh *bm = mesh.edit_mesh->bm; + const std::string name = attribute_name; + const CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh.id, name.c_str()); + const eAttrDomain domain = BKE_id_attribute_domain(&mesh.id, layer); + if (layer->type == CD_PROP_COLOR) { + fill_bm_face_or_corner_attribute( + *bm, color, domain, layer->offset, use_vert_sel); + } + else if (layer->type == CD_PROP_BYTE_COLOR) { + fill_bm_face_or_corner_attribute( + *bm, color.encode(), domain, layer->offset, use_vert_sel); } } else { - Color *color_layer = static_cast(layer->data); - const Span polys = me->polys(); - const Span loops = me->loops(); - - for (const int i : polys.index_range()) { - if (use_face_sel && !select_poly[i]) { - continue; - } - const MPoly &poly = polys[i]; - - int j = 0; - do { - uint vidx = loops[poly.loopstart + j].v; - - if (!(use_vert_sel && !(select_vert[vidx]))) { - if constexpr (domain == ATTR_DOMAIN_CORNER) { - color_layer[poly.loopstart + j] = paintcol; - } - else { - color_layer[vidx] = paintcol; - } - } - j++; - } while (j < poly.totloop); + bke::GSpanAttributeWriter attribute = mesh.attributes_for_write().lookup_for_write_span( + attribute_name); + if (attribute.span.type().is()) { + fill_mesh_face_or_corner_attribute( + mesh, + color, + attribute.domain, + attribute.span.typed().cast(), + use_vert_sel, + use_face_sel); } - - /* remove stale me->mcol, will be added later */ - BKE_mesh_tessface_clear(me); + else if (attribute.span.type().is()) { + fill_mesh_face_or_corner_attribute( + mesh, + color.encode(), + attribute.domain, + attribute.span.typed().cast(), + use_vert_sel, + use_face_sel); + } + attribute.finish(); } - - DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE); - - /* NOTE: Original mesh is used for display, so tag it directly here. */ - BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL); - - return true; } /** @@ -4176,46 +4199,26 @@ static bool paint_object_attributes_active_color_fill_ex(Object *ob, ColorPaint4f fill_color, bool only_selected = true) { - Mesh *me = BKE_object_get_original_mesh(ob); + Mesh *me = BKE_mesh_from_object(ob); if (!me) { return false; } - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - if (!layer) { - return false; - } - /* Store original #Mesh.editflag. */ - const decltype(me->editflag) editflag = me->editflag; - if (!only_selected) { - me->editflag &= ~ME_EDIT_PAINT_FACE_SEL; - me->editflag &= ~ME_EDIT_PAINT_VERT_SEL; - } - eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer); - bool ok = false; - if (domain == ATTR_DOMAIN_POINT) { - if (layer->type == CD_PROP_COLOR) { - ok = vertex_color_set(ob, fill_color, layer); - } - else if (layer->type == CD_PROP_BYTE_COLOR) { - ok = vertex_color_set(ob, fill_color, layer); - } - } - else { - if (layer->type == CD_PROP_COLOR) { - ok = vertex_color_set(ob, fill_color, layer); - } - else if (layer->type == CD_PROP_BYTE_COLOR) { - ok = vertex_color_set(ob, fill_color, layer); - } - } - /* Restore #Mesh.editflag. */ - me->editflag = editflag; - return ok; + + const bool use_face_sel = only_selected ? (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0 : false; + const bool use_vert_sel = only_selected ? (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0 : false; + fill_mesh_color(*me, fill_color, me->active_color_attribute, use_vert_sel, use_face_sel); + + DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE); + + /* NOTE: Original mesh is used for display, so tag it directly here. */ + BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL); + + return true; } -extern "C" bool BKE_object_attributes_active_color_fill(Object *ob, - const float fill_color[4], - bool only_selected) +bool BKE_object_attributes_active_color_fill(Object *ob, + const float fill_color[4], + bool only_selected) { return paint_object_attributes_active_color_fill_ex(ob, ColorPaint4f(fill_color), only_selected); } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc index 09374422888..bb8a298503c 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc @@ -77,8 +77,7 @@ static bool vertex_paint_from_weight(Object *ob) return false; } - const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id); - if (active_color_layer == nullptr) { + if (!me->attributes().contains(me->active_color_attribute)) { BLI_assert_unreachable(); return false; } @@ -93,7 +92,7 @@ static bool vertex_paint_from_weight(Object *ob) bke::MutableAttributeAccessor attributes = me->attributes_for_write(); - bke::GAttributeWriter color_attribute = attributes.lookup_for_write(active_color_layer->name); + bke::GAttributeWriter color_attribute = attributes.lookup_for_write(me->active_color_attribute); if (!color_attribute) { BLI_assert_unreachable(); return false; @@ -178,25 +177,22 @@ static IndexMask get_selected_indices(const Mesh &mesh, static void face_corner_color_equalize_verts(Mesh &mesh, const IndexMask selection) { using namespace blender; - - const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id); - if (active_color_layer == nullptr) { + const StringRef name = mesh.active_color_attribute; + bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); + bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(name); + if (!attribute) { BLI_assert_unreachable(); return; } - - bke::AttributeAccessor attributes = mesh.attributes(); - - if (attributes.lookup_meta_data(active_color_layer->name)->domain == ATTR_DOMAIN_POINT) { + if (attribute.domain == ATTR_DOMAIN_POINT) { return; } - GVArray color_attribute_point = attributes.lookup(active_color_layer->name, ATTR_DOMAIN_POINT); - + GVArray color_attribute_point = attributes.lookup(name, ATTR_DOMAIN_POINT); GVArray color_attribute_corner = attributes.adapt_domain( color_attribute_point, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER); - - color_attribute_corner.materialize(selection, active_color_layer->data); + color_attribute_corner.materialize(selection, attribute.span.data()); + attribute.finish(); } static bool vertex_color_smooth(Object *ob) @@ -252,16 +248,14 @@ template static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn) { using namespace blender; - - const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id); - if (active_color_layer == nullptr) { + const StringRef name = mesh.active_color_attribute; + bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); + if (!attributes.contains(name)) { BLI_assert_unreachable(); return false; } - bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); - - bke::GAttributeWriter color_attribute = attributes.lookup_for_write(active_color_layer->name); + bke::GAttributeWriter color_attribute = attributes.lookup_for_write(name); if (!color_attribute) { BLI_assert_unreachable(); return false; diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 416f394e8ee..654083605da 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -31,6 +31,7 @@ #include "DNA_scene_types.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_colortools.h" @@ -131,10 +132,20 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, PBVHVertRef vertex) bool SCULPT_has_loop_colors(const Object *ob) { + using namespace blender; Mesh *me = BKE_object_get_original_mesh(ob); - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); - - return layer && BKE_id_attribute_domain(&me->id, layer) == ATTR_DOMAIN_CORNER; + const std::optional meta_data = me->attributes().lookup_meta_data( + me->active_color_attribute); + if (!meta_data) { + return false; + } + if (meta_data->domain != ATTR_DOMAIN_CORNER) { + return false; + } + if (!(CD_TYPE_AS_MASK(meta_data->data_type) & CD_MASK_COLOR_ALL)) { + return false; + } + return true; } bool SCULPT_has_colors(const SculptSession *ss) diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index ef8339d8971..e5cb9c924b6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1860,7 +1860,7 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr } if (layer) { - BKE_id_attributes_active_color_set(&me->id, layer); + BKE_id_attributes_active_color_set(&me->id, layer->name); if (ob->sculpt && ob->sculpt->pbvh) { BKE_pbvh_update_active_vcol(ob->sculpt->pbvh, me); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 1c51ff02aaf..fa93a44af66 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -26,6 +26,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_attribute.h" #include "BKE_collection.h" #include "BKE_customdata.h" #include "BKE_global.h" @@ -606,7 +607,8 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) &mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, mesh->totloop, "Color"); MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named( &mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, mesh->totloop, "Alpha"); - CustomData_set_layer_active(&mesh->ldata, CD_PROP_BYTE_COLOR, 0); + BKE_id_attributes_active_color_set( + &mesh->id, CustomData_get_layer_name(&mesh->ldata, CD_PROP_BYTE_COLOR, 0)); mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList"); for (const auto item : group->materials.items()) { diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 57a4ae70b5f..2e6fb87e823 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -1125,6 +1125,15 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, } }); + if (first_mesh.active_color_attribute) { + MEM_SAFE_FREE(dst_mesh->active_color_attribute); + dst_mesh->active_color_attribute = BLI_strdup(first_mesh.active_color_attribute); + } + if (first_mesh.default_color_attribute) { + MEM_SAFE_FREE(dst_mesh->default_color_attribute); + dst_mesh->default_color_attribute = BLI_strdup(first_mesh.default_color_attribute); + } + /* Tag modified attributes. */ for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) { dst_attribute.finish(); diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index 48a5c52bebc..cebdab2c415 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -111,26 +111,6 @@ void UI_GetThemeColorShadeAlpha4ubv(int /*colorid*/, /** \name Stubs of BKE_attribute.h * \{ */ -void BKE_id_attribute_copy_domains_temp(short /*id_type*/, - const struct CustomData * /*vdata*/, - const struct CustomData * /*edata*/, - const struct CustomData * /*ldata*/, - const struct CustomData * /*pdata*/, - const struct CustomData * /*cdata*/, - struct ID * /*r_id*/) -{ -} - -struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID * /*id*/) -{ - return nullptr; -} - -struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID * /*id*/) -{ - return nullptr; -} - eAttrDomain BKE_id_attribute_domain(const struct ID * /*id*/, const struct CustomDataLayer * /*layer*/) { diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 3f676fa9df9..436d919f8d5 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -16,6 +16,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_attribute.h" #include "BKE_customdata.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -486,7 +487,8 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) CustomData_add_layer_named( &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, colname.c_str()); } - CustomData_set_layer_active(&me->ldata, CD_PROP_BYTE_COLOR, 0); + BKE_id_attributes_active_color_set( + &me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0)); } } } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index 599357ece37..909c179dda3 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -251,14 +251,11 @@ void OBJWriter::write_vertex_coords(FormatHandler &fh, const int tot_count = obj_mesh_data.tot_vertices(); const Mesh *mesh = obj_mesh_data.get_mesh(); - const CustomDataLayer *colors_layer = nullptr; - if (write_colors) { - colors_layer = BKE_id_attributes_active_color_get(&mesh->id); - } - if (write_colors && (colors_layer != nullptr)) { + const StringRef name = mesh->active_color_attribute; + if (write_colors && !name.is_empty()) { const bke::AttributeAccessor attributes = mesh->attributes(); const VArray attribute = attributes.lookup_or_default( - colors_layer->name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f}); + name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f}); BLI_assert(tot_count == attribute.size()); obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler &buf, int i) { diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index b2b49457051..42293a9b992 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -376,6 +376,7 @@ void MeshFromGeometry::create_colors(Mesh *mesh) /* This block is suitable, use colors from it. */ CustomDataLayer *color_layer = BKE_id_attribute_new( &mesh->id, "Color", CD_PROP_COLOR, ATTR_DOMAIN_POINT, nullptr); + BKE_id_attributes_active_color_set(&mesh->id, color_layer->name); float4 *colors = (float4 *)color_layer->data; int offset = mesh_geometry_.vertex_index_min_ - block.start_vertex_index; for (int i = 0, n = mesh_geometry_.get_vertex_count(); i != n; ++i) { diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 0355ed3febe..5a534fa7904 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -244,8 +244,10 @@ enum { CD_FLAG_EXTERNAL = (1 << 3), /* Indicates external data is read into memory */ CD_FLAG_IN_MEMORY = (1 << 4), +#ifdef DNA_DEPRECATED_ALLOW CD_FLAG_COLOR_ACTIVE = (1 << 5), CD_FLAG_COLOR_RENDER = (1 << 6) +#endif }; /* Limits */ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 7a28485c768..5e04c23445d 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -151,6 +151,11 @@ typedef struct Mesh { * default and Face Sets can be used without affecting the color of the mesh. */ int face_sets_color_default; + /** The color attribute currently selected in the list and edited by a user. */ + char *active_color_attribute; + /** The color attribute used by default (i.e. for rendering) if no name is given explicitly. */ + char *default_color_attribute; + /** * User-defined symmetry flag (#eMeshSymmetryType) that causes editing operations to maintain * symmetrical geometry. Supported by operations such as transform and weight-painting. diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index d65159af28a..1fd7ce85125 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -560,7 +560,10 @@ static void rna_AttributeGroup_update_active(Main *bmain, Scene *scene, PointerR static PointerRNA rna_AttributeGroup_active_color_get(PointerRNA *ptr) { ID *id = ptr->owner_id; - CustomDataLayer *layer = BKE_id_attributes_active_color_get(id); + CustomDataLayer *layer = BKE_id_attribute_search(ptr->owner_id, + BKE_id_attributes_active_color_name(id), + CD_MASK_COLOR_ALL, + ATTR_DOMAIN_MASK_COLOR); PointerRNA attribute_ptr; RNA_pointer_create(id, &RNA_Attribute, layer, &attribute_ptr); @@ -573,13 +576,16 @@ static void rna_AttributeGroup_active_color_set(PointerRNA *ptr, { ID *id = ptr->owner_id; CustomDataLayer *layer = attribute_ptr.data; - - BKE_id_attributes_active_color_set(id, layer); + BKE_id_attributes_active_color_set(id, layer->name); } static int rna_AttributeGroup_active_color_index_get(PointerRNA *ptr) { - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(ptr->owner_id); + const CustomDataLayer *layer = BKE_id_attribute_search( + ptr->owner_id, + BKE_id_attributes_active_color_name(ptr->owner_id), + CD_MASK_COLOR_ALL, + ATTR_DOMAIN_MASK_COLOR); return BKE_id_attribute_to_index( ptr->owner_id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); @@ -595,7 +601,7 @@ static void rna_AttributeGroup_active_color_index_set(PointerRNA *ptr, int value return; } - BKE_id_attributes_active_color_set(ptr->owner_id, layer); + BKE_id_attributes_active_color_set(ptr->owner_id, layer->name); } static void rna_AttributeGroup_active_color_index_range( @@ -623,7 +629,8 @@ static void rna_AttributeGroup_update_active_color(Main *UNUSED(bmain), static int rna_AttributeGroup_render_color_index_get(PointerRNA *ptr) { - CustomDataLayer *layer = BKE_id_attributes_render_color_get(ptr->owner_id); + const CustomDataLayer *layer = BKE_id_attributes_color_find( + ptr->owner_id, BKE_id_attributes_default_color_name(ptr->owner_id)); return BKE_id_attribute_to_index( ptr->owner_id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); @@ -639,7 +646,7 @@ static void rna_AttributeGroup_render_color_index_set(PointerRNA *ptr, int value return; } - BKE_id_attributes_render_color_set(ptr->owner_id, layer); + BKE_id_attributes_default_color_set(ptr->owner_id, layer->name); } static void rna_AttributeGroup_render_color_index_range( @@ -655,43 +662,61 @@ static void rna_AttributeGroup_render_color_index_range( static void rna_AttributeGroup_default_color_name_get(PointerRNA *ptr, char *value) { const ID *id = ptr->owner_id; - const CustomDataLayer *layer = BKE_id_attributes_render_color_get(id); - if (!layer) { + const char *name = BKE_id_attributes_default_color_name(id); + if (!name) { value[0] = '\0'; return; } - BLI_strncpy(value, layer->name, MAX_CUSTOMDATA_LAYER_NAME); + BLI_strncpy(value, name, MAX_CUSTOMDATA_LAYER_NAME); } static int rna_AttributeGroup_default_color_name_length(PointerRNA *ptr) { const ID *id = ptr->owner_id; - const CustomDataLayer *layer = BKE_id_attributes_render_color_get(id); - if (!layer) { - return 0; + const char *name = BKE_id_attributes_default_color_name(id); + return name ? strlen(name) : 0; +} + +static void rna_AttributeGroup_default_color_name_set(PointerRNA *ptr, const char *value) +{ + ID *id = ptr->owner_id; + if (GS(id->name) == ID_ME) { + Mesh *mesh = (Mesh *)id; + MEM_SAFE_FREE(mesh->default_color_attribute); + if (value[0]) { + mesh->default_color_attribute = BLI_strdup(value); + } } - return strlen(layer->name); } static void rna_AttributeGroup_active_color_name_get(PointerRNA *ptr, char *value) { const ID *id = ptr->owner_id; - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(id); - if (!layer) { + const char *name = BKE_id_attributes_active_color_name(id); + if (!name) { value[0] = '\0'; return; } - BLI_strncpy(value, layer->name, MAX_CUSTOMDATA_LAYER_NAME); + BLI_strncpy(value, name, MAX_CUSTOMDATA_LAYER_NAME); } static int rna_AttributeGroup_active_color_name_length(PointerRNA *ptr) { const ID *id = ptr->owner_id; - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(id); - if (!layer) { - return 0; + const char *name = BKE_id_attributes_active_color_name(id); + return name ? strlen(name) : 0; +} + +static void rna_AttributeGroup_active_color_name_set(PointerRNA *ptr, const char *value) +{ + ID *id = ptr->owner_id; + if (GS(id->name) == ID_ME) { + Mesh *mesh = (Mesh *)id; + MEM_SAFE_FREE(mesh->default_color_attribute); + if (value[0]) { + mesh->default_color_attribute = BLI_strdup(value); + } } - return strlen(layer->name); } #else @@ -1160,7 +1185,7 @@ static void rna_def_attribute_group(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_AttributeGroup_default_color_name_get", "rna_AttributeGroup_default_color_name_length", - NULL); + "rna_AttributeGroup_default_color_name_set"); RNA_def_property_ui_text( prop, "Default Color Attribute", @@ -1172,7 +1197,7 @@ static void rna_def_attribute_group(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_AttributeGroup_active_color_name_get", "rna_AttributeGroup_active_color_name_length", - NULL); + "rna_AttributeGroup_active_color_name_set"); RNA_def_property_ui_text(prop, "Active Color Attribute", "The name of the active color attribute for display and editing"); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 1141d7e75a4..71a4a4b37f4 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -171,7 +171,7 @@ static void rna_Material_active_paint_texture_index_update(bContext *C, PointerR Mesh *mesh = ob->data; CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh->id, slot->attribute_name); if (layer != NULL) { - BKE_id_attributes_active_color_set(&mesh->id, layer); + BKE_id_attributes_active_color_set(&mesh->id, layer->name); } DEG_id_tag_update(&ob->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 2ca465c95b8..7351ca1d8ca 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1037,12 +1037,16 @@ static int rna_MeshLoopColorLayer_data_length(PointerRNA *ptr) static bool rna_MeshLoopColorLayer_active_render_get(PointerRNA *ptr) { - return rna_CustomDataLayer_active_get(ptr, rna_mesh_ldata(ptr), CD_PROP_BYTE_COLOR, 1); + const Mesh *mesh = rna_mesh(ptr); + const CustomDataLayer *layer = (const CustomDataLayer *)ptr->data; + return mesh->default_color_attribute && STREQ(mesh->default_color_attribute, layer->name); } static bool rna_MeshLoopColorLayer_active_get(PointerRNA *ptr) { - return rna_CustomDataLayer_active_get(ptr, rna_mesh_ldata(ptr), CD_PROP_BYTE_COLOR, 0); + const Mesh *mesh = rna_mesh(ptr); + const CustomDataLayer *layer = (const CustomDataLayer *)ptr->data; + return mesh->active_color_attribute && STREQ(mesh->active_color_attribute, layer->name); } static void rna_MeshLoopColorLayer_active_render_set(PointerRNA *ptr, bool value) @@ -1077,12 +1081,16 @@ static int rna_MeshVertColorLayer_data_length(PointerRNA *ptr) static bool rna_MeshVertColorLayer_active_render_get(PointerRNA *ptr) { - return rna_CustomDataLayer_active_get(ptr, rna_mesh_vdata(ptr), CD_PROP_COLOR, 1); + const Mesh *mesh = rna_mesh(ptr); + const CustomDataLayer *layer = (const CustomDataLayer *)ptr->data; + return mesh->default_color_attribute && STREQ(mesh->default_color_attribute, layer->name); } static bool rna_MeshVertColorLayer_active_get(PointerRNA *ptr) { - return rna_CustomDataLayer_active_get(ptr, rna_mesh_vdata(ptr), CD_PROP_COLOR, 0); + const Mesh *mesh = rna_mesh(ptr); + const CustomDataLayer *layer = (const CustomDataLayer *)ptr->data; + return mesh->active_color_attribute && STREQ(mesh->active_color_attribute, layer->name); } static void rna_MeshVertColorLayer_active_render_set(PointerRNA *ptr, bool value)