Refactor: BLI: use FunctionRef in BLI_uniquename api
This simplifies the API usage, removes the need for intermediate structs and reduces the overall amount of code. Pull Request: https://projects.blender.org/blender/blender/pulls/137300
This commit is contained in:
@@ -373,30 +373,20 @@ const Slot *Action::slot_for_handle(const slot_handle_t handle) const
|
||||
|
||||
static void slot_identifier_ensure_unique(Action &action, Slot &slot)
|
||||
{
|
||||
/* Cannot capture parameters by reference in the lambda, as that would change its signature
|
||||
* and no longer be compatible with BLI_uniquename_cb(). That's why this struct is necessary. */
|
||||
struct DupNameCheckData {
|
||||
Action &action;
|
||||
Slot &slot;
|
||||
};
|
||||
DupNameCheckData check_data = {action, slot};
|
||||
|
||||
auto check_name_is_used = [](void *arg, const char *name) -> bool {
|
||||
DupNameCheckData *data = static_cast<DupNameCheckData *>(arg);
|
||||
for (const Slot *slot : data->action.slots()) {
|
||||
if (slot == &data->slot) {
|
||||
auto check_name_is_used = [&](const StringRef name) -> bool {
|
||||
for (const Slot *slot_iter : action.slots()) {
|
||||
if (slot_iter == &slot) {
|
||||
/* Don't compare against the slot that's being renamed. */
|
||||
continue;
|
||||
}
|
||||
if (STREQ(slot->identifier, name)) {
|
||||
if (slot_iter->identifier == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
BLI_uniquename_cb(
|
||||
check_name_is_used, &check_data, "", '.', slot.identifier, sizeof(slot.identifier));
|
||||
BLI_uniquename_cb(check_name_is_used, "", '.', slot.identifier, sizeof(slot.identifier));
|
||||
}
|
||||
|
||||
void Action::slot_display_name_set(Main &bmain, Slot &slot, StringRefNull new_display_name)
|
||||
|
||||
@@ -123,26 +123,18 @@ void ANIM_armature_runtime_free(bArmature *armature)
|
||||
*/
|
||||
static void bonecoll_ensure_name_unique(bArmature *armature, BoneCollection *bcoll)
|
||||
{
|
||||
struct DupNameCheckData {
|
||||
bArmature *arm;
|
||||
BoneCollection *bcoll;
|
||||
};
|
||||
|
||||
/* Cannot capture armature & bcoll by reference in the lambda, as that would change its signature
|
||||
* and no longer be compatible with BLI_uniquename_cb(). */
|
||||
auto bonecoll_name_is_duplicate = [](void *arg, const char *name) -> bool {
|
||||
DupNameCheckData *data = static_cast<DupNameCheckData *>(arg);
|
||||
for (BoneCollection *bcoll : data->arm->collections_span()) {
|
||||
if (bcoll != data->bcoll && STREQ(bcoll->name, name)) {
|
||||
auto bonecoll_name_is_duplicate = [&](const blender::StringRef name) -> bool {
|
||||
for (BoneCollection *bcoll_iter : armature->collections_span()) {
|
||||
if (bcoll_iter != bcoll && bcoll_iter->name == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
DupNameCheckData check_data = {armature, bcoll};
|
||||
BLI_uniquename_cb(bonecoll_name_is_duplicate,
|
||||
&check_data,
|
||||
DATA_(bonecoll_default_name),
|
||||
'.',
|
||||
bcoll->name,
|
||||
|
||||
@@ -4404,18 +4404,6 @@ static bool cd_layer_find_dupe(CustomData *data,
|
||||
return false;
|
||||
}
|
||||
|
||||
struct CustomDataUniqueCheckData {
|
||||
CustomData *data;
|
||||
eCustomDataType type;
|
||||
int index;
|
||||
};
|
||||
|
||||
static bool customdata_unique_check(void *arg, const char *name)
|
||||
{
|
||||
CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg);
|
||||
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
|
||||
}
|
||||
|
||||
int CustomData_name_maxncpy_calc(const blender::StringRef name)
|
||||
{
|
||||
if (name.startswith(".")) {
|
||||
@@ -4436,8 +4424,6 @@ void CustomData_set_layer_unique_name(CustomData *data, const int index)
|
||||
CustomDataLayer *nlayer = &data->layers[index];
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(nlayer->type));
|
||||
|
||||
CustomDataUniqueCheckData data_arg{data, eCustomDataType(nlayer->type), index};
|
||||
|
||||
if (!typeInfo->defaultname) {
|
||||
return;
|
||||
}
|
||||
@@ -4451,7 +4437,14 @@ void CustomData_set_layer_unique_name(CustomData *data, const int index)
|
||||
}
|
||||
|
||||
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
|
||||
BLI_uniquename_cb(customdata_unique_check, &data_arg, defname, '.', nlayer->name, name_maxncpy);
|
||||
BLI_uniquename_cb(
|
||||
[&](const StringRef name) {
|
||||
return cd_layer_find_dupe(data, name, eCustomDataType(nlayer->type), index);
|
||||
},
|
||||
defname,
|
||||
'.',
|
||||
nlayer->name,
|
||||
name_maxncpy);
|
||||
}
|
||||
|
||||
void CustomData_validate_layer_name(const CustomData *data,
|
||||
|
||||
@@ -738,16 +738,14 @@ static bool defgroup_find_name_dupe(const StringRef name, bDeformGroup *dg, Obje
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool defgroup_unique_check(void *arg, const char *name)
|
||||
{
|
||||
DeformGroupUniqueNameData *data = static_cast<DeformGroupUniqueNameData *>(arg);
|
||||
return defgroup_find_name_dupe(name, data->dg, data->ob);
|
||||
}
|
||||
|
||||
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));
|
||||
BLI_uniquename_cb(
|
||||
[&](const blender::StringRef name) { return defgroup_find_name_dupe(name, dg, ob); },
|
||||
DATA_("Group"),
|
||||
'.',
|
||||
dg->name,
|
||||
sizeof(dg->name));
|
||||
}
|
||||
|
||||
void BKE_object_defgroup_set_name(bDeformGroup *dg, Object *ob, const char *new_name)
|
||||
|
||||
@@ -353,9 +353,9 @@ bool dynamicPaint_outputLayerExists(DynamicPaintSurface *surface, Object *ob, in
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool surface_duplicateOutputExists(void *arg, const char *name)
|
||||
static bool surface_duplicateOutputExists(DynamicPaintSurface *t_surface,
|
||||
const blender::StringRefNull name)
|
||||
{
|
||||
DynamicPaintSurface *t_surface = static_cast<DynamicPaintSurface *>(arg);
|
||||
DynamicPaintSurface *surface = static_cast<DynamicPaintSurface *>(
|
||||
t_surface->canvas->surfaces.first);
|
||||
|
||||
@@ -363,8 +363,8 @@ static bool surface_duplicateOutputExists(void *arg, const char *name)
|
||||
if (surface != t_surface && surface->type == t_surface->type &&
|
||||
surface->format == t_surface->format)
|
||||
{
|
||||
if ((surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) ||
|
||||
(surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)))
|
||||
if ((surface->output_name[0] != '\0' && !BLI_path_cmp(name.c_str(), surface->output_name)) ||
|
||||
(surface->output_name2[0] != '\0' && !BLI_path_cmp(name.c_str(), surface->output_name2)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -375,34 +375,29 @@ static bool surface_duplicateOutputExists(void *arg, const char *name)
|
||||
|
||||
static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output)
|
||||
{
|
||||
auto is_unique_fn = [&](const blender::StringRefNull check_name) {
|
||||
return surface_duplicateOutputExists(surface, check_name);
|
||||
};
|
||||
|
||||
char name[64];
|
||||
STRNCPY(name, basename); /* in case basename is surface->name use a copy */
|
||||
if (output == 0) {
|
||||
BLI_uniquename_cb(surface_duplicateOutputExists,
|
||||
surface,
|
||||
name,
|
||||
'.',
|
||||
surface->output_name,
|
||||
sizeof(surface->output_name));
|
||||
BLI_uniquename_cb(is_unique_fn, name, '.', surface->output_name, sizeof(surface->output_name));
|
||||
}
|
||||
else if (output == 1) {
|
||||
BLI_uniquename_cb(surface_duplicateOutputExists,
|
||||
surface,
|
||||
name,
|
||||
'.',
|
||||
surface->output_name2,
|
||||
sizeof(surface->output_name2));
|
||||
BLI_uniquename_cb(
|
||||
is_unique_fn, name, '.', surface->output_name2, sizeof(surface->output_name2));
|
||||
}
|
||||
}
|
||||
|
||||
static bool surface_duplicateNameExists(void *arg, const char *name)
|
||||
static bool surface_duplicateNameExists(DynamicPaintSurface *t_surface,
|
||||
const blender::StringRefNull name)
|
||||
{
|
||||
DynamicPaintSurface *t_surface = static_cast<DynamicPaintSurface *>(arg);
|
||||
DynamicPaintSurface *surface = static_cast<DynamicPaintSurface *>(
|
||||
t_surface->canvas->surfaces.first);
|
||||
|
||||
for (; surface; surface = surface->next) {
|
||||
if (surface != t_surface && STREQ(name, surface->name)) {
|
||||
if (surface != t_surface && STREQ(name.c_str(), surface->name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -414,7 +409,13 @@ void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char
|
||||
char name[64];
|
||||
STRNCPY_UTF8(name, basename); /* in case basename is surface->name use a copy */
|
||||
BLI_uniquename_cb(
|
||||
surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
|
||||
[&](const blender::StringRefNull check_name) {
|
||||
return surface_duplicateNameExists(surface, check_name);
|
||||
},
|
||||
name,
|
||||
'.',
|
||||
surface->name,
|
||||
sizeof(surface->name));
|
||||
}
|
||||
|
||||
void dynamicPaintSurface_updateType(DynamicPaintSurface *surface)
|
||||
|
||||
@@ -1895,11 +1895,6 @@ bool BKE_nlastrip_has_curves_for_property(const PointerRNA *ptr, const PropertyR
|
||||
|
||||
/* Sanity Validation ------------------------------------ */
|
||||
|
||||
static bool nla_editbone_name_check(void *arg, const char *name)
|
||||
{
|
||||
return BLI_ghash_haskey((GHash *)arg, (const void *)name);
|
||||
}
|
||||
|
||||
void BKE_nlastrip_validate_name(AnimData *adt, NlaStrip *strip)
|
||||
{
|
||||
GHash *gh;
|
||||
@@ -1950,12 +1945,14 @@ void BKE_nlastrip_validate_name(AnimData *adt, NlaStrip *strip)
|
||||
* - In an extreme case, it might not be able to find a name,
|
||||
* but then everything else in Blender would fail too :).
|
||||
*/
|
||||
BLI_uniquename_cb(nla_editbone_name_check,
|
||||
(void *)gh,
|
||||
DATA_("NlaStrip"),
|
||||
'.',
|
||||
strip->name,
|
||||
sizeof(strip->name));
|
||||
BLI_uniquename_cb(
|
||||
[&](const blender::StringRefNull check_name) {
|
||||
return BLI_ghash_haskey(gh, check_name.c_str());
|
||||
},
|
||||
DATA_("NlaStrip"),
|
||||
'.',
|
||||
strip->name,
|
||||
sizeof(strip->name));
|
||||
|
||||
/* free the hash... */
|
||||
BLI_ghash_free(gh, nullptr, nullptr);
|
||||
|
||||
@@ -1952,17 +1952,6 @@ bNodeSocket *node_find_enabled_output_socket(bNode &node, const StringRef name)
|
||||
return node_find_enabled_socket(node, SOCK_OUT, name);
|
||||
}
|
||||
|
||||
static bool unique_identifier_check(void *arg, const char *identifier)
|
||||
{
|
||||
const ListBase *lb = static_cast<const ListBase *>(arg);
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
|
||||
if (STREQ(sock->identifier, identifier)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bNodeSocket *make_socket(bNodeTree *ntree,
|
||||
bNode * /*node*/,
|
||||
const int in_out,
|
||||
@@ -1983,7 +1972,18 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
|
||||
}
|
||||
/* Make the identifier unique. */
|
||||
BLI_uniquename_cb(
|
||||
unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
|
||||
[&](const StringRef check_name) {
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
|
||||
if (sock->identifier == check_name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
"socket",
|
||||
'_',
|
||||
auto_identifier,
|
||||
sizeof(auto_identifier));
|
||||
|
||||
bNodeSocket *sock = MEM_callocN<bNodeSocket>(__func__);
|
||||
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
||||
@@ -4432,42 +4432,26 @@ std::optional<eNodeSocketDatatype> grid_type_to_socket_type(const VolumeGridType
|
||||
}
|
||||
}
|
||||
|
||||
struct SocketTemplateIdentifierCallbackData {
|
||||
bNodeSocketTemplate *list;
|
||||
bNodeSocketTemplate *ntemp;
|
||||
};
|
||||
|
||||
static bool unique_socket_template_identifier_check(void *arg, const char *name)
|
||||
{
|
||||
const SocketTemplateIdentifierCallbackData *data =
|
||||
static_cast<const SocketTemplateIdentifierCallbackData *>(arg);
|
||||
|
||||
for (bNodeSocketTemplate *ntemp = data->list; ntemp->type >= 0; ntemp++) {
|
||||
if (ntemp != data->ntemp) {
|
||||
if (STREQ(ntemp->identifier, name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void unique_socket_template_identifier(bNodeSocketTemplate *list,
|
||||
bNodeSocketTemplate *ntemp,
|
||||
const char defname[],
|
||||
const char delim)
|
||||
{
|
||||
SocketTemplateIdentifierCallbackData data;
|
||||
data.list = list;
|
||||
data.ntemp = ntemp;
|
||||
|
||||
BLI_uniquename_cb(unique_socket_template_identifier_check,
|
||||
&data,
|
||||
defname,
|
||||
delim,
|
||||
ntemp->identifier,
|
||||
sizeof(ntemp->identifier));
|
||||
BLI_uniquename_cb(
|
||||
[&](const StringRef check_name) {
|
||||
for (bNodeSocketTemplate *ntemp_iter = list; ntemp_iter->type >= 0; ntemp_iter++) {
|
||||
if (ntemp_iter != ntemp) {
|
||||
if (ntemp_iter->identifier == check_name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
defname,
|
||||
delim,
|
||||
ntemp->identifier,
|
||||
sizeof(ntemp->identifier));
|
||||
}
|
||||
|
||||
void node_type_socket_templates(bNodeType *ntype,
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
struct ListBase;
|
||||
|
||||
using UniquenameCheckCallback = bool (*)(void *arg, const char *name);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/** \name String Replace
|
||||
* \{ */
|
||||
@@ -147,18 +145,16 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
||||
* incrementing its numeric suffix as necessary.
|
||||
*
|
||||
* \param unique_check: Return true if name is not unique
|
||||
* \param arg: Additional arg to unique_check--meaning is up to caller
|
||||
* \param defname: To initialize name if latter is empty
|
||||
* \param delim: Delimits numeric suffix in name
|
||||
* \param name: Name to be ensured unique
|
||||
* \param name_maxncpy: Maximum length of name area
|
||||
*/
|
||||
void BLI_uniquename_cb(UniquenameCheckCallback unique_check,
|
||||
void *arg,
|
||||
void BLI_uniquename_cb(blender::FunctionRef<bool(blender::StringRefNull)> unique_check,
|
||||
const char *defname,
|
||||
char delim,
|
||||
char *name,
|
||||
size_t name_maxncpy) ATTR_NONNULL(1, 3, 5);
|
||||
size_t name_maxncpy) ATTR_NONNULL(2, 4);
|
||||
|
||||
/**
|
||||
* Ensures name is unique (according to criteria specified by caller in unique_check callback),
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.hh"
|
||||
@@ -397,8 +398,7 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
||||
|
||||
/* Unique name utils. */
|
||||
|
||||
void BLI_uniquename_cb(UniquenameCheckCallback unique_check,
|
||||
void *arg,
|
||||
void BLI_uniquename_cb(blender::FunctionRef<bool(blender::StringRefNull)> unique_check,
|
||||
const char *defname,
|
||||
char delim,
|
||||
char *name,
|
||||
@@ -410,7 +410,7 @@ void BLI_uniquename_cb(UniquenameCheckCallback unique_check,
|
||||
BLI_strncpy(name, defname, name_maxncpy);
|
||||
}
|
||||
|
||||
if (unique_check(arg, name)) {
|
||||
if (unique_check(name)) {
|
||||
char numstr[16];
|
||||
char *tempname = static_cast<char *>(alloca(name_maxncpy));
|
||||
char *left = static_cast<char *>(alloca(name_maxncpy));
|
||||
@@ -430,7 +430,7 @@ void BLI_uniquename_cb(UniquenameCheckCallback unique_check,
|
||||
tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_maxncpy - numlen);
|
||||
memcpy(tempname_buf, numstr, numlen + 1);
|
||||
}
|
||||
} while (unique_check(arg, tempname));
|
||||
} while (unique_check(tempname));
|
||||
|
||||
BLI_strncpy(name, tempname, name_maxncpy);
|
||||
}
|
||||
@@ -468,45 +468,6 @@ std::string BLI_uniquename_cb(blender::FunctionRef<bool(blender::StringRef)> uni
|
||||
return new_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic function to set a unique name. It is only designed to be used in situations
|
||||
* where the name is part of the struct.
|
||||
*
|
||||
* For places where this is used, see `constraint.cc` for example...
|
||||
*
|
||||
* \param name_offset: should be calculated using `offsetof(structname, membername)`
|
||||
* macro from `stddef.h`
|
||||
*/
|
||||
static bool uniquename_find_dupe(const ListBase *list,
|
||||
void *vlink,
|
||||
const char *name,
|
||||
int name_offset)
|
||||
{
|
||||
for (Link *link = static_cast<Link *>(list->first); link; link = link->next) {
|
||||
if (link != vlink) {
|
||||
if (STREQ(static_cast<const char *>(POINTER_OFFSET((const char *)link, name_offset)), name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct UniqueNameCheckData {
|
||||
const ListBase *lb;
|
||||
void *vlink;
|
||||
int name_offset;
|
||||
};
|
||||
|
||||
static bool uniquename_unique_check(void *arg, const char *name)
|
||||
{
|
||||
UniqueNameCheckData *data = static_cast<UniqueNameCheckData *>(arg);
|
||||
|
||||
return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offset);
|
||||
}
|
||||
|
||||
void BLI_uniquename(const ListBase *list,
|
||||
void *vlink,
|
||||
const char *defname,
|
||||
@@ -514,11 +475,6 @@ void BLI_uniquename(const ListBase *list,
|
||||
int name_offset,
|
||||
size_t name_maxncpy)
|
||||
{
|
||||
UniqueNameCheckData data{};
|
||||
data.lb = list;
|
||||
data.vlink = vlink;
|
||||
data.name_offset = name_offset;
|
||||
|
||||
BLI_assert(name_maxncpy > 1);
|
||||
|
||||
/* See if we are given an empty string */
|
||||
@@ -526,12 +482,22 @@ void BLI_uniquename(const ListBase *list,
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_uniquename_cb(uniquename_unique_check,
|
||||
&data,
|
||||
defname,
|
||||
delim,
|
||||
static_cast<char *>(POINTER_OFFSET(vlink, name_offset)),
|
||||
name_maxncpy);
|
||||
BLI_uniquename_cb(
|
||||
[&](const blender::StringRefNull name) {
|
||||
LISTBASE_FOREACH (Link *, link, list) {
|
||||
if (link != vlink) {
|
||||
const char *link_name = POINTER_OFFSET((const char *)link, name_offset);
|
||||
if (name == link_name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
defname,
|
||||
delim,
|
||||
static_cast<char *>(POINTER_OFFSET(vlink, name_offset)),
|
||||
name_maxncpy);
|
||||
}
|
||||
|
||||
size_t BLI_string_len_array(const char *strings[], uint strings_num)
|
||||
|
||||
@@ -12,58 +12,52 @@
|
||||
|
||||
namespace blender {
|
||||
|
||||
static bool unique_check_func(void *arg, const char *name)
|
||||
{
|
||||
const Vector<std::string> *current_names = static_cast<const Vector<std::string> *>(arg);
|
||||
return current_names->contains(name);
|
||||
}
|
||||
|
||||
TEST(BLI_string_utils, BLI_uniquename_cb)
|
||||
{
|
||||
const Vector<std::string> current_names{"Foo", "Bar", "Bar.003", "Baz.001", "Big.999"};
|
||||
|
||||
/* C version. */
|
||||
{
|
||||
void *arg = const_cast<void *>(static_cast<const void *>(¤t_names));
|
||||
auto unique_check_func = [&](const StringRef check_name) {
|
||||
return current_names.contains(check_name);
|
||||
};
|
||||
|
||||
{
|
||||
char name[64] = "";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Default Name");
|
||||
}
|
||||
|
||||
{
|
||||
char name[64] = "Baz";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Baz");
|
||||
}
|
||||
|
||||
{
|
||||
char name[64] = "Foo";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Foo.001");
|
||||
}
|
||||
|
||||
{
|
||||
char name[64] = "Baz.001";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Baz.002");
|
||||
}
|
||||
|
||||
{
|
||||
char name[64] = "Bar.003";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Bar.004");
|
||||
}
|
||||
|
||||
{
|
||||
char name[64] = "Big.999";
|
||||
BLI_uniquename_cb(unique_check_func, arg, "Default Name", '.', name, sizeof(name));
|
||||
BLI_uniquename_cb(unique_check_func, "Default Name", '.', name, sizeof(name));
|
||||
EXPECT_STREQ(name, "Big.1000");
|
||||
}
|
||||
}
|
||||
|
||||
/* C++ version. */
|
||||
{
|
||||
const auto unique_check = [&](const blender::StringRef name) -> bool {
|
||||
return current_names.contains(name);
|
||||
|
||||
@@ -57,38 +57,33 @@ using namespace blender;
|
||||
* \{ */
|
||||
|
||||
/* NOTE: there's a ed_armature_bone_unique_name() too! */
|
||||
static bool editbone_unique_check(void *arg, const char *name)
|
||||
static bool editbone_unique_check(ListBase *ebones, const StringRefNull name, EditBone *bone)
|
||||
{
|
||||
struct Arg {
|
||||
ListBase *lb;
|
||||
void *bone;
|
||||
} *data = static_cast<Arg *>(arg);
|
||||
|
||||
if (data->bone) {
|
||||
if (bone) {
|
||||
/* This indicates that there is a bone to ignore. This means ED_armature_ebone_find_name()
|
||||
* cannot be used, as it might return the bone we should be ignoring. */
|
||||
for (EditBone *ebone : ListBaseWrapper<EditBone>(data->lb)) {
|
||||
if (STREQ(ebone->name, name) && ebone != data->bone) {
|
||||
for (EditBone *ebone : ListBaseWrapper<EditBone>(ebones)) {
|
||||
if (ebone->name == name && ebone != bone) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EditBone *dupli = ED_armature_ebone_find_name(data->lb, name);
|
||||
return dupli && dupli != data->bone;
|
||||
EditBone *dupli = ED_armature_ebone_find_name(ebones, name.c_str());
|
||||
return dupli && dupli != bone;
|
||||
}
|
||||
|
||||
void ED_armature_ebone_unique_name(ListBase *ebones, char *name, EditBone *bone)
|
||||
{
|
||||
struct {
|
||||
ListBase *lb;
|
||||
void *bone;
|
||||
} data;
|
||||
data.lb = ebones;
|
||||
data.bone = bone;
|
||||
|
||||
BLI_uniquename_cb(editbone_unique_check, &data, DATA_("Bone"), '.', name, sizeof(bone->name));
|
||||
BLI_uniquename_cb(
|
||||
[&](const StringRefNull check_name) {
|
||||
return editbone_unique_check(ebones, check_name, bone);
|
||||
},
|
||||
DATA_("Bone"),
|
||||
'.',
|
||||
name,
|
||||
sizeof(bone->name));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -97,14 +92,16 @@ void ED_armature_ebone_unique_name(ListBase *ebones, char *name, EditBone *bone)
|
||||
/** \name Unique Bone Name Utility (Object Mode)
|
||||
* \{ */
|
||||
|
||||
static bool bone_unique_check(void *arg, const char *name)
|
||||
{
|
||||
return BKE_armature_find_bone_name(static_cast<bArmature *>(arg), name) != nullptr;
|
||||
}
|
||||
|
||||
static void ed_armature_bone_unique_name(bArmature *arm, char *name)
|
||||
{
|
||||
BLI_uniquename_cb(bone_unique_check, (void *)arm, DATA_("Bone"), '.', name, sizeof(Bone::name));
|
||||
BLI_uniquename_cb(
|
||||
[&](const StringRefNull check_name) {
|
||||
return BKE_armature_find_bone_name(arm, check_name.c_str()) != nullptr;
|
||||
},
|
||||
DATA_("Bone"),
|
||||
'.',
|
||||
name,
|
||||
sizeof(Bone::name));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -30,27 +30,20 @@ bool catalogs_read_only(const AssetLibrary &library)
|
||||
return catalog_service.is_read_only();
|
||||
}
|
||||
|
||||
struct CatalogUniqueNameFnData {
|
||||
const AssetCatalogService &catalog_service;
|
||||
StringRef parent_path;
|
||||
};
|
||||
|
||||
static bool catalog_name_exists_fn(void *arg, const char *name)
|
||||
{
|
||||
CatalogUniqueNameFnData &fn_data = *static_cast<CatalogUniqueNameFnData *>(arg);
|
||||
AssetCatalogPath fullpath = AssetCatalogPath(fn_data.parent_path) / name;
|
||||
return fn_data.catalog_service.find_catalog_by_path(fullpath);
|
||||
}
|
||||
|
||||
static std::string catalog_name_ensure_unique(AssetCatalogService &catalog_service,
|
||||
StringRefNull name,
|
||||
StringRef parent_path)
|
||||
{
|
||||
CatalogUniqueNameFnData fn_data = {catalog_service, parent_path};
|
||||
|
||||
char unique_name[MAX_NAME] = "";
|
||||
BLI_uniquename_cb(
|
||||
catalog_name_exists_fn, &fn_data, name.c_str(), '.', unique_name, sizeof(unique_name));
|
||||
[&](const StringRef check_name) {
|
||||
AssetCatalogPath fullpath = AssetCatalogPath(parent_path) / check_name;
|
||||
return catalog_service.find_catalog_by_path(fullpath);
|
||||
},
|
||||
name.c_str(),
|
||||
'.',
|
||||
unique_name,
|
||||
sizeof(unique_name));
|
||||
|
||||
return unique_name;
|
||||
}
|
||||
|
||||
@@ -77,19 +77,16 @@ static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
|
||||
BLI_findstring(lb, name, offsetof(TransformOrientation, name)));
|
||||
}
|
||||
|
||||
static bool uniqueOrientationNameCheck(void *arg, const char *name)
|
||||
{
|
||||
return findOrientationName((ListBase *)arg, name) != nullptr;
|
||||
}
|
||||
|
||||
static void uniqueOrientationName(ListBase *lb, char *name)
|
||||
{
|
||||
BLI_uniquename_cb(uniqueOrientationNameCheck,
|
||||
lb,
|
||||
CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"),
|
||||
'.',
|
||||
name,
|
||||
sizeof(TransformOrientation::name));
|
||||
BLI_uniquename_cb(
|
||||
[&](const StringRefNull check_name) {
|
||||
return findOrientationName(lb, check_name.c_str()) != nullptr;
|
||||
},
|
||||
CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"),
|
||||
'.',
|
||||
name,
|
||||
sizeof(TransformOrientation::name));
|
||||
}
|
||||
|
||||
static TransformOrientation *createViewSpace(bContext *C,
|
||||
|
||||
@@ -103,23 +103,17 @@ inline void set_item_name_and_make_unique(bNode &node,
|
||||
char unique_name[MAX_NAME + 4];
|
||||
STRNCPY(unique_name, value);
|
||||
|
||||
struct Args {
|
||||
SocketItemsRef<ItemT> array;
|
||||
ItemT *item;
|
||||
} args = {array, &item};
|
||||
BLI_uniquename_cb(
|
||||
[](void *arg, const char *name) {
|
||||
const Args &args = *static_cast<Args *>(arg);
|
||||
for (ItemT &item : blender::MutableSpan(*args.array.items, *args.array.items_num)) {
|
||||
if (&item != args.item) {
|
||||
if (STREQ(*Accessor::get_name(item), name)) {
|
||||
[&](const StringRef name) {
|
||||
for (ItemT &item_iter : blender::MutableSpan(*array.items, *array.items_num)) {
|
||||
if (&item_iter != &item) {
|
||||
if (*Accessor::get_name(item_iter) == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
&args,
|
||||
default_name.c_str(),
|
||||
'.',
|
||||
unique_name,
|
||||
|
||||
@@ -56,18 +56,14 @@
|
||||
/* **************** OUTPUT FILE ******************** */
|
||||
|
||||
/* find unique path */
|
||||
static bool unique_path_unique_check(void *arg, const char *name)
|
||||
static bool unique_path_unique_check(ListBase *lb,
|
||||
bNodeSocket *sock,
|
||||
const blender::StringRef name)
|
||||
{
|
||||
struct Args {
|
||||
ListBase *lb;
|
||||
bNodeSocket *sock;
|
||||
};
|
||||
Args *data = (Args *)arg;
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, data->lb) {
|
||||
if (sock != data->sock) {
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
||||
if (STREQ(sockdata->path, name)) {
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock_iter, lb) {
|
||||
if (sock_iter != sock) {
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock_iter->storage;
|
||||
if (sockdata->path == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -79,37 +75,30 @@ void ntreeCompositOutputFileUniquePath(ListBase *list,
|
||||
const char defname[],
|
||||
char delim)
|
||||
{
|
||||
NodeImageMultiFileSocket *sockdata;
|
||||
struct {
|
||||
ListBase *lb;
|
||||
bNodeSocket *sock;
|
||||
} data;
|
||||
data.lb = list;
|
||||
data.sock = sock;
|
||||
|
||||
/* See if we are given an empty string */
|
||||
if (ELEM(nullptr, sock, defname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
||||
BLI_uniquename_cb(
|
||||
unique_path_unique_check, &data, defname, delim, sockdata->path, sizeof(sockdata->path));
|
||||
[&](const blender::StringRef check_name) {
|
||||
return unique_path_unique_check(list, sock, check_name);
|
||||
},
|
||||
defname,
|
||||
delim,
|
||||
sockdata->path,
|
||||
sizeof(sockdata->path));
|
||||
}
|
||||
|
||||
/* find unique EXR layer */
|
||||
static bool unique_layer_unique_check(void *arg, const char *name)
|
||||
static bool unique_layer_unique_check(ListBase *lb,
|
||||
bNodeSocket *sock,
|
||||
const blender::StringRef name)
|
||||
{
|
||||
struct Args {
|
||||
ListBase *lb;
|
||||
bNodeSocket *sock;
|
||||
};
|
||||
Args *data = (Args *)arg;
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, data->lb) {
|
||||
if (sock != data->sock) {
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
||||
if (STREQ(sockdata->layer, name)) {
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock_iter, lb) {
|
||||
if (sock_iter != sock) {
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock_iter->storage;
|
||||
if (sockdata->layer == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -121,21 +110,19 @@ void ntreeCompositOutputFileUniqueLayer(ListBase *list,
|
||||
const char defname[],
|
||||
char delim)
|
||||
{
|
||||
struct {
|
||||
ListBase *lb;
|
||||
bNodeSocket *sock;
|
||||
} data;
|
||||
data.lb = list;
|
||||
data.sock = sock;
|
||||
|
||||
/* See if we are given an empty string */
|
||||
if (ELEM(nullptr, sock, defname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)sock->storage;
|
||||
BLI_uniquename_cb(
|
||||
unique_layer_unique_check, &data, defname, delim, sockdata->layer, sizeof(sockdata->layer));
|
||||
[&](const blender::StringRef check_name) {
|
||||
return unique_layer_unique_check(list, sock, check_name);
|
||||
},
|
||||
defname,
|
||||
delim,
|
||||
sockdata->layer,
|
||||
sizeof(sockdata->layer));
|
||||
}
|
||||
|
||||
bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree,
|
||||
|
||||
Reference in New Issue
Block a user