Fix #103410: name collisions between vertex groups and attributes #109910
|
@ -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
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
/**
|
||||
|
|
|
@ -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
Hans Goudey
commented
This comment basically says the same thing that the 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
Hans Goudey
commented
"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?
Philipp Oeser
commented
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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
Hans Goudey
commented
This removes the need for the change in `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)
|
||||
|
|
This should be forward declared at the top of the file right before
CustomData