Nodes: Panel declarations for grouping sockets #108649
|
@ -566,18 +566,24 @@ void ntreeSetSocketInterfaceCategory(bNodeTree *ntree,
|
|||
/** \name Node Tree Socket Categories
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Find a socket category by its unique ID.
|
||||
* \param id: Unique ID of the category within the node tree.
|
||||
LukasTonne marked this conversation as resolved
Outdated
|
||||
*/
|
||||
bNodeSocketCategory *ntreeFindSocketCategoryByID(bNodeTree *ntree, int id);
|
||||
|
||||
/**
|
||||
* Add a new socket category to the node tree.
|
||||
* \param name Name of the new category.
|
||||
* \param name Flags of the new category.
|
||||
* \param name: Name of the new category.
|
||||
* \param flag: Flags of the new category.
|
||||
*/
|
||||
bNodeSocketCategory *ntreeAddSocketCategory(bNodeTree *ntree, const char *name, int flag);
|
||||
|
||||
/**
|
||||
* Insert a new socket category in the node tree.
|
||||
* \param name Name of the new category.
|
||||
* \param name Flags of the new category.
|
||||
* \param index Index at which to insert the category.
|
||||
* \param name: Name of the new category.
|
||||
* \param flag: Flags of the new category.
|
||||
* \param index: Index at which to insert the category.
|
||||
*/
|
||||
bNodeSocketCategory *ntreeInsertSocketCategory(bNodeTree *ntree,
|
||||
const char *name,
|
||||
|
|
|
@ -3658,7 +3658,7 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
|
|||
STRNCPY(sock->name, name);
|
||||
sock->storage = nullptr;
|
||||
sock->flag |= SOCK_COLLAPSED;
|
||||
sock->category_index = -1;
|
||||
sock->category_id = -1;
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
@ -3667,7 +3667,7 @@ static int node_socket_category_cmp(const void *a, const void *b)
|
|||
{
|
||||
const bNodeSocket *sock_a = static_cast<const bNodeSocket *>(a);
|
||||
const bNodeSocket *sock_b = static_cast<const bNodeSocket *>(b);
|
||||
return (sock_a->category_index > sock_b->category_index) ? 1 : 0;
|
||||
return (sock_a->category_id > sock_b->category_id) ? 1 : 0;
|
||||
}
|
||||
|
||||
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
|
||||
|
@ -3687,8 +3687,32 @@ bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
|
|||
|
||||
void ntreeEnsureSocketCategoryOrder(bNodeTree *ntree)
|
||||
{
|
||||
/* XXX Hack: store category index in category_id temporarily for sorting. */
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->inputs) {
|
||||
const bNodeSocketCategory *category = ntreeFindSocketCategoryByID(ntree, iosock->category_id);
|
||||
iosock->category_id = category == nullptr ? -1 :
|
||||
(int)(category - ntree->socket_categories_array);
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->outputs) {
|
||||
const bNodeSocketCategory *category = ntreeFindSocketCategoryByID(ntree, iosock->category_id);
|
||||
iosock->category_id = category == nullptr ? -1 :
|
||||
(int)(category - ntree->socket_categories_array);
|
||||
}
|
||||
BLI_listbase_sort(&ntree->inputs, blender::bke::node_socket_category_cmp);
|
||||
BLI_listbase_sort(&ntree->outputs, blender::bke::node_socket_category_cmp);
|
||||
/* Restore category_id. */
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->inputs) {
|
||||
if (iosock->category_id >= 0) {
|
||||
const bNodeSocketCategory &category = ntree->socket_categories()[iosock->category_id];
|
||||
iosock->category_id = category.identifier;
|
||||
}
|
||||
}
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
`VectorSet` and VectorSet::index_of` are probably a more natural choice here, with a bit less boilerplate.
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->outputs) {
|
||||
if (iosock->category_id >= 0) {
|
||||
const bNodeSocketCategory &category = ntree->socket_categories()[iosock->category_id];
|
||||
iosock->category_id = category.identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
|
||||
|
@ -3715,12 +3739,11 @@ void ntreeSetSocketInterfaceCategory(bNodeTree *ntree,
|
|||
bNodeSocketCategory *category)
|
||||
{
|
||||
if (category == NULL) {
|
||||
socket->category_index = -1;
|
||||
socket->category_id = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
socket->category_index = category - ntree->socket_categories_array;
|
||||
BLI_assert(ntree->socket_categories().index_range().contains(socket->category_index));
|
||||
socket->category_id = category->identifier;
|
||||
|
||||
ntreeEnsureSocketCategoryOrder(ntree);
|
||||
|
||||
|
@ -3805,25 +3828,16 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
|
|||
BKE_ntree_update_tag_interface(ntree);
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/* Fix socket category indices after changes. */
|
||||
static void remap_socket_categories(bNodeTree &ntree, std::function<int(int)> index_fn)
|
||||
bNodeSocketCategory *ntreeFindSocketCategoryByID(bNodeTree *ntree, int id)
|
||||
{
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
IMO IMO `__func__` for the allocation string is nicer than specifying one manually. It just takes up less visual space. I've also seen other developers preferring that too.
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree.inputs) {
|
||||
socket->category_index = index_fn(socket->category_index);
|
||||
BLI_assert(socket->category_index == -1 ||
|
||||
ntree.socket_categories().index_range().contains(socket->category_index));
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree.outputs) {
|
||||
socket->category_index = index_fn(socket->category_index);
|
||||
BLI_assert(socket->category_index == -1 ||
|
||||
ntree.socket_categories().index_range().contains(socket->category_index));
|
||||
for (bNodeSocketCategory &category : ntree->socket_categories_for_write()) {
|
||||
if (category.identifier == id) {
|
||||
return &category;
|
||||
}
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
Don't have a strong preference, but this seems a bit more idiomatic and clear to me: Don't have a strong preference, but this seems a bit more idiomatic and clear to me:
` std::copy(old_categories.begin(), old_categories.end(), new_categories.data());`
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
bNodeSocketCategory *ntreeAddSocketCategory(bNodeTree *ntree, const char *name, int flag)
|
||||
{
|
||||
bNodeSocketCategory *old_categories_array = ntree->socket_categories_array;
|
||||
|
@ -3837,11 +3851,10 @@ bNodeSocketCategory *ntreeAddSocketCategory(bNodeTree *ntree, const char *name,
|
|||
new_categories[i] = old_categories[i];
|
||||
}
|
||||
bNodeSocketCategory &new_category = new_categories[new_categories.size() - 1];
|
||||
new_category = {BLI_strdup(name), flag};
|
||||
new_category = {BLI_strdup(name), flag, ntree->next_socket_category_identifier++};
|
||||
|
||||
MEM_SAFE_FREE(old_categories_array);
|
||||
|
||||
/* No need to remap socket categories, in this case old indices stay the same. */
|
||||
/* No need to sort sockets, nothing is using the new category yet */
|
||||
|
||||
return &new_category;
|
||||
|
@ -3870,14 +3883,10 @@ bNodeSocketCategory *ntreeInsertSocketCategory(bNodeTree *ntree,
|
|||
new_categories[i + 1] = old_categories[i];
|
||||
}
|
||||
bNodeSocketCategory &new_category = new_categories[index];
|
||||
new_category = {BLI_strdup(name), flag};
|
||||
new_category = {BLI_strdup(name), flag, ntree->next_socket_category_identifier++};
|
||||
|
||||
MEM_SAFE_FREE(old_categories_array);
|
||||
|
||||
blender::bke::remap_socket_categories(*ntree, [index](const int old_category_index) {
|
||||
return old_category_index < index ? old_category_index : old_category_index + 1;
|
||||
});
|
||||
|
||||
/* No need to sort sockets, nothing is using the new category yet */
|
||||
|
||||
return &new_category;
|
||||
|
@ -3906,11 +3915,6 @@ void ntreeRemoveSocketCategory(bNodeTree *ntree, bNodeSocketCategory *category)
|
|||
|
||||
MEM_SAFE_FREE(old_categories_array);
|
||||
|
||||
blender::bke::remap_socket_categories(*ntree, [index](const int old_category_index) {
|
||||
return old_category_index < index ? old_category_index :
|
||||
(old_category_index > index ? old_category_index - 1 : -1);
|
||||
});
|
||||
|
||||
ntreeEnsureSocketCategoryOrder(ntree);
|
||||
}
|
||||
|
||||
|
@ -3920,8 +3924,6 @@ void ntreeClearSocketCategories(bNodeTree *ntree)
|
|||
ntree->socket_categories_array = nullptr;
|
||||
ntree->socket_categories_num = 0;
|
||||
|
||||
blender::bke::remap_socket_categories(*ntree, [](const int /*old_index*/) { return -1; });
|
||||
|
||||
/* No need to sort sockets, only null category exists, relative order remains unchanged. */
|
||||
}
|
||||
|
||||
|
@ -3943,13 +3945,6 @@ void ntreeMoveSocketCategory(bNodeTree *ntree, bNodeSocketCategory *category, in
|
|||
categories[i] = categories[i + 1];
|
||||
}
|
||||
categories[new_index] = tmp;
|
||||
|
||||
blender::bke::remap_socket_categories(
|
||||
*ntree, [old_index, new_index](const int old_category_index) {
|
||||
return old_category_index < old_index || old_category_index > new_index ?
|
||||
old_category_index :
|
||||
(old_category_index == old_index ? new_index : old_category_index - 1);
|
||||
});
|
||||
}
|
||||
else /* old_index > new_index */ {
|
||||
const bNodeSocketCategory tmp = categories[old_index];
|
||||
|
@ -3957,13 +3952,6 @@ void ntreeMoveSocketCategory(bNodeTree *ntree, bNodeSocketCategory *category, in
|
|||
categories[i] = categories[i - 1];
|
||||
}
|
||||
categories[new_index] = tmp;
|
||||
|
||||
blender::bke::remap_socket_categories(
|
||||
*ntree, [old_index, new_index](const int old_category_index) {
|
||||
return old_category_index < new_index || old_category_index > old_index ?
|
||||
old_category_index :
|
||||
(old_category_index == old_index ? new_index : old_category_index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
ntreeEnsureSocketCategoryOrder(ntree);
|
||||
|
|
|
@ -138,13 +138,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bNodeSocket", "int", "category_index")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bNodeSocket", "int", "category_id")) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->inputs) {
|
||||
socket->category_index = -1;
|
||||
socket->category_id = -1;
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->outputs) {
|
||||
socket->category_index = -1;
|
||||
socket->category_id = -1;
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
|
|
|
@ -2192,7 +2192,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
|
|||
/* XXX this only works for actual sockets, not interface templates! */
|
||||
// nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);
|
||||
/* Inherit socket category from the active socket interface. */
|
||||
sock->category_index = active_sock->category_index;
|
||||
sock->category_id = active_sock->category_id;
|
||||
}
|
||||
else {
|
||||
/* XXX TODO: define default socket type for a tree! */
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#define _DNA_DEFAULT_bNodeSocket \
|
||||
{ \
|
||||
.category_index = -1, \
|
||||
.category_id = -1, \
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -168,8 +168,8 @@ typedef struct bNodeSocket {
|
|||
/** Custom data for inputs, only UI writes in this. */
|
||||
bNodeStack ns DNA_DEPRECATED;
|
||||
|
||||
/* UI category index of the socket. */
|
||||
int category_index;
|
||||
/* ID of the UI category of the socket. */
|
||||
int category_id;
|
||||
int _pad2;
|
||||
|
||||
bNodeSocketRuntimeHandle *runtime;
|
||||
|
@ -538,7 +538,7 @@ typedef struct bNodeLink {
|
|||
typedef struct bNodeSocketCategory {
|
||||
char *name;
|
||||
int flag;
|
||||
int _pad;
|
||||
int identifier;
|
||||
} bNodeSocketCategory;
|
||||
|
||||
/* the basis for a Node tree, all links and nodes reside internal here */
|
||||
|
@ -608,6 +608,8 @@ typedef struct bNodeTree {
|
|||
struct bNodeSocketCategory *socket_categories_array;
|
||||
int socket_categories_num;
|
||||
int active_socket_category;
|
||||
int next_socket_category_identifier;
|
||||
char _pad2[4];
|
||||
|
||||
bNodeTreeRuntimeHandle *runtime;
|
||||
|
||||
|
|
|
@ -3168,12 +3168,8 @@ static PointerRNA rna_NodeSocketInterface_category_get(PointerRNA *ptr)
|
|||
{
|
||||
bNodeSocket *socket = (bNodeSocket *)ptr->data;
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
|
||||
const int index = socket->category_index;
|
||||
|
||||
bNodeSocketCategory *category = NULL;
|
||||
if (index >= 0 && index < ntree->socket_categories_num) {
|
||||
category = &ntree->socket_categories_array[index];
|
||||
}
|
||||
bNodeSocketCategory *category = ntreeFindSocketCategoryByID(ntree, socket->category_id);
|
||||
|
||||
PointerRNA r_ptr;
|
||||
RNA_pointer_create(&ntree->id, &RNA_NodeSocketCategory, category, &r_ptr);
|
||||
|
@ -3188,10 +3184,12 @@ static void rna_NodeSocketInterface_category_set(PointerRNA *ptr,
|
|||
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
|
||||
bNodeSocketCategory *category = (bNodeSocketCategory *)value.data;
|
||||
|
||||
const size_t index = category - ntree->socket_categories_array;
|
||||
if (index >= ntree->socket_categories_num) {
|
||||
BKE_report(reports, RPT_ERROR, "Category is not in the node tree interface");
|
||||
return;
|
||||
if (category != NULL) {
|
||||
const int64_t index = category - ntree->socket_categories_array;
|
||||
if (index < 0 || index >= ntree->socket_categories_num) {
|
||||
BKE_report(reports, RPT_ERROR, "Category is not in the node tree interface");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ntreeSetSocketInterfaceCategory(ntree, socket, category);
|
||||
|
@ -3206,7 +3204,7 @@ static bool rna_NodeSocketInterface_category_poll(PointerRNA *ptr, PointerRNA va
|
|||
return true;
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
Super picky but this newline isn't helpful IMO, better to more closely connect the variable declaration and the null check. Super picky but this newline isn't helpful IMO, better to more closely connect the variable declaration and the null check.
|
||||
}
|
||||
|
||||
const int index = category - ntree->socket_categories_array;
|
||||
const int64_t index = category - ntree->socket_categories_array;
|
||||
if (index < 0 || index >= ntree->socket_categories_num) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
There's meant to be a colon after the name here:
\param name: