Fix #103410: name collisions between vertex groups and attributes #109910

Merged
Philipp Oeser merged 8 commits from lichtwerk/blender:103410 into main 2023-08-08 10:11:18 +02:00
4 changed files with 48 additions and 20 deletions

View File

@ -17,6 +17,7 @@
extern "C" {
#endif
struct bDeformGroup;
struct CustomData;
struct CustomDataLayer;
struct ID;
@ -117,6 +118,12 @@ void BKE_id_attributes_default_color_set(struct ID *id, const char *name);
const struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
typedef struct AttributeAndDefgroupUniqueNameData {
struct ID *id;
lichtwerk marked this conversation as resolved
Review

This should be forward declared at the top of the file right before CustomData

This should be forward declared at the top of the file right before `CustomData`
struct bDeformGroup *dg;
} AttributeAndDefgroupUniqueNameData;
bool BKE_id_attribute_and_defgroup_unique_name_check(void *arg, const char *name);
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer);

View File

@ -89,6 +89,7 @@ int *BKE_object_defgroup_flip_map_single(const struct Object *ob,
int BKE_object_defgroup_flip_index(const struct Object *ob, int index, bool use_default);
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name);
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
bool BKE_defgroup_unique_name_check(void *arg, const char *name);
struct MDeformWeight *BKE_defvert_find_index(const struct MDeformVert *dv, int defgroup);
/**

View File

@ -31,6 +31,7 @@
#include "BKE_attribute.hh"
#include "BKE_curves.hh"
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.hh"
#include "BKE_pointcloud.h"
@ -223,13 +224,14 @@ bool BKE_id_attribute_rename(ID *id,
return true;
}
struct AttrUniqueData {
ID *id;
};
static bool unique_name_cb(void *arg, const char *name)
bool BKE_id_attribute_and_defgroup_unique_name_check(void *arg, const char *name)
{
AttrUniqueData *data = (AttrUniqueData *)arg;
AttributeAndDefgroupUniqueNameData *data = static_cast<AttributeAndDefgroupUniqueNameData *>(
arg);
if (BKE_defgroup_unique_name_check(data, name)) {
lichtwerk marked this conversation as resolved
Review

This comment basically says the same thing that the BKE_defgroup_unique_name_check function name does. Best to let the code do the talking here I think-- comments can describe the reasoning, etc. but just saying what the code does on the next line usually shouldn't be necessary

This comment basically says the same thing that the `BKE_defgroup_unique_name_check` function name does. Best to let the code do the talking here I think-- comments can describe the reasoning, etc. but just saying what the code does on the next line usually shouldn't be necessary
return true;
}
DomainInfo info[ATTR_DOMAIN_NUM];
get_domains(data->id, info);
@ -254,15 +256,18 @@ static bool unique_name_cb(void *arg, const char *name)
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
{
AttrUniqueData data{id};
AttributeAndDefgroupUniqueNameData data{id, nullptr};
const int name_maxncpy = CustomData_name_maxncpy_calc(name);
/* Set default name if none specified.
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
BLI_strncpy_utf8(outname, (name && name[0]) ? name : IFACE_("Attribute"), name_maxncpy);
/* Avoid name collisions with vertex groups and other attributes. */
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
return BLI_uniquename_cb(unique_name_cb, &data, defname, '.', outname, name_maxncpy);
return BLI_uniquename_cb(
BKE_id_attribute_and_defgroup_unique_name_check, &data, defname, '.', outname, name_maxncpy);
}
CustomDataLayer *BKE_id_attribute_new(ID *id,
@ -301,6 +306,10 @@ CustomDataLayer *BKE_id_attribute_new(ID *id,
attributes->add(uniquename, domain, eCustomDataType(type), AttributeInitDefaultValue());
const int index = CustomData_get_named_layer_index(customdata, type, uniquename);
if (index == -1) {
BKE_reportf(reports, RPT_WARNING, "Layer '%s' could not be created", uniquename);
}
lichtwerk marked this conversation as resolved
Review

"with a unique name" seems a bit off here, a bit like unnecessary information-- there are other things that could go wrong. And actually the unique name seems like one thing that generally shouldn't fail? When do you run into this in practice?

"with a unique name" seems a bit off here, a bit like unnecessary information-- there are other things that could go wrong. And actually the unique name seems like one thing that generally shouldn't fail? When do you run into this in practice?
Review

Yep, this was from the very first iteration where I didnt actually have the real solution implemented...

Yep, this was from the very first iteration where I didnt actually have the real solution implemented...
return (index == -1) ? nullptr : &(customdata->layers[index]);
}

View File

@ -29,6 +29,7 @@
#include "BLT_translation.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
@ -681,9 +682,9 @@ int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_d
return (flip_index == -1 && use_default) ? index : flip_index;
}
static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, ID *id)
{
const ListBase *defbase = BKE_object_defgroup_list(ob);
const ListBase *defbase = BKE_id_defgroup_list_get(id);
LISTBASE_FOREACH (bDeformGroup *, curdef, defbase) {
if (dg != curdef) {
@ -696,21 +697,31 @@ static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *
return false;
}
struct DeformGroupUniqueNameData {
Object *ob;
bDeformGroup *dg;
};
static bool defgroup_unique_check(void *arg, const char *name)
bool BKE_defgroup_unique_name_check(void *arg, const char *name)
{
DeformGroupUniqueNameData *data = static_cast<DeformGroupUniqueNameData *>(arg);
return defgroup_find_name_dupe(name, data->dg, data->ob);
AttributeAndDefgroupUniqueNameData *data = static_cast<AttributeAndDefgroupUniqueNameData *>(
arg);
return defgroup_find_name_dupe(name, data->dg, data->id);
}
void BKE_object_defgroup_unique_name(bDeformGroup *dg, Object *ob)
{
DeformGroupUniqueNameData data{ob, dg};
BLI_uniquename_cb(defgroup_unique_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
/* Avoid name collisions with other vertex groups and (mesh) attributes. */
if (ob->type == OB_MESH) {
Mesh *me = static_cast<Mesh *>(ob->data);
AttributeAndDefgroupUniqueNameData data{&me->id, dg};
BLI_uniquename_cb(BKE_id_attribute_and_defgroup_unique_name_check,
&data,
DATA_("Group"),
'.',
dg->name,
sizeof(dg->name));
}
else {
AttributeAndDefgroupUniqueNameData data{static_cast<ID *>(ob->data), dg};
BLI_uniquename_cb(
BKE_defgroup_unique_name_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
}
}

AttributeAndDefgroupUniqueNameData data{static_cast<ID *>(ob->data), dg};

This removes the need for the change in defgroup_find_name_dupe

`AttributeAndDefgroupUniqueNameData data{static_cast<ID *>(ob->data), dg};` This removes the need for the change in `defgroup_find_name_dupe`
float BKE_defvert_find_weight(const MDeformVert *dvert, const int defgroup)