Nodes: Panel declarations for grouping sockets #108649

Merged
Lukas Tönne merged 27 commits from LukasTonne/blender:node-socket-categories into main 2023-06-14 18:02:46 +02:00
7 changed files with 65 additions and 71 deletions
Showing only changes of commit c7ab5dc068 - Show all commits

View File

@ -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.
*/
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,

View File

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

View File

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

View File

@ -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! */

View File

@ -15,7 +15,7 @@
#define _DNA_DEFAULT_bNodeSocket \
{ \
.category_index = -1, \
.category_id = -1, \
}
/** \} */

View File

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

View File

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