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