|
|
|
@@ -21,8 +21,8 @@
|
|
|
|
|
* \ingroup nodes
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
|
|
|
@@ -53,8 +53,7 @@ enum {
|
|
|
|
|
|
|
|
|
|
bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
for (sock = groupnode->inputs.first; sock; sock = sock->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &groupnode->inputs) {
|
|
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
@@ -64,8 +63,7 @@ bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifi
|
|
|
|
|
|
|
|
|
|
bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
for (sock = groupnode->outputs.first; sock; sock = sock->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &groupnode->outputs) {
|
|
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
@@ -95,7 +93,6 @@ bool node_group_poll_instance(bNode *node, bNodeTree *nodetree, const char **dis
|
|
|
|
|
|
|
|
|
|
bool nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree, const char **r_disabled_hint)
|
|
|
|
|
{
|
|
|
|
|
bNode *node;
|
|
|
|
|
bool valid = true;
|
|
|
|
|
|
|
|
|
|
/* unspecified node group, generally allowed
|
|
|
|
@@ -110,7 +107,7 @@ bool nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree, const char **r_dis
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (node = grouptree->nodes.first; node; node = node->next) {
|
|
|
|
|
LISTBASE_FOREACH (bNode *, node, &grouptree->nodes) {
|
|
|
|
|
if (node->typeinfo->poll_instance &&
|
|
|
|
|
!node->typeinfo->poll_instance(node, nodetree, r_disabled_hint)) {
|
|
|
|
|
valid = false;
|
|
|
|
@@ -121,12 +118,15 @@ bool nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree, const char **r_dis
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* used for both group nodes and interface nodes */
|
|
|
|
|
static bNodeSocket *group_verify_socket(
|
|
|
|
|
bNodeTree *ntree, bNode *gnode, bNodeSocket *iosock, ListBase *verify_lb, int in_out)
|
|
|
|
|
static bNodeSocket *group_verify_socket(bNodeTree *ntree,
|
|
|
|
|
bNode *gnode,
|
|
|
|
|
bNodeSocket *iosock,
|
|
|
|
|
ListBase *verify_lb,
|
|
|
|
|
eNodeSocketInOut in_out)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
|
|
|
|
|
for (sock = verify_lb->first; sock; sock = sock->next) {
|
|
|
|
|
for (sock = (bNodeSocket *)verify_lb->first; sock; sock = sock->next) {
|
|
|
|
|
if (STREQ(sock->identifier, iosock->identifier)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -163,25 +163,28 @@ static bNodeSocket *group_verify_socket(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* used for both group nodes and interface nodes */
|
|
|
|
|
static void group_verify_socket_list(
|
|
|
|
|
bNodeTree *ntree, bNode *gnode, ListBase *iosock_lb, ListBase *verify_lb, int in_out)
|
|
|
|
|
static void group_verify_socket_list(bNodeTree *ntree,
|
|
|
|
|
bNode *gnode,
|
|
|
|
|
ListBase *iosock_lb,
|
|
|
|
|
ListBase *verify_lb,
|
|
|
|
|
eNodeSocketInOut in_out)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *iosock, *sock, *nextsock;
|
|
|
|
|
bNodeSocket *sock, *nextsock;
|
|
|
|
|
|
|
|
|
|
/* step by step compare */
|
|
|
|
|
|
|
|
|
|
iosock = iosock_lb->first;
|
|
|
|
|
bNodeSocket *iosock = (bNodeSocket *)iosock_lb->first;
|
|
|
|
|
for (; iosock; iosock = iosock->next) {
|
|
|
|
|
/* abusing new_sock pointer for verification here! only used inside this function */
|
|
|
|
|
iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out);
|
|
|
|
|
}
|
|
|
|
|
/* leftovers are removed */
|
|
|
|
|
for (sock = verify_lb->first; sock; sock = nextsock) {
|
|
|
|
|
for (sock = (bNodeSocket *)verify_lb->first; sock; sock = nextsock) {
|
|
|
|
|
nextsock = sock->next;
|
|
|
|
|
nodeRemoveSocket(ntree, gnode, sock);
|
|
|
|
|
}
|
|
|
|
|
/* and we put back the verified sockets */
|
|
|
|
|
iosock = iosock_lb->first;
|
|
|
|
|
iosock = (bNodeSocket *)iosock_lb->first;
|
|
|
|
|
for (; iosock; iosock = iosock->next) {
|
|
|
|
|
if (iosock->new_sock) {
|
|
|
|
|
BLI_addtail(verify_lb, iosock->new_sock);
|
|
|
|
@@ -227,7 +230,7 @@ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node)
|
|
|
|
|
void register_node_type_frame(void)
|
|
|
|
|
{
|
|
|
|
|
/* frame type is used for all tree types, needs dynamic allocation */
|
|
|
|
|
bNodeType *ntype = MEM_callocN(sizeof(bNodeType), "frame node type");
|
|
|
|
|
bNodeType *ntype = (bNodeType *)MEM_callocN(sizeof(bNodeType), "frame node type");
|
|
|
|
|
ntype->free_self = (void (*)(bNodeType *))MEM_freeN;
|
|
|
|
|
|
|
|
|
|
node_type_base(ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND);
|
|
|
|
@@ -254,11 +257,11 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link = MEM_callocN(sizeof(bNodeLink), "internal node link");
|
|
|
|
|
link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "internal node link");
|
|
|
|
|
link->fromnode = node;
|
|
|
|
|
link->fromsock = node->inputs.first;
|
|
|
|
|
link->fromsock = (bNodeSocket *)node->inputs.first;
|
|
|
|
|
link->tonode = node;
|
|
|
|
|
link->tosock = node->outputs.first;
|
|
|
|
|
link->tosock = (bNodeSocket *)node->outputs.first;
|
|
|
|
|
/* internal link is always valid */
|
|
|
|
|
link->flag |= NODE_LINK_VALID;
|
|
|
|
|
BLI_addtail(&node->internal_links, link);
|
|
|
|
@@ -276,7 +279,7 @@ static void node_reroute_init(bNodeTree *ntree, bNode *node)
|
|
|
|
|
void register_node_type_reroute(void)
|
|
|
|
|
{
|
|
|
|
|
/* frame type is used for all tree types, needs dynamic allocation */
|
|
|
|
|
bNodeType *ntype = MEM_callocN(sizeof(bNodeType), "frame node type");
|
|
|
|
|
bNodeType *ntype = (bNodeType *)MEM_callocN(sizeof(bNodeType), "frame node type");
|
|
|
|
|
ntype->free_self = (void (*)(bNodeType *))MEM_freeN;
|
|
|
|
|
|
|
|
|
|
node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
|
|
|
|
@@ -288,8 +291,8 @@ void register_node_type_reroute(void)
|
|
|
|
|
|
|
|
|
|
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, int flag)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *input = node->inputs.first;
|
|
|
|
|
bNodeSocket *output = node->outputs.first;
|
|
|
|
|
bNodeSocket *input = (bNodeSocket *)node->inputs.first;
|
|
|
|
|
bNodeSocket *output = (bNodeSocket *)node->outputs.first;
|
|
|
|
|
bNodeLink *link;
|
|
|
|
|
int type = SOCK_FLOAT;
|
|
|
|
|
const char *type_idname = nodeStaticSocketType(type, PROP_NONE);
|
|
|
|
@@ -302,7 +305,7 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, i
|
|
|
|
|
node->done = 1;
|
|
|
|
|
|
|
|
|
|
/* recursive update */
|
|
|
|
|
for (link = ntree->links.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = link->next) {
|
|
|
|
|
bNode *fromnode = link->fromnode;
|
|
|
|
|
bNode *tonode = link->tonode;
|
|
|
|
|
if (!tonode || !fromnode) {
|
|
|
|
@@ -336,7 +339,7 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, i
|
|
|
|
|
|
|
|
|
|
if (input->type != type) {
|
|
|
|
|
bNodeSocket *ninput = nodeAddSocket(ntree, node, SOCK_IN, type_idname, "input", "Input");
|
|
|
|
|
for (link = ntree->links.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = link->next) {
|
|
|
|
|
if (link->tosock == input) {
|
|
|
|
|
link->tosock = ninput;
|
|
|
|
|
ninput->link = link;
|
|
|
|
@@ -347,7 +350,7 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, i
|
|
|
|
|
|
|
|
|
|
if (output->type != type) {
|
|
|
|
|
bNodeSocket *noutput = nodeAddSocket(ntree, node, SOCK_OUT, type_idname, "output", "Output");
|
|
|
|
|
for (link = ntree->links.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = link->next) {
|
|
|
|
|
if (link->fromsock == output) {
|
|
|
|
|
link->fromsock = noutput;
|
|
|
|
|
}
|
|
|
|
@@ -366,11 +369,11 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
|
|
|
|
|
bNode *node;
|
|
|
|
|
|
|
|
|
|
/* clear tags */
|
|
|
|
|
for (node = ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
for (node = (bNode *)ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
node->done = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (node = ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
for (node = (bNode *)ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
if (node->type == NODE_REROUTE && !node->done) {
|
|
|
|
|
node_reroute_inherit_type_recursive(ntree, node, REFINE_FORWARD | REFINE_BACKWARD);
|
|
|
|
|
}
|
|
|
|
@@ -393,7 +396,7 @@ static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* test all connected nodes, first positive find is sufficient to return true */
|
|
|
|
|
for (link = ntree->links.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = link->next) {
|
|
|
|
|
if (link->fromnode == node) {
|
|
|
|
|
if (node_is_connected_to_output_recursive(ntree, link->tonode)) {
|
|
|
|
|
return true;
|
|
|
|
@@ -408,7 +411,7 @@ bool BKE_node_is_connected_to_output(bNodeTree *ntree, bNode *node)
|
|
|
|
|
bNode *tnode;
|
|
|
|
|
|
|
|
|
|
/* clear flags */
|
|
|
|
|
for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
|
|
|
|
|
for (tnode = (bNode *)ntree->nodes.first; tnode; tnode = tnode->next) {
|
|
|
|
|
tnode->done = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -419,7 +422,7 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
|
|
|
|
|
{
|
|
|
|
|
bNode *node;
|
|
|
|
|
|
|
|
|
|
for (node = ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
for (node = (bNode *)ntree->nodes.first; node; node = node->next) {
|
|
|
|
|
if (node->id == id) {
|
|
|
|
|
node->id = NULL;
|
|
|
|
|
}
|
|
|
|
@@ -440,7 +443,7 @@ static void node_group_input_init(bNodeTree *ntree, bNode *node)
|
|
|
|
|
bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
for (sock = node->outputs.first; sock; sock = sock->next) {
|
|
|
|
|
for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
|
|
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
@@ -450,7 +453,7 @@ bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
|
|
|
|
|
|
|
|
|
|
void node_group_input_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *extsock = node->outputs.last;
|
|
|
|
|
bNodeSocket *extsock = (bNodeSocket *)node->outputs.last;
|
|
|
|
|
bNodeLink *link, *linknext, *exposelink;
|
|
|
|
|
/* Adding a tree socket and verifying will remove the extension socket!
|
|
|
|
|
* This list caches the existing links from the extension socket
|
|
|
|
@@ -460,14 +463,14 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
/* find links from the extension socket and store them */
|
|
|
|
|
BLI_listbase_clear(&tmplinks);
|
|
|
|
|
for (link = ntree->links.first; link; link = linknext) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = linknext) {
|
|
|
|
|
linknext = link->next;
|
|
|
|
|
if (nodeLinkIsHidden(link)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (link->fromsock == extsock) {
|
|
|
|
|
bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
|
|
|
|
|
bNodeLink *tlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "temporary link");
|
|
|
|
|
*tlink = *link;
|
|
|
|
|
BLI_addtail(&tmplinks, tlink);
|
|
|
|
|
|
|
|
|
@@ -477,7 +480,7 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
/* find valid link to expose */
|
|
|
|
|
exposelink = NULL;
|
|
|
|
|
for (link = tmplinks.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)tmplinks.first; link; link = link->next) {
|
|
|
|
|
/* XXX Multiple sockets can be connected to the extension socket at once,
|
|
|
|
|
* in that case the arbitrary first link determines name and type.
|
|
|
|
|
* This could be improved by choosing the "best" type among all links,
|
|
|
|
@@ -498,7 +501,7 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
newsock = node_group_input_find_socket(node, gsock->identifier);
|
|
|
|
|
|
|
|
|
|
/* redirect links from the extension socket */
|
|
|
|
|
for (link = tmplinks.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)tmplinks.first; link; link = link->next) {
|
|
|
|
|
nodeAddLink(ntree, node, newsock, link->tonode, link->tosock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -518,7 +521,7 @@ void node_group_input_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
void register_node_type_group_input(void)
|
|
|
|
|
{
|
|
|
|
|
/* used for all tree types, needs dynamic allocation */
|
|
|
|
|
bNodeType *ntype = MEM_callocN(sizeof(bNodeType), "node type");
|
|
|
|
|
bNodeType *ntype = (bNodeType *)MEM_callocN(sizeof(bNodeType), "node type");
|
|
|
|
|
ntype->free_self = (void (*)(bNodeType *))MEM_freeN;
|
|
|
|
|
|
|
|
|
|
node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, 0);
|
|
|
|
@@ -537,7 +540,7 @@ static void node_group_output_init(bNodeTree *ntree, bNode *node)
|
|
|
|
|
bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *sock;
|
|
|
|
|
for (sock = node->inputs.first; sock; sock = sock->next) {
|
|
|
|
|
for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
|
|
|
|
|
if (STREQ(sock->identifier, identifier)) {
|
|
|
|
|
return sock;
|
|
|
|
|
}
|
|
|
|
@@ -547,7 +550,7 @@ bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
|
|
|
|
|
|
|
|
|
|
void node_group_output_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
{
|
|
|
|
|
bNodeSocket *extsock = node->inputs.last;
|
|
|
|
|
bNodeSocket *extsock = (bNodeSocket *)node->inputs.last;
|
|
|
|
|
bNodeLink *link, *linknext, *exposelink;
|
|
|
|
|
/* Adding a tree socket and verifying will remove the extension socket!
|
|
|
|
|
* This list caches the existing links to the extension socket
|
|
|
|
@@ -557,14 +560,14 @@ void node_group_output_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
/* find links to the extension socket and store them */
|
|
|
|
|
BLI_listbase_clear(&tmplinks);
|
|
|
|
|
for (link = ntree->links.first; link; link = linknext) {
|
|
|
|
|
for (link = (bNodeLink *)ntree->links.first; link; link = linknext) {
|
|
|
|
|
linknext = link->next;
|
|
|
|
|
if (nodeLinkIsHidden(link)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (link->tosock == extsock) {
|
|
|
|
|
bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
|
|
|
|
|
bNodeLink *tlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "temporary link");
|
|
|
|
|
*tlink = *link;
|
|
|
|
|
BLI_addtail(&tmplinks, tlink);
|
|
|
|
|
|
|
|
|
@@ -574,7 +577,7 @@ void node_group_output_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
|
|
|
|
|
/* find valid link to expose */
|
|
|
|
|
exposelink = NULL;
|
|
|
|
|
for (link = tmplinks.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)tmplinks.first; link; link = link->next) {
|
|
|
|
|
/* XXX Multiple sockets can be connected to the extension socket at once,
|
|
|
|
|
* in that case the arbitrary first link determines name and type.
|
|
|
|
|
* This could be improved by choosing the "best" type among all links,
|
|
|
|
@@ -596,7 +599,7 @@ void node_group_output_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
newsock = node_group_output_find_socket(node, gsock->identifier);
|
|
|
|
|
|
|
|
|
|
/* redirect links to the extension socket */
|
|
|
|
|
for (link = tmplinks.first; link; link = link->next) {
|
|
|
|
|
for (link = (bNodeLink *)tmplinks.first; link; link = link->next) {
|
|
|
|
|
nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -616,7 +619,7 @@ void node_group_output_update(bNodeTree *ntree, bNode *node)
|
|
|
|
|
void register_node_type_group_output(void)
|
|
|
|
|
{
|
|
|
|
|
/* used for all tree types, needs dynamic allocation */
|
|
|
|
|
bNodeType *ntype = MEM_callocN(sizeof(bNodeType), "node type");
|
|
|
|
|
bNodeType *ntype = (bNodeType *)MEM_callocN(sizeof(bNodeType), "node type");
|
|
|
|
|
ntype->free_self = (void (*)(bNodeType *))MEM_freeN;
|
|
|
|
|
|
|
|
|
|
node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, 0);
|