diff options
Diffstat (limited to 'source/blender/nodes/intern')
-rw-r--r-- | source/blender/nodes/intern/node_common.c | 514 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_common.h | 9 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_exec.c | 100 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_exec.h | 18 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_socket.c | 712 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_util.c | 57 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_util.h | 27 |
7 files changed, 609 insertions, 828 deletions
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index d59061dfc0a..85e2f775ad9 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -31,19 +31,22 @@ #include <string.h> +#include <stddef.h> #include "DNA_node_types.h" #include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" #include "BLF_translation.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BLI_math.h" #include "BKE_node.h" #include "RNA_access.h" @@ -55,247 +58,110 @@ #include "node_util.h" #include "node_exec.h" #include "NOD_socket.h" +#include "NOD_common.h" + /**** Group ****/ -bNodeSocket *node_group_find_input(bNode *gnode, bNodeSocket *gsock) +bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier) { bNodeSocket *sock; - for (sock=gnode->inputs.first; sock; sock=sock->next) - if (sock->groupsock == gsock) + for (sock=groupnode->inputs.first; sock; sock=sock->next) + if (strcmp(sock->identifier, identifier)==0) return sock; return NULL; } -bNodeSocket *node_group_find_output(bNode *gnode, bNodeSocket *gsock) +bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier) { bNodeSocket *sock; - for (sock=gnode->outputs.first; sock; sock=sock->next) - if (sock->groupsock == gsock) + for (sock=groupnode->outputs.first; sock; sock=sock->next) + if (strcmp(sock->identifier, identifier)==0) return sock; return NULL; } -bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb, int in_out, bNodeSocket *gsock) -{ - bNodeSocket *sock; - - if (gsock->flag & SOCK_INTERNAL) - return NULL; - - sock= MEM_callocN(sizeof(bNodeSocket), "sock"); - - /* make a copy of the group socket */ - *sock = *gsock; - sock->link = NULL; - sock->next = sock->prev = NULL; - sock->new_sock = NULL; - - /* group sockets are dynamically added */ - sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; - - sock->own_index = gsock->own_index; - sock->groupsock = gsock; - sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); - - sock->default_value = node_socket_make_default_value(sock->type); - node_socket_copy_default_value(sock->type, sock->default_value, gsock->default_value); - - if (lb) - BLI_addtail(lb, sock); - - return sock; -} - -bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out) -{ - bNodeSocketType *stype = ntreeGetSocketType(type); - bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket"); - - BLI_strncpy(gsock->name, name, sizeof(gsock->name)); - gsock->type = type; - /* group sockets are dynamically added */ - gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; - - gsock->next = gsock->prev = NULL; - gsock->new_sock = NULL; - gsock->link = NULL; - /* assign new unique index */ - gsock->own_index = ngroup->cur_index++; - gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1); - - if (stype->value_structsize > 0) - gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value"); - - BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock); - - ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT); - - return gsock; -} - -bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int in_out) -{ - bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - return gsock; -} - -void node_group_expose_all_sockets(bNodeTree *ngroup) -{ - bNode *node; - bNodeSocket *sock, *gsock; - - for (node=ngroup->nodes.first; node; node=node->next) { - for (sock=node->inputs.first; sock; sock=sock->next) { - if (!sock->link && !nodeSocketIsHidden(sock)) { - gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock); - } - } - for (sock=node->outputs.first; sock; sock=sock->next) { - if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) { - gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT); - - /* initialize the default value. */ - node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value); - - gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock); - } - } - } -} - -void node_group_remove_socket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out) -{ - nodeRemSocketLinks(ngroup, gsock); - - switch (in_out) { - case SOCK_IN: - BLI_remlink(&ngroup->inputs, gsock); - ngroup->update |= NTREE_UPDATE_GROUP_IN; - break; - case SOCK_OUT: - BLI_remlink(&ngroup->outputs, gsock); - ngroup->update |= NTREE_UPDATE_GROUP_OUT; - break; - } - - if (gsock->default_value) - MEM_freeN(gsock->default_value); - - MEM_freeN(gsock); -} - /* groups display their internal tree name as label */ const char *node_group_label(bNode *node) { return (node->id)? node->id->name + 2: IFACE_("Missing Datablock"); } -int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp) +int node_group_poll_instance(bNode *node, bNodeTree *nodetree) { - bNodeTemplate childtemp; - bNode *node; - - /* regular groups cannot be recursive */ - if (ntree == ntemp->ngroup) - return 0; - - /* make sure all children are valid */ - for (node=ntemp->ngroup->nodes.first; node; node=node->next) { - childtemp = nodeMakeTemplate(node); - if (!nodeValid(ntree, &childtemp)) - return 0; - } - - return 1; -} - -bNodeTemplate node_group_template(bNode *node) -{ - bNodeTemplate ntemp; - ntemp.type = NODE_GROUP; - ntemp.ngroup = (bNodeTree *)node->id; - return ntemp; + bNodeTree *grouptree = (bNodeTree*)node->id; + if (grouptree) + return nodeGroupPoll(nodetree, grouptree); + else + return 1; } -void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) +int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree) { - node->id = (ID *)ntemp->ngroup; + bNode *node; + int valid = 1; - /* NB: group socket input/output roles are inverted internally! - * Group "inputs" work as outputs in links and vice versa. - */ - if (ntemp->ngroup) { - bNodeSocket *gsock; - for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); - for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); + if (nodetree == grouptree) + return 0; + + for (node=grouptree->nodes.first; node; node=node->next) { + if (!node->typeinfo->poll_instance(node, nodetree)) { + valid = 0; + break; + } } + return valid; } -static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock) +/* 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) { bNodeSocket *sock; - /* group sockets tagged as internal are not exposed ever */ - if (gsock->flag & SOCK_INTERNAL) - return NULL; - - for (sock= lb->first; sock; sock= sock->next) { - if (sock->own_index==gsock->own_index) + for (sock= verify_lb->first; sock; sock= sock->next) { + if (strcmp(sock->identifier, iosock->identifier)==0) break; } if (sock) { - sock->groupsock = gsock; - - BLI_strncpy(sock->name, gsock->name, sizeof(sock->name)); - if (gsock->type != sock->type) - nodeSocketSetType(sock, gsock->type); - - /* XXX hack: group socket input/output roles are inverted internally, - * need to change the limit value when making actual node sockets from them. - */ - sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); - - BLI_remlink(lb, sock); - - return sock; + strcpy(sock->name, iosock->name); } else { - return node_group_add_extern_socket(ntree, NULL, in_out, gsock); + sock = nodeAddSocket(ntree, gnode, in_out, iosock->idname, iosock->identifier, iosock->name); + + if (iosock->typeinfo->interface_init_socket) + iosock->typeinfo->interface_init_socket(ntree, iosock, gnode, sock, "interface"); } + + /* remove from list temporarily, to distinguish from orphaned sockets */ + BLI_remlink(verify_lb, sock); + + return sock; } -static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb) +/* 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) { - bNodeSocket *sock, *nextsock, *gsock; + bNodeSocket *iosock, *sock, *nextsock; /* step by step compare */ - for (gsock= glb->first; gsock; gsock=gsock->next) { + + iosock = iosock_lb->first; + for (; iosock; iosock = iosock->next) { /* abusing new_sock pointer for verification here! only used inside this function */ - gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock); + iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out); } /* leftovers are removed */ - for (sock=lb->first; sock; sock=nextsock) { - nextsock=sock->next; - if (sock->flag & SOCK_DYNAMIC) - nodeRemoveSocket(ntree, node, sock); + for (sock = verify_lb->first; sock; sock = nextsock) { + nextsock = sock->next; + nodeRemoveSocket(ntree, gnode, sock); } /* and we put back the verified sockets */ - for (gsock= glb->first; gsock; gsock=gsock->next) { - if (gsock->new_sock) { - BLI_addtail(lb, gsock->new_sock); - gsock->new_sock = NULL; + iosock = iosock_lb->first; + for (; iosock; iosock = iosock->next) { + if (iosock->new_sock) { + BLI_addtail(verify_lb, iosock->new_sock); + iosock->new_sock = NULL; } } } @@ -304,59 +170,16 @@ static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id) { /* check inputs and outputs, and remove or insert them */ - if (node->id==id) { + if (id == node->id) { bNodeTree *ngroup= (bNodeTree *)node->id; - group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs); - group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs); + group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN); + group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT); } } -struct bNodeTree *node_group_edit_get(bNode *node) -{ - if (node->flag & NODE_GROUP_EDIT) - return (bNodeTree *)node->id; - else - return NULL; -} - -struct bNodeTree *node_group_edit_set(bNode *node, int edit) -{ - if (edit) { - bNodeTree *ngroup= (bNodeTree *)node->id; - if (ngroup) { - if (ngroup->id.lib) - ntreeMakeLocal(ngroup); - - node->flag |= NODE_GROUP_EDIT; - } - return ngroup; - } - else { - node->flag &= ~NODE_GROUP_EDIT; - return NULL; - } -} - -void node_group_edit_clear(bNode *node) -{ - bNodeTree *ngroup= (bNodeTree *)node->id; - bNode *inode; - - node->flag &= ~NODE_GROUP_EDIT; - - if (ngroup) - for (inode=ngroup->nodes.first; inode; inode=inode->next) - nodeGroupEditClear(inode); -} - -static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out) -{ - node_group_expose_socket(ntree, sock, in_out); -} - /**** FRAME ****/ -static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node) { NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage"); node->storage = data; @@ -366,19 +189,19 @@ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate data->label_size = 20; } -void register_node_type_frame(bNodeTreeType *ttype) +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"); - node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS); + node_type_base(ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS); node_type_init(ntype, node_frame_init); node_type_storage(ntype, "NodeFrame", node_free_standard_storage, node_copy_standard_storage); node_type_size(ntype, 150, 100, 0); node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); ntype->needs_free = 1; - nodeRegisterType(ttype, ntype); + nodeRegisterType(ntype); } @@ -403,34 +226,34 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node) BLI_addtail(&node->internal_links, link); } -static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp)) +static void node_reroute_init(bNodeTree *ntree, bNode *node) { /* Note: Cannot use socket templates for this, since it would reset the socket type * on each file read via the template verification procedure. */ - nodeAddSocket(ntree, node, SOCK_IN, "Input", SOCK_RGBA); - nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA); + nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input"); + nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_RGBA, PROP_NONE, "Output", "Output"); } -void register_node_type_reroute(bNodeTreeType *ttype) +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"); - node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); + node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); node_type_init(ntype, node_reroute_init); node_type_internal_links(ntype, node_reroute_update_internal_links); ntype->needs_free = 1; - nodeRegisterType(ttype, ntype); + nodeRegisterType(ntype); } static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) { bNodeSocket *input = node->inputs.first; bNodeSocket *output = node->outputs.first; - int type = SOCK_FLOAT; bNodeLink *link; + int type = SOCK_FLOAT; /* XXX it would be a little bit more efficient to restrict actual updates * to rerout nodes connected to an updated node, but there's no reliable flag @@ -446,6 +269,8 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) bNode *tonode = link->tonode; if (!tonode || !fromnode) continue; + if (nodeLinkIsHidden(link)) + continue; if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) node_reroute_inherit_type_recursive(ntree, fromnode); @@ -462,9 +287,13 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) /* arbitrary, could also test output->type, both are the same */ if (input->type != type) { + PointerRNA input_ptr, output_ptr; /* same type for input/output */ - nodeSocketSetType(input, type); - nodeSocketSetType(output, type); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, input, &input_ptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, output, &output_ptr); + + RNA_enum_set(&input_ptr, "type", type); + RNA_enum_set(&output_ptr, "type", type); } } @@ -484,9 +313,8 @@ void ntree_update_reroute_nodes(bNodeTree *ntree) node_reroute_inherit_type_recursive(ntree, node); } -void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) +void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree) { - ID *id = (ID *)calldata; bNode *node; for (node = ntree->nodes.first; node; node = node->next) { @@ -495,3 +323,179 @@ void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), str } } } + +/**** GROUP_INPUT / GROUP_OUTPUT ****/ + +static void node_group_input_init(bNodeTree *ntree, bNode *node) +{ + node_group_input_verify(ntree, node, (ID *)ntree); +} + +bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier) +{ + bNodeSocket *sock; + for (sock=node->outputs.first; sock; sock=sock->next) + if (strcmp(sock->identifier, identifier)==0) + return sock; + return NULL; +} + +void node_group_input_verify(bNodeTree *ntree, bNode *node, ID *id) +{ + /* check inputs and outputs, and remove or insert them */ + if (id == (ID *)ntree) { + /* value_in_out inverted for interface nodes to get correct socket value_property */ + group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT); + + /* add virtual extension socket */ + nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", ""); + } +} + +static void node_group_input_update(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *extsock = node->outputs.last; + bNodeLink *link; + /* Adding a tree socket and verifying will remove the extension socket! + * This list caches the existing links from the extension socket + * so they can be recreated after verification. + */ + ListBase tmplinks; + + /* find links from the extension socket and store them */ + tmplinks.first = tmplinks.last = NULL; + for (link = ntree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; + if (link->fromsock == extsock) { + bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link"); + *tlink = *link; + BLI_addtail(&tmplinks, tlink); + } + } + + if (tmplinks.first) { + bNodeSocket *gsock, *newsock; + /* 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, + * whatever that means. + */ + bNodeLink *exposelink = tmplinks.first; + + /* XXX what if connecting virtual to virtual socket?? */ + gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock); + + node_group_input_verify(ntree, node, (ID *)ntree); + newsock = node_group_input_find_socket(node, gsock->identifier); + + /* redirect links from the extension socket */ + for (link = tmplinks.first; link; link = link->next) { + nodeAddLink(ntree, node, newsock, link->tonode, link->tosock); + } + + BLI_freelistN(&tmplinks); + } +} + +void register_node_type_group_input(void) +{ + /* used for all tree types, needs dynamic allocation */ + bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type"); + + node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, NODE_OPTIONS); + node_type_size(ntype, 140, 80, 200); + node_type_init(ntype, node_group_input_init); + node_type_update(ntype, node_group_input_update, node_group_input_verify); + node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); + + ntype->needs_free = 1; + nodeRegisterType(ntype); +} + +static void node_group_output_init(bNodeTree *ntree, bNode *node) +{ + node_group_output_verify(ntree, node, (ID *)ntree); +} + +bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier) +{ + bNodeSocket *sock; + for (sock=node->inputs.first; sock; sock=sock->next) + if (strcmp(sock->identifier, identifier)==0) + return sock; + return NULL; +} + +void node_group_output_verify(bNodeTree *ntree, bNode *node, ID *id) +{ + /* check inputs and outputs, and remove or insert them */ + if (id == (ID *)ntree) { + /* value_in_out inverted for interface nodes to get correct socket value_property */ + group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN); + + /* add virtual extension socket */ + nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", ""); + } +} + +static void node_group_output_update(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *extsock = node->inputs.last; + bNodeLink *link; + /* Adding a tree socket and verifying will remove the extension socket! + * This list caches the existing links to the extension socket + * so they can be recreated after verification. + */ + ListBase tmplinks; + + /* find links to the extension socket and store them */ + tmplinks.first = tmplinks.last = NULL; + for (link = ntree->links.first; link; link = link->next) { + if (nodeLinkIsHidden(link)) + continue; + if (link->tosock == extsock) { + bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link"); + *tlink = *link; + BLI_addtail(&tmplinks, tlink); + } + } + + if (tmplinks.first) { + bNodeSocket *gsock, *newsock; + /* 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, + * whatever that means. + */ + bNodeLink *exposelink = tmplinks.first; + + /* XXX what if connecting virtual to virtual socket?? */ + gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock); + + node_group_output_verify(ntree, node, (ID *)ntree); + newsock = node_group_output_find_socket(node, gsock->identifier); + + /* redirect links to the extension socket */ + for (link = tmplinks.first; link; link = link->next) { + nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock); + } + + BLI_freelistN(&tmplinks); + } +} + +void register_node_type_group_output(void) +{ + /* used for all tree types, needs dynamic allocation */ + bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type"); + + node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, NODE_OPTIONS); + node_type_size(ntype, 140, 80, 200); + node_type_init(ntype, node_group_output_init); + node_type_update(ntype, node_group_output_update, node_group_output_verify); + node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING); + + ntype->needs_free = 1; + nodeRegisterType(ntype); +} diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h index 9e04a9e05f8..498da607b91 100644 --- a/source/blender/nodes/intern/node_common.h +++ b/source/blender/nodes/intern/node_common.h @@ -37,15 +37,8 @@ struct bNodeTree; -void node_group_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); const char *node_group_label(struct bNode *node); -struct bNodeTemplate node_group_template(struct bNode *node); -int node_group_valid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); -void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); - -struct bNodeTree *node_group_edit_get(struct bNode *node); -struct bNodeTree *node_group_edit_set(struct bNode *node, int edit); -void node_group_edit_clear(bNode *node); +int node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree); void ntree_update_reroute_nodes(struct bNodeTree *ntree); diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 8cf7cc7a1ea..8fb23064bf0 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -41,12 +41,19 @@ #include "MEM_guardedalloc.h" #include "node_exec.h" +#include "node_util.h" +/* supported socket types in old nodes */ +int node_exec_socket_use_stack(bNodeSocket *sock) +{ + return ELEM3(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); +} + /* for a given socket, find the actual stack entry */ bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock) { - if (stack && sock) + if (stack && sock && sock->stack_index >= 0) return stack + sock->stack_index; return NULL; } @@ -75,7 +82,10 @@ static void node_init_input_index(bNodeSocket *sock, int *index) sock->stack_index = sock->link->fromsock->stack_index; } else { - sock->stack_index = (*index)++; + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; } } @@ -91,19 +101,27 @@ static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *inte } } /* if not internally connected, assign a new stack index anyway to avoid bad stack access */ - if (!link) - sock->stack_index = (*index)++; + if (!link) { + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; + } } else { - sock->stack_index = (*index)++; + if (node_exec_socket_use_stack(sock)) + sock->stack_index = (*index)++; + else + sock->stack_index = -1; } } /* basic preparation of socket stacks */ -static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock) +static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock) { bNodeStack *ns = node_get_socket_stack(stack, sock); - float null_value[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + if (!ns) + return NULL; /* don't mess with remote socket stacks, these are initialized by other nodes! */ if (sock->link) @@ -111,49 +129,37 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock) ns->sockettype = sock->type; - if (sock->default_value) { - switch (sock->type) { + switch (sock->type) { case SOCK_FLOAT: - ns->vec[0] = ((bNodeSocketValueFloat *)sock->default_value)->value; + ns->vec[0] = node_socket_get_float(ntree, node, sock); break; case SOCK_VECTOR: - copy_v3_v3(ns->vec, ((bNodeSocketValueVector *)sock->default_value)->value); + node_socket_get_vector(ntree, node, sock, ns->vec); break; case SOCK_RGBA: - copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA *)sock->default_value)->value); + node_socket_get_color(ntree, node, sock, ns->vec); break; - } - } - else { - switch (sock->type) { - case SOCK_FLOAT: - ns->vec[0] = 0.0f; - break; - case SOCK_VECTOR: - copy_v3_v3(ns->vec, null_value); - break; - case SOCK_RGBA: - copy_v4_v4(ns->vec, null_value); - break; - } } return ns; } -bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) +bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) { bNodeTreeExec *exec; bNode *node; bNodeExec *nodeexec; - bNodeSocket *sock, *gsock; + bNodeInstanceKey nodekey; + bNodeSocket *sock; bNodeStack *ns; int index; bNode **nodelist; int totnodes, n; - if ((ntree->init & NTREE_TYPE_INIT)==0) - ntreeInitTypes(ntree); + BLI_assert(ntreeIsValid(ntree)); + + /* ensure all sock->link pointers and node levels are correct */ + ntreeUpdateTree(ntree); /* get a dependency-sorted list of nodes */ ntreeGetDependencyList(ntree, &nodelist, &totnodes); @@ -165,9 +171,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) /* set stack indices */ index = 0; - /* group inputs essentially work as outputs */ - for (gsock=ntree->inputs.first; gsock; gsock = gsock->next) - node_init_output_index(gsock, &index, NULL); for (n=0; n < totnodes; ++n) { node = nodelist[n]; @@ -186,9 +189,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) node_init_output_index(sock, &index, NULL); } } - /* group outputs essentially work as inputs */ - for (gsock=ntree->outputs.first; gsock; gsock = gsock->next) - node_init_input_index(gsock, &index); /* allocated exec data pointers for nodes */ exec->totnodes = totnodes; @@ -201,11 +201,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) for (n=0; n < exec->stacksize; ++n) exec->stack[n].hasinput = 1; - /* prepare group tree inputs */ - for (sock=ntree->inputs.first; sock; sock=sock->next) { - /* ns = */ setup_stack(exec->stack, sock); - } - /* prepare all internal nodes for execution */ + /* prepare all nodes for execution */ for (n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) { node = nodeexec->node = nodelist[n]; @@ -215,22 +211,20 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) node->need_exec= 0; - ns = setup_stack(exec->stack, sock); - ns->hasoutput = 1; + ns = setup_stack(exec->stack, ntree, node, sock); + if (ns) + ns->hasoutput = 1; } /* tag all outputs */ for (sock=node->outputs.first; sock; sock=sock->next) { - /* ns = */ setup_stack(exec->stack, sock); + /* ns = */ setup_stack(exec->stack, ntree, node, sock); } + nodekey = BKE_node_instance_key(parent_key, ntree, node); + nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL; if (node->typeinfo->initexecfunc) - nodeexec->data = node->typeinfo->initexecfunc(node); - } - /* prepare group tree outputs */ - for (sock=ntree->outputs.first; sock; sock=sock->next) { - ns = setup_stack(exec->stack, sock); - ns->hasoutput = 1; + nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey); } if (nodelist) @@ -250,7 +244,7 @@ void ntree_exec_end(bNodeTreeExec *exec) for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { if (nodeexec->node->typeinfo) if (nodeexec->node->typeinfo->freeexecfunc) - nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data); + nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data.data); } if (exec->nodeexec) @@ -309,9 +303,7 @@ bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call // if (node->typeinfo->compatibility == NODE_NEW_SHADING) // return false; if (node->typeinfo->execfunc) - node->typeinfo->execfunc(callerdata, node, nsin, nsout); - else if (node->typeinfo->newexecfunc) - node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout); + node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout); } } diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index 5febda036e0..7d76ef34934 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -39,6 +39,8 @@ #include "BKE_node.h" +#include "node_util.h" + #include "RNA_types.h" struct bNodeTree; @@ -48,20 +50,20 @@ struct bNodeStack; /* Node execution data */ typedef struct bNodeExec { struct bNode *node; /* backpointer to node */ - void *data; /* custom data storage */ + bNodeExecData data; } bNodeExec; /* Execution Data for each instance of node tree execution */ typedef struct bNodeTreeExec { struct bNodeTree *nodetree; /* backpointer to node tree */ - int totnodes; /* total node count */ + int totnodes; /* total node count */ struct bNodeExec *nodeexec; /* per-node execution data */ int stacksize; struct bNodeStack *stack; /* socket data stack */ /* only used by material and texture trees to keep one stack for each thread */ - ListBase *threadstack; /* one instance of the stack for each thread */ + ListBase *threadstack; /* one instance of the stack for each thread */ } bNodeTreeExec; /* stores one stack copy for each thread (material and texture trees) */ @@ -71,14 +73,22 @@ typedef struct bNodeThreadStack { int used; } bNodeThreadStack; +int node_exec_socket_use_stack(struct bNodeSocket *sock); + struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock); void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeStack **in, struct bNodeStack **out); -struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree); +struct bNodeTreeExec *ntree_exec_begin(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); void ntree_exec_end(struct bNodeTreeExec *exec); struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread); void ntreeReleaseThreadStack(struct bNodeThreadStack *nts); bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread); +struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); +void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec); + +struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key); +void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec); + #endif diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 69256fafc3d..68ae8fa87b3 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -33,547 +33,95 @@ #include "DNA_node_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLI_string.h" -#include "BKE_DerivedMesh.h" #include "BKE_node.h" +#include "BKE_idprop.h" #include "RNA_access.h" +#include "RNA_define.h" #include "RNA_types.h" #include "MEM_guardedalloc.h" #include "NOD_socket.h" -/****************** FLOAT ******************/ - -static bNodeSocketType node_socket_type_float = { - /* type */ SOCK_FLOAT, - /* ui_name */ "Float", - /* ui_description */ "Floating Point", - /* ui_icon */ 0, - /* ui_color */ {160, 160, 160, 255}, - - /* value_structname */ "bNodeSocketValueFloat", - /* value_structsize */ sizeof(bNodeSocketValueFloat), - - /* buttonfunc */ NULL, -}; - -/****************** VECTOR ******************/ - -static bNodeSocketType node_socket_type_vector = { - /* type */ SOCK_VECTOR, - /* ui_name */ "Vector", - /* ui_description */ "3-dimensional floating point vector", - /* ui_icon */ 0, - /* ui_color */ {100, 100, 200, 255}, - - /* value_structname */ "bNodeSocketValueVector", - /* value_structsize */ sizeof(bNodeSocketValueVector), - - /* buttonfunc */ NULL, -}; - -/****************** RGBA ******************/ - -static bNodeSocketType node_socket_type_rgba = { - /* type */ SOCK_RGBA, - /* ui_name */ "RGBA", - /* ui_description */ "RGBA color", - /* ui_icon */ 0, - /* ui_color */ {200, 200, 40, 255}, - - /* value_structname */ "bNodeSocketValueRGBA", - /* value_structsize */ sizeof(bNodeSocketValueRGBA), - - /* buttonfunc */ NULL, -}; - -/****************** INT ******************/ - -static bNodeSocketType node_socket_type_int = { - /* type */ SOCK_INT, - /* ui_name */ "Int", - /* ui_description */ "Integer", - /* ui_icon */ 0, - /* ui_color */ {17, 133, 37, 255}, - - /* value_structname */ "bNodeSocketValueInt", - /* value_structsize */ sizeof(bNodeSocketValueInt), - - /* buttonfunc */ NULL, -}; - -/****************** BOOLEAN ******************/ - -static bNodeSocketType node_socket_type_boolean = { - /* type */ SOCK_BOOLEAN, - /* ui_name */ "Boolean", - /* ui_description */ "Boolean", - /* ui_icon */ 0, - /* ui_color */ {158, 139, 63, 255}, - - /* value_structname */ "bNodeSocketValueBoolean", - /* value_structsize */ sizeof(bNodeSocketValueBoolean), - - /* buttonfunc */ NULL, -}; - -/****************** SHADER ******************/ - -static bNodeSocketType node_socket_type_shader = { - /* type */ SOCK_SHADER, - /* ui_name */ "Shader", - /* ui_description */ "Shader", - /* ui_icon */ 0, - /* ui_color */ {100, 200, 100, 255}, - - /* value_structname */ NULL, - /* value_structsize */ 0, - - /* buttonfunc */ NULL, -}; - -/****************** MESH ******************/ - -static bNodeSocketType node_socket_type_mesh = { - /* type */ SOCK_MESH, - /* ui_name */ "Mesh", - /* ui_description */ "Mesh geometry data", - /* ui_icon */ 0, - /* ui_color */ {255, 133, 7, 255}, - - /* value_structname */ NULL, - /* value_structsize */ 0, - - /* buttonfunc */ NULL, -}; +struct Main; -/****************** STRING ******************/ - -static bNodeSocketType node_socket_type_string = { - /* type */ SOCK_STRING, - /* ui_name */ "String", - /* ui_description */ "String", - /* ui_icon */ 0, - /* ui_color */ {255, 255, 255, 255}, - - /* value_structname */ "bNodeSocketValueString", - /* value_structsize */ sizeof(bNodeSocketValueString), - - /* buttonfunc */ NULL, -}; - -void node_socket_type_init(bNodeSocketType *types[]) +struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out) { - #define INIT_TYPE(name) types[node_socket_type_##name.type] = &node_socket_type_##name + bNodeSocket *sock = nodeAddStaticSocket(ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name); - INIT_TYPE(float); - INIT_TYPE(vector); - INIT_TYPE(rgba); - INIT_TYPE(int); - INIT_TYPE(boolean); - INIT_TYPE(shader); - INIT_TYPE(mesh); - INIT_TYPE(string); + sock->flag |= stemp->flag; - #undef INIT_TYPE -} - -void *node_socket_make_default_value(int type) -{ - /* XXX currently just allocates from stype->structsize. - * it might become necessary to do more complex allocations for later types. - */ - bNodeSocketType *stype = ntreeGetSocketType(type); - if (stype->value_structsize > 0) { - void *default_value = MEM_callocN(stype->value_structsize, "default socket value"); - return default_value; - } - else - return NULL; -} - -void node_socket_free_default_value(int UNUSED(type), void *default_value) -{ - /* XXX can just free the pointee for all current socket types. */ - if (default_value) - MEM_freeN(default_value); -} - -void node_socket_init_default_value(int type, void *default_value) -{ - switch (type) { - case SOCK_FLOAT: - node_socket_set_default_value_float(default_value, PROP_NONE, 0.0f, -FLT_MAX, FLT_MAX); - break; - case SOCK_INT: - node_socket_set_default_value_int(default_value, PROP_NONE, 0, INT_MIN, INT_MAX); - break; - case SOCK_BOOLEAN: - node_socket_set_default_value_boolean(default_value, FALSE); - break; - case SOCK_VECTOR: - node_socket_set_default_value_vector(default_value, PROP_NONE, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX); - break; - case SOCK_RGBA: - node_socket_set_default_value_rgba(default_value, 0.0f, 0.0f, 0.0f, 1.0f); - break; - case SOCK_SHADER: - node_socket_set_default_value_shader(default_value); - break; - case SOCK_MESH: - node_socket_set_default_value_mesh(default_value); - break; - case SOCK_STRING: - node_socket_set_default_value_string(default_value, PROP_NONE, (char *)""); - break; - } -} - -void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max) -{ - bNodeSocketValueInt *val = default_value; - val->subtype = subtype; - val->value = value; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max) -{ - bNodeSocketValueFloat *val = default_value; - val->subtype = subtype; - val->value = value; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_boolean(void *default_value, char value) -{ - bNodeSocketValueBoolean *val = default_value; - val->value = value; -} - -void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max) -{ - bNodeSocketValueVector *val = default_value; - val->subtype = subtype; - val->value[0] = x; - val->value[1] = y; - val->value[2] = z; - val->min = min; - val->max = max; -} - -void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a) -{ - bNodeSocketValueRGBA *val = default_value; - val->value[0] = r; - val->value[1] = g; - val->value[2] = b; - val->value[3] = a; -} - -void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value) -{ - bNodeSocketValueString *val = default_value; - val->subtype = subtype; - BLI_strncpy(val->value, value, 1024);//FILE_MAX -} - -void node_socket_set_default_value_shader(void *UNUSED(default_value)) -{ -} - -void node_socket_set_default_value_mesh(void *UNUSED(default_value)) -{ -} - - -void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value) -{ - /* XXX only one of these pointers is valid! just putting them here for convenience */ - bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value; - bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value; - bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; - bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; - bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; - bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value; - - bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; - bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; - bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; - bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; - bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; - bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value; - - switch (type) { - case SOCK_FLOAT: - *tofloat = *fromfloat; - break; - case SOCK_INT: - *toint = *fromint; - break; - case SOCK_BOOLEAN: - *tobool = *frombool; - break; - case SOCK_VECTOR: - *tovector = *fromvector; - break; - case SOCK_RGBA: - *torgba = *fromrgba; - break; - case SOCK_STRING: - *tostring = *fromstring; - break; - } -} - -/* XXX This is a makeshift function to have useful initial group socket values. - * In the end this should be implemented by a flexible socket data conversion system, - * which is yet to be implemented. The idea is that beside default standard conversions, - * such as int-to-float, it should be possible to quickly select a conversion method or - * a chain of conversions for each input, whenever there is more than one option. - * E.g. a vector-to-float conversion could use either of the x/y/z components or - * the vector length. - * - * In the interface this could be implemented by a pseudo-script textbox on linked inputs, - * with quick selection from a predefined list of conversion options. Some Examples: - * - vector component 'z' (vector->float): "z" - * - grayscale color (float->color): "gray" - * - color luminance (color->float): "lum" - * - matrix column 2 length (matrix->vector->float): "col[1].len" - * - mesh vertex coordinate 'y' (mesh->vertex->vector->float): "vertex.co.y" - * - * The actual conversion is then done by a series of conversion functions, - * which are defined in the socket type structs. - */ -void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value) -{ - /* XXX only one of these pointers is valid! just putting them here for convenience */ - bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value; - bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value; - bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; - bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; - bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; - - bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; - bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; - bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; - bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; - bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; - - switch (from_type) { - case SOCK_FLOAT: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromfloat->value; - break; - case SOCK_INT: - toint->value = (int)fromfloat->value; - break; - case SOCK_BOOLEAN: - tobool->value = (fromfloat->value > 0.0f); - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value; - break; - } - break; - case SOCK_INT: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = (float)fromint->value; - break; - case SOCK_INT: - toint->value = fromint->value; - break; - case SOCK_BOOLEAN: - tobool->value = (fromint->value > 0); - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value; - break; - } - break; - case SOCK_BOOLEAN: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = (float)frombool->value; - break; - case SOCK_INT: - toint->value = (int)frombool->value; - break; - case SOCK_BOOLEAN: - tobool->value = frombool->value; - break; - case SOCK_VECTOR: - tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value; - break; - case SOCK_RGBA: - torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value; - break; - } - break; - case SOCK_VECTOR: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromvector->value[0]; - break; - case SOCK_INT: - toint->value = (int)fromvector->value[0]; - break; - case SOCK_BOOLEAN: - tobool->value = (fromvector->value[0] > 0.0f); - break; - case SOCK_VECTOR: - copy_v3_v3(tovector->value, fromvector->value); - break; - case SOCK_RGBA: - copy_v3_v3(torgba->value, fromvector->value); - torgba->value[3] = 1.0f; + /* initialize default_value */ + switch (stemp->type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *dval = sock->default_value; + dval->value = stemp->val1; + dval->min = stemp->min; + dval->max = stemp->max; break; } - break; - case SOCK_RGBA: - switch (to_type) { - case SOCK_FLOAT: - tofloat->value = fromrgba->value[0]; - break; - case SOCK_INT: - toint->value = (int)fromrgba->value[0]; - break; - case SOCK_BOOLEAN: - tobool->value = (fromrgba->value[0] > 0.0f); - break; - case SOCK_VECTOR: - copy_v3_v3(tovector->value, fromrgba->value); - break; - case SOCK_RGBA: - copy_v4_v4(torgba->value, fromrgba->value); + case SOCK_INT: { + bNodeSocketValueInt *dval = sock->default_value; + dval->value = (int)stemp->val1; + dval->min = (int)stemp->min; + dval->max = (int)stemp->max; break; } - break; - } -} - -static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp) -{ - switch (sock->type) { - case SOCK_FLOAT: - { - bNodeSocketValueFloat *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; + case SOCK_BOOLEAN: { + bNodeSocketValueBoolean *dval = sock->default_value; + dval->value = (int)stemp->val1; break; } - case SOCK_INT: - { - bNodeSocketValueInt *dval= sock->default_value; + case SOCK_VECTOR: { + bNodeSocketValueVector *dval = sock->default_value; + dval->value[0] = stemp->val1; + dval->value[1] = stemp->val2; + dval->value[2] = stemp->val3; dval->min = stemp->min; dval->max = stemp->max; - dval->subtype = stemp->subtype; break; } - case SOCK_VECTOR: - { - bNodeSocketValueVector *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; + case SOCK_RGBA: { + bNodeSocketValueRGBA *dval = sock->default_value; + dval->value[0] = stemp->val1; + dval->value[1] = stemp->val2; + dval->value[2] = stemp->val3; + dval->value[3] = stemp->val4; break; } } -} - -struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) -{ - bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type); - sock->flag |= stemp->flag; - - switch (stemp->type) { - case SOCK_INT: - node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max); - break; - case SOCK_FLOAT: - node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max); - break; - case SOCK_BOOLEAN: - node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1); - break; - case SOCK_VECTOR: - node_socket_set_default_value_vector(sock->default_value, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max); - break; - case SOCK_RGBA: - node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4); - break; - case SOCK_SHADER: - node_socket_set_default_value_shader(sock->default_value); - break; - case SOCK_MESH: - node_socket_set_default_value_mesh(sock->default_value); - break; - case SOCK_STRING: - node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)""); - break; - } return sock; } -struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) -{ - bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type); - node_socket_set_minmax_subtype(sock, stemp); - return sock; -} - static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp) { bNodeSocket *sock; for (sock= socklist->first; sock; sock= sock->next) { - if (!(sock->flag & SOCK_DYNAMIC) && strncmp(sock->name, stemp->name, NODE_MAXSTR)==0) + if (strncmp(sock->name, stemp->name, NODE_MAXSTR)==0) break; } if (sock) { - sock->type = stemp->type; /* in future, read this from tydefs! */ + sock->type = stemp->type; if (stemp->limit == 0) sock->limit= 0xFFF; else sock->limit = stemp->limit; sock->flag |= stemp->flag; - /* Copy the property range and subtype parameters in case the template changed. - * NOT copying the actual value here, only button behavior changes! - */ - node_socket_set_minmax_subtype(sock, stemp); - BLI_remlink(socklist, sock); return sock; } else { /* no socket for this template found, make a new one */ - if (in_out==SOCK_IN) - sock = node_add_input_from_template(ntree, node, stemp); - else - sock = node_add_output_from_template(ntree, node, stemp); + sock = node_add_socket_from_template(ntree, node, stemp, in_out); /* remove the new socket from the node socket list first, * will be added back after verification. */ @@ -592,8 +140,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou if (stemp_first==NULL) { for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) { nextsock = sock->next; - if (!(sock->flag & SOCK_DYNAMIC)) - nodeRemoveSocket(ntree, node, sock); + nodeRemoveSocket(ntree, node, sock); } } else { @@ -606,8 +153,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou /* leftovers are removed */ for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) { nextsock = sock->next; - if (!(sock->flag & SOCK_DYNAMIC)) - nodeRemoveSocket(ntree, node, sock); + nodeRemoveSocket(ntree, node, sock); } /* and we put back the verified sockets */ @@ -635,14 +181,182 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou void node_verify_socket_templates(bNodeTree *ntree, bNode *node) { bNodeType *ntype= node->typeinfo; - /* XXX Small trick: don't try to match socket lists when there are no templates. - * This also prevents group node sockets from being removed, without the need to explicitly + /* Don't try to match socket lists when there are no templates. + * This prevents group node sockets from being removed, without the need to explicitly * check the node type here. */ - if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) || - (ntype->outputs && ntype->outputs[0].type >= 0))) - { - verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); - verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); + if (ntype) { + if (ntype->inputs && ntype->inputs[0].type >= 0) + verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); + if (ntype->outputs && ntype->outputs[0].type >= 0) + verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); + } +} + + +void node_socket_init_default_value(bNodeSocket *sock) +{ + int type = sock->typeinfo->type; + int subtype = sock->typeinfo->subtype; + + if (sock->default_value) + return; /* already initialized */ + + switch (type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *dval = MEM_callocN(sizeof(bNodeSocketValueFloat), "node socket value float"); + dval->subtype = subtype; + dval->value = 0.0f; + dval->min = -FLT_MAX; + dval->max = FLT_MAX; + + sock->default_value = dval; + break; + } + case SOCK_INT: { + bNodeSocketValueInt *dval = MEM_callocN(sizeof(bNodeSocketValueInt), "node socket value int"); + dval->subtype = subtype; + dval->value = 0; + dval->min = INT_MIN; + dval->max = INT_MAX; + + sock->default_value = dval; + break; + } + case SOCK_BOOLEAN: { + bNodeSocketValueBoolean *dval = MEM_callocN(sizeof(bNodeSocketValueBoolean), "node socket value bool"); + dval->value = false; + + sock->default_value = dval; + break; + } + case SOCK_VECTOR: { + bNodeSocketValueVector *dval = MEM_callocN(sizeof(bNodeSocketValueVector), "node socket value vector"); + dval->subtype = subtype; + copy_v3_v3(dval->value, (float[]){0.0f, 0.0f, 0.0f}); + dval->min = -FLT_MAX; + dval->max = FLT_MAX; + + sock->default_value = dval; + break; } + case SOCK_RGBA: { + bNodeSocketValueRGBA *dval = MEM_callocN(sizeof(bNodeSocketValueRGBA), "node socket value color"); + copy_v4_v4(dval->value, (float[]){0.0f, 0.0f, 0.0f, 1.0f}); + + sock->default_value = dval; + break; + } + case SOCK_STRING: { + bNodeSocketValueString *dval = MEM_callocN(sizeof(bNodeSocketValueString), "node socket value string"); + dval->subtype = subtype; + dval->value[0] = '\0'; + + sock->default_value = dval; + break; + } + } +} + + +static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree), bNodeSocket *UNUSED(stemp), bNode *UNUSED(node), bNodeSocket *sock, const char *UNUSED(data_path)) +{ + /* initialize the type value */ + sock->type = sock->typeinfo->type; +} + +static bNodeSocketType *make_standard_socket_type(int type, int subtype) +{ + extern void ED_init_standard_node_socket_type(bNodeSocketType *); + + const char *socket_idname = nodeStaticSocketType(type, subtype); + const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype); + bNodeSocketType *stype; + StructRNA *srna; + + stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); + BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + + /* set the RNA type + * uses the exact same identifier as the socket type idname */ + srna = stype->ext_socket.srna = RNA_struct_find(socket_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + /* set the interface RNA type */ + srna = stype->ext_interface.srna = RNA_struct_find(interface_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + /* extra type info for standard socket types */ + stype->type = type; + stype->subtype = subtype; + + /* XXX bad-level call! needed for setting draw callbacks */ + ED_init_standard_node_socket_type(stype); + + stype->interface_init_socket = standard_node_socket_interface_init_socket; + + return stype; +} + +static bNodeSocketType *make_socket_type_virtual(void) +{ + extern void ED_init_node_socket_type_virtual(bNodeSocketType *); + + const char *socket_idname = "NodeSocketVirtual"; + bNodeSocketType *stype; + StructRNA *srna; + + stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); + BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + + /* set the RNA type + * uses the exact same identifier as the socket type idname */ + srna = stype->ext_socket.srna = RNA_struct_find(socket_idname); + BLI_assert(srna != NULL); + /* associate the RNA type with the socket type */ + RNA_struct_blender_type_set(srna, stype); + + ED_init_node_socket_type_virtual(stype); + + return stype; +} + + +void register_standard_node_socket_types() +{ + /* draw callbacks are set in drawnode.c to avoid bad-level calls */ + + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_UNSIGNED)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_PERCENTAGE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_FACTOR)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_ANGLE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_TIME)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_UNSIGNED)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_PERCENTAGE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_FACTOR)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_TRANSLATION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_DIRECTION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_VELOCITY)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_ACCELERATION)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_EULER)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_XYZ)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_RGBA, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_STRING, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE)); + + nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index 09e6ddd18a5..c622c1c5227 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -30,6 +30,7 @@ */ #include <limits.h> +#include <string.h> #include "DNA_action_types.h" #include "DNA_node_types.h" @@ -63,17 +64,17 @@ void node_free_standard_storage(bNode *node) } } -void node_copy_curves(bNode *orig_node, bNode *new_node) +void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - new_node->storage = curvemapping_copy(orig_node->storage); + dest_node->storage = curvemapping_copy(src_node->storage); } -void node_copy_standard_storage(bNode *orig_node, bNode *new_node) +void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { - new_node->storage = MEM_dupallocN(orig_node->storage); + dest_node->storage = MEM_dupallocN(src_node->storage); } -void *node_initexec_curves(bNode *node) +void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key)) { curvemapping_initialize(node->storage); return NULL; /* unused return */ @@ -129,6 +130,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) fromindex = INT_MAX; fromsock = NULL; for (link=ntree->links.first; link; link=link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->tonode == node && link->tosock->type == datatype) { int index = BLI_findindex(&node->inputs, link->tosock); if (index < fromindex) { @@ -146,6 +149,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) toindex = INT_MAX; tosock = NULL; for (link=ntree->links.first; link; link=link->next) { + if (nodeLinkIsHidden(link)) + continue; if (link->fromnode == node && link->fromsock->type == datatype) { int index = BLI_findindex(&node->outputs, link->fromsock); if (index < toindex) { @@ -188,3 +193,45 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node) BLI_addtail(&node->internal_links, ilink); } } + +float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + return RNA_float_get(&ptr, "default_value"); +} + +void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set(&ptr, "default_value", value); +} + +void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_get_array(&ptr, "default_value", value); +} + +void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set_array(&ptr, "default_value", value); +} + +void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_get_array(&ptr, "default_value", value); +} + +void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value) +{ + PointerRNA ptr; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + RNA_float_set_array(&ptr, "default_value", value); +} diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 6b783915816..2b3f84420f9 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -35,6 +35,8 @@ #include "DNA_listBase.h" +#include "BLI_utildefines.h" + #include "BKE_node.h" #include "MEM_guardedalloc.h" @@ -43,17 +45,29 @@ #include "GPU_material.h" /* For Shader muting GPU code... */ +#include "RNA_access.h" + struct bNodeTree; struct bNode; +/* data for initializing node execution */ +typedef struct bNodeExecContext { + struct bNodeInstanceHash *previews; +} bNodeExecContext; + +typedef struct bNodeExecData { + void *data; /* custom data storage */ + struct bNodePreview *preview; /* optional preview image */ +} bNodeExecData; + /**** Storage Data ****/ extern void node_free_curves(struct bNode *node); extern void node_free_standard_storage(struct bNode *node); -extern void node_copy_curves(struct bNode *orig_node, struct bNode *new_node); -extern void node_copy_standard_storage(struct bNode *orig_node, struct bNode *new_node); -extern void *node_initexec_curves(struct bNode *node); +extern void node_copy_curves(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); +extern void node_copy_standard_storage(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); +extern void *node_initexec_curves(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key); /**** Labels ****/ @@ -64,4 +78,11 @@ const char *node_filter_label(struct bNode *node); void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node); +float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); +void node_socket_set_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float value); +void node_socket_get_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value); +void node_socket_set_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value); +void node_socket_get_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value); +void node_socket_set_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value); + #endif |