Fix #103410: name collisions between vertex groups and attributes
These name collisions should be avoided with attributes, all sorts of
issues can arise from those. We already warned in the attributes
(but not the vertex groups) list if those were found.
Previously, creating a vertex group with the same name as an already
existing attribute would allow this (and give said warning), and creating
an attribute with the same name as an already existing vertex group
would silently fail (as in: not return a layer) -- and then due to an oversight
in 101d04f41f (which assumed a valid layer would always be returned
by `BKE_id_attribute_new`) would even crash.
Now name collisions between vertex groups and attributes are avoided,
unique names will be found across attributes and vertex groups if either
`BKE_id_attribute_calc_unique_name` or `BKE_object_defgroup_unique_name`
is called.
This is done by unifying the checks and callbacks for both into a single.
Pull Request: https://projects.blender.org/blender/blender/pulls/109910
This commit is contained in:
committed by
Philipp Oeser
parent
ecb3262bf0
commit
12ef20990b
@@ -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;
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
float BKE_defvert_find_weight(const MDeformVert *dvert, const int defgroup)
|
||||
|
||||
Reference in New Issue
Block a user