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:
Jacques Lucke
2025-04-10 20:30:45 +02:00
parent 9f46f09075
commit b92fdff697
15 changed files with 180 additions and 301 deletions

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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,

View File

@@ -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),

View File

@@ -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)

View File

@@ -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 *>(&current_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);

View File

@@ -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));
}
/** \} */

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,