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-04-18 15:36:11 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2013-04-18 15:36:11 +0400
commit4f23bd8904dfd46181a4082f1bea91dbbcaa8d86 (patch)
treed55964acef036f81f94375549aff8993069bd4a7 /source/blender/editors/space_node/node_templates.c
parent4587ecd45be207a79365329d9c1266ced4043ae4 (diff)
Fix for #35010, Node Groups don't show up anymore in Material Surface. Fixing the node tree view was a bit of a todo item after pynodes.
To make the type-dependent socket linking in this template a bit more manageable, there are now separate functions that generate "items" for a particular node type consisting of the socket index, name and possibly additional properties required (currently only node groups vs. all other types). This is still nowhere near flexible enough to be used as a generic template all node systems, but works for now. In order to make this usable as a generic tool we will have to devise a way of storing, comparing, applying node settings *outside of actual node instances*. Then each node needs to tell how sockets are generated based on these properties. For the current nodes this would be far too complicated ...
Diffstat (limited to 'source/blender/editors/space_node/node_templates.c')
-rw-r--r--source/blender/editors/space_node/node_templates.c168
1 files changed, 134 insertions, 34 deletions
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 527defb1f07..973cb5acc80 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -57,6 +57,44 @@
/************************* Node Socket Manipulation **************************/
+/* describes an instance of a node type and a specific socket to link */
+typedef struct NodeLinkItem {
+ int socket_index; /* index for linking */
+ int socket_type; /* socket type for compatibility check */
+ const char *socket_name; /* ui label of the socket */
+ const char *node_name; /* ui label of the node */
+
+ /* extra settings */
+ bNodeTree *ngroup; /* group node tree */
+} NodeLinkItem;
+
+/* Compare an existing node to a link item to see if it can be reused.
+ * item must be for the same node type!
+ * XXX should become a node type callback
+ */
+static bool node_link_item_compare(bNode *node, NodeLinkItem *item)
+{
+ if (node->type == NODE_GROUP) {
+ return (node->id == (ID *)item->ngroup);
+ }
+ else
+ return true;
+}
+
+static void node_link_item_apply(bNode *node, NodeLinkItem *item)
+{
+ if (node->type == NODE_GROUP) {
+ node->id = (ID *)item->ngroup;
+ ntreeUpdateTree(item->ngroup);
+ }
+ else {
+ /* nothing to do for now */
+ }
+
+ if (node->id)
+ id_us_plus(node->id);
+}
+
static void node_tag_recursive(bNode *node)
{
bNodeSocket *input;
@@ -149,7 +187,8 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
}
/* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num)
+static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to,
+ int type, NodeLinkItem *item)
{
bNode *node_from;
bNodeSocket *sock_from_tmp;
@@ -170,9 +209,7 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
node_from = NULL;
- /* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */
- if (node_prev && node_prev->type == type &&
- (type != NODE_GROUP || node_prev->id == &ngroup->id))
+ if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item))
{
/* keep the previous node if it's the same type */
node_from = node_prev;
@@ -182,19 +219,13 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy;
- /* XXX bad, should be dispatched to generic operator or something ... */
- if (type == NODE_GROUP) {
- node_from->id = (ID *)ngroup;
- }
-
- if (node_from->id)
- id_us_plus(node_from->id);
+ node_link_item_apply(node_from, item);
}
nodeSetActive(ntree, node_from);
/* add link */
- sock_from_tmp = BLI_findlink(&node_from->outputs, sock_num);
+ sock_from_tmp = BLI_findlink(&node_from->outputs, item->socket_index);
nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to);
sock_to->flag &= ~SOCK_COLLAPSED;
@@ -215,11 +246,9 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
nodeRemLink(ntree, link);
}
-#if 0 /* XXX TODO */
- node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value);
- sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo);
- node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value);
-#endif
+ if (sock_from->default_value)
+ MEM_freeN(sock_from->default_value);
+ node_socket_copy_default_value(sock_from->default_value, sock_prev->default_value);
}
}
}
@@ -255,13 +284,77 @@ typedef struct NodeLinkArg {
bNode *node;
bNodeSocket *sock;
- bNodeTree *ngroup;
- int type;
- int output;
+ bNodeType *node_type;
+ NodeLinkItem item;
uiLayout *layout;
} NodeLinkArg;
+static void ui_node_link_items(NodeLinkArg *arg, int in_out, NodeLinkItem **r_items, int *r_totitems)
+{
+ /* XXX this should become a callback for node types! */
+ NodeLinkItem *items = NULL;
+ int totitems = 0;
+
+ if (arg->node_type->type == NODE_GROUP) {
+ bNodeTree *ngroup;
+ int i;
+
+ for (ngroup = arg->bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
+ ListBase *lb = (in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs);
+ totitems += BLI_countlist(lb);
+ }
+
+ if (totitems > 0) {
+ items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
+
+ i = 0;
+ for (ngroup = arg->bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
+ ListBase *lb = (in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs);
+ bNodeSocket *stemp;
+ int index;
+ for (stemp = lb->first, index = 0; stemp; stemp = stemp->next, ++index) {
+ NodeLinkItem *item = &items[i++];
+
+ item->socket_index = index;
+ /* note: int stemp->type is not fully reliable, not used for node group
+ * interface sockets. use the typeinfo->type instead.
+ */
+ item->socket_type = stemp->typeinfo->type;
+ item->socket_name = stemp->name;
+ item->node_name = ngroup->id.name + 2;
+ item->ngroup = ngroup;
+ }
+ }
+ }
+ }
+ else {
+ bNodeSocketTemplate *socket_templates = (in_out == SOCK_IN ? arg->node_type->inputs : arg->node_type->outputs);
+ bNodeSocketTemplate *stemp;
+ int i;
+
+ for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp)
+ ++totitems;
+
+ if (totitems > 0) {
+ items = MEM_callocN(sizeof(NodeLinkItem) * totitems, "ui node link items");
+
+ i = 0;
+ for (stemp = socket_templates; stemp && stemp->type != -1; ++stemp) {
+ NodeLinkItem *item = &items[i++];
+
+ item->socket_index = i;
+ item->socket_type = stemp->type;
+ item->socket_name = stemp->name;
+ item->node_name = arg->node_type->ui_name;
+ }
+ }
+ }
+
+ *r_items = items;
+ *r_totitems = totitems;
+}
+
static void ui_node_link(bContext *C, void *arg_p, void *event_p)
{
NodeLinkArg *arg = (NodeLinkArg *)arg_p;
@@ -276,7 +369,7 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
else if (event == UI_NODE_LINK_REMOVE)
node_socket_remove(bmain, ntree, node_to, sock_to);
else
- node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output);
+ node_socket_add_replace(C, ntree, node_to, sock_to, arg->node_type->type, &arg->item);
ED_undo_push(C, "Node input modify");
}
@@ -335,8 +428,9 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
compatibility = NODE_OLD_SHADING;
}
- NODE_TYPES_BEGIN(ntype)
- bNodeSocketTemplate *stemp;
+ NODE_TYPES_BEGIN(ntype) {
+ NodeLinkItem *items;
+ int totitems;
char name[UI_MAX_NAME_STR];
int i, j, num = 0;
@@ -346,12 +440,17 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
if (ntype->nclass != nclass)
continue;
- for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
- if (ui_compatible_sockets(stemp->type, sock->type))
+ arg->node_type = ntype;
+
+ ui_node_link_items(arg, SOCK_OUT, &items, &totitems);
+
+ for (i = 0; i < totitems; ++i)
+ if (ui_compatible_sockets(items[i].socket_type, sock->type))
num++;
- for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
- if (!ui_compatible_sockets(stemp->type, sock->type))
+ j = 0;
+ for (i = 0; i < totitems; ++i) {
+ if (!ui_compatible_sockets(items[i].socket_type, sock->type))
continue;
if (first) {
@@ -367,25 +466,28 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
if (num > 1) {
if (j == 0) {
- uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE);
+ uiItemL(column, IFACE_(items[i].node_name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
}
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(items[i].socket_name));
j++;
}
else
- BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR);
+ BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
argN = MEM_dupallocN(arg);
- argN->type = ntype->type;
- argN->output = i;
+ argN->item = items[i];
uiButSetNFunc(but, ui_node_link, argN, NULL);
}
+
+ if (items)
+ MEM_freeN(items);
+ }
NODE_TYPES_END
}
@@ -448,8 +550,6 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
arg->ntree = ntree;
arg->node = node;
arg->sock = sock;
- arg->type = 0;
- arg->output = 0;
uiBlockSetCurLayout(block, layout);