Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2013-03-18 20:34:57 +0400
commit4638e5f99a9ba59ad0b8a1fd52b12e876480b9e8 (patch)
tree2444f12b4612440f44cf02835cdf5951b6564e92 /source/blender/nodes/intern
parent7bfef29f2f2a1b262d28abdc6e30fcd9c1f1caad (diff)
Merge of the PyNodes branch (aka "custom nodes") into trunk.
PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
Diffstat (limited to 'source/blender/nodes/intern')
-rw-r--r--source/blender/nodes/intern/node_common.c514
-rw-r--r--source/blender/nodes/intern/node_common.h9
-rw-r--r--source/blender/nodes/intern/node_exec.c100
-rw-r--r--source/blender/nodes/intern/node_exec.h18
-rw-r--r--source/blender/nodes/intern/node_socket.c712
-rw-r--r--source/blender/nodes/intern/node_util.c57
-rw-r--r--source/blender/nodes/intern/node_util.h27
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