Workspace: Move engines to workspace and Properties Editor cleanup
[blender.git] / source / blender / editors / space_node / node_templates.c
index d4df449a41b0dd618e3bd9115aea759ef4c9629a..c791b9f6eae40d2c69b61b09849bc4db8b35c2de 100644 (file)
@@ -24,6 +24,7 @@
  *  \ingroup edinterface
  */
 
+#include <stdlib.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
 #include "DNA_node_types.h"
 #include "DNA_screen_types.h"
 
+#include "BLI_array.h"
 #include "BLI_listbase.h"
 #include "BLI_string.h"
 
-#include "BLF_translation.h"
+#include "BLT_translation.h"
 
 #include "BKE_context.h"
+#include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_scene.h"
 
 #include "ED_util.h"
 
+
 /************************* 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(G.main, 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;
@@ -109,7 +151,7 @@ static void node_remove_linked(bNodeTree *ntree, bNode *rem_node)
 
                if (node->flag & NODE_TEST) {
                        if (node->id)
-                               node->id->us--;
+                               id_us_min(node->id);
                        nodeFreeNode(ntree, node);
                }
        }
@@ -125,9 +167,9 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
        sock_to->flag |= SOCK_COLLAPSED;
 
        nodeUpdate(ntree, node_to);
-       ntreeUpdateTree(ntree);
+       ntreeUpdateTree(bmain, ntree);
 
-       ED_node_generic_update(bmain, ntree, node_to);
+       ED_node_tag_update_nodetree(bmain, ntree, node_to);
 }
 
 /* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -140,13 +182,14 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
        sock_to->flag |= SOCK_COLLAPSED;
 
        nodeUpdate(ntree, node_to);
-       ntreeUpdateTree(ntree);
+       ntreeUpdateTree(bmain, ntree);
 
-       ED_node_generic_update(bmain, ntree, node_to);
+       ED_node_tag_update_nodetree(bmain, ntree, node_to);
 }
 
 /* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, 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;
@@ -160,32 +203,43 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
 
        /* find existing node that we can use */
        for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
-               if (node_from->type == ntemp->type)
+               if (node_from->type == type)
                        break;
 
        if (node_from)
-               if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
+               if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex)
                        node_from = NULL;
 
-       if (node_prev && node_prev->type == ntemp->type &&
-           (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->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;
        }
        else if (!node_from) {
-               node_from = nodeAddNode(ntree, ntemp);
-               node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
-               node_from->locy = node_to->locy;
-
-               if (node_from->id)
-                       id_us_plus(node_from->id);
+               node_from = nodeAddStaticNode(C, ntree, type);
+               if (node_prev != NULL) {
+                       /* If we're replacing existing node, use it's location. */
+                       node_from->locx = node_prev->locx;
+                       node_from->locy = node_prev->locy;
+                       node_from->offsetx = node_prev->offsetx;
+                       node_from->offsety = node_prev->offsety;
+               }
+               else {
+                       /* Avoid exact intersection of nodes.
+                        * TODO(sergey): Still not ideal, but better than nothing.
+                        */
+                       int index = BLI_findindex(&node_to->inputs, sock_to);
+                       BLI_assert(index != -1);
+                       node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
+                       node_from->locy = node_to->locy - (node_from->typeinfo->height * index);
+               }
+               
+               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;
 
@@ -198,7 +252,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
                                if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
                                        continue;
 
-                               if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
+                               if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
                                        bNodeLink *link = sock_prev->link;
 
                                        if (link && link->fromnode) {
@@ -206,9 +260,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
                                                nodeRemLink(ntree, link);
                                        }
 
-                                       node_socket_free_default_value(sock_from->type, sock_from->default_value);
-                                       sock_from->default_value = node_socket_make_default_value(sock_from->type);
-                                       node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
+                                       node_socket_copy_default_value(sock_from, sock_prev);
                                }
                        }
                }
@@ -226,9 +278,9 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
 
        nodeUpdate(ntree, node_from);
        nodeUpdate(ntree, node_to);
-       ntreeUpdateTree(ntree);
+       ntreeUpdateTree(CTX_data_main(C), ntree);
 
-       ED_node_generic_update(bmain, ntree, node_to);
+       ED_node_tag_update_nodetree(CTX_data_main(C), ntree, node_to);
 }
 
 /****************************** Node Link Menu *******************************/
@@ -244,13 +296,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_listbase_count(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, ++i) {
+                                       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, ++i) {
+                               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;
@@ -259,19 +375,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
        bNodeSocket *sock_to = arg->sock;
        bNodeTree *ntree = arg->ntree;
        int event = GET_INT_FROM_POINTER(event_p);
-       bNodeTemplate ntemp;
-
-       ntemp.type = arg->type;
-       ntemp.ngroup = arg->ngroup;
-       ntemp.scene = CTX_data_scene(C);
-       ntemp.main = CTX_data_main(C);
 
        if (event == UI_NODE_LINK_DISCONNECT)
                node_socket_disconnect(bmain, ntree, node_to, sock_to);
        else if (event == UI_NODE_LINK_REMOVE)
                node_socket_remove(bmain, ntree, node_to, sock_to);
        else
-               node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, 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");
 }
@@ -286,14 +396,13 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
                        if (node->id)
                                BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR);
                        else
-                               BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR);
+                               BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR);
                }
                else
-                       BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
+                       BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR);
 
-               if (node->inputs.first == NULL &&
-                   node->outputs.first != node->outputs.last &&
-                   !(node->typeinfo->flag & NODE_OPTIONS))
+               if (BLI_listbase_is_empty(&node->inputs) &&
+                   node->outputs.first != node->outputs.last)
                {
                        BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name));
                }
@@ -312,21 +421,39 @@ static int ui_compatible_sockets(int typeA, int typeB)
        return (typeA == typeB);
 }
 
+static int ui_node_item_name_compare(const void *a, const void *b)
+{
+       const bNodeType *type_a = *(const bNodeType **)a;
+       const bNodeType *type_b = *(const bNodeType **)b;
+       return BLI_natstrcmp(type_a->ui_name, type_b->ui_name);
+}
+
+static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree),
+                                      const bNodeType *ntype)
+{
+       if (STREQ(ntype->idname, "ShaderNodeUVAlongStroke")) {
+               /* TODO(sergey): Currently we don't have Freestyle nodes edited from
+                * the buttons context, so can ignore it's nodes completely.
+                *
+                * However, we might want to do some extra checks here later.
+                */
+               return false;
+       }
+       return true;
+}
+
 static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
 {
-       Main *bmain = arg->bmain;
        bNodeTree *ntree = arg->ntree;
        bNodeSocket *sock = arg->sock;
        uiLayout *layout = arg->layout;
        uiLayout *column = NULL;
        uiBlock *block = uiLayoutGetBlock(layout);
        uiBut *but;
-       bNodeType *ntype;
-       bNodeTree *ngroup;
        NodeLinkArg *argN;
        int first = 1;
        int compatibility = 0;
-
+       
        if (ntree->type == NTREE_SHADER) {
                if (BKE_scene_use_new_shading_nodes(arg->scene))
                        compatibility = NODE_NEW_SHADING;
@@ -334,114 +461,90 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
                        compatibility = NODE_OLD_SHADING;
        }
 
-       if (nclass == NODE_CLASS_GROUP) {
-               for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
-                       bNodeSocket *gsock;
-                       char name[UI_MAX_NAME_STR];
-                       int i, j, num = 0;
-
-                       if (ngroup->type != ntree->type)
-                               continue;
-
-                       for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next)
-                               if (ui_compatible_sockets(gsock->type, sock->type))
-                                       num++;
-
-                       for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) {
-                               if (!ui_compatible_sockets(gsock->type, sock->type))
-                                       continue;
-
-                               if (first) {
-                                       column = uiLayoutColumn(layout, FALSE);
-                                       uiBlockSetCurLayout(block, column);
-
-                                       uiItemL(column, IFACE_(cname), ICON_NODE);
-                                       but = block->buttons.last;
-                                       but->flag = UI_TEXT_LEFT;
-
-                                       first = 0;
-                               }
-
-                               if (num > 1) {
-                                       if (j == 0) {
-                                               uiItemL(column, ngroup->id.name + 2, ICON_NODE);
-                                               but = block->buttons.last;
-                                               but->flag = UI_TEXT_LEFT;
-                                       }
+       /* generate array of node types sorted by UI name */
+       bNodeType **sorted_ntypes = NULL;
+       BLI_array_declare(sorted_ntypes);
 
-                                       BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", gsock->name);
-                                       j++;
-                               }
-                               else
-                                       BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR);
+       NODE_TYPES_BEGIN(ntype) {
+               if (compatibility && !(ntype->compatibility & compatibility)) {
+                       continue;
+               }
 
-                               but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
-                                              NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
+               if (ntype->nclass != nclass) {
+                       continue;
+               }
 
-                               argN = MEM_dupallocN(arg);
-                               argN->type = NODE_GROUP;
-                               argN->ngroup = ngroup;
-                               argN->output = i;
-                               uiButSetNFunc(but, ui_node_link, argN, NULL);
-                       }
+               if (!ui_node_item_special_poll(ntree, ntype)) {
+                       continue;
                }
-       }
-       else {
-               bNodeTreeType *ttype = ntreeGetType(ntree->type);
 
-               for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
-                       bNodeSocketTemplate *stemp;
-                       char name[UI_MAX_NAME_STR];
-                       int i, j, num = 0;
+               BLI_array_append(sorted_ntypes, ntype);
+       }
+       NODE_TYPES_END
 
-                       if (compatibility && !(ntype->compatibility & compatibility))
-                               continue;
+       qsort(sorted_ntypes, BLI_array_count(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
 
-                       if (ntype->nclass != nclass)
+       /* generate UI */
+       for (int j = 0; j < BLI_array_count(sorted_ntypes); j++) {
+               bNodeType *ntype = sorted_ntypes[j];
+               NodeLinkItem *items;
+               int totitems;
+               char name[UI_MAX_NAME_STR];
+               const char *cur_node_name = NULL;
+               int i, num = 0;
+               int icon = ICON_NONE;
+               
+               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; i < totitems; ++i) {
+                       if (!ui_compatible_sockets(items[i].socket_type, sock->type))
                                continue;
-
-                       for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
-                               if (ui_compatible_sockets(stemp->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))
-                                       continue;
-
-                               if (first) {
-                                       column = uiLayoutColumn(layout, FALSE);
-                                       uiBlockSetCurLayout(block, column);
-
-                                       uiItemL(column, IFACE_(cname), ICON_NODE);
-                                       but = block->buttons.last;
-                                       but->flag = UI_TEXT_LEFT;
-
-                                       first = 0;
-                               }
-
-                               if (num > 1) {
-                                       if (j == 0) {
-                                               uiItemL(column, IFACE_(ntype->name), ICON_NODE);
-                                               but = block->buttons.last;
-                                               but->flag = UI_TEXT_LEFT;
-                                       }
-
-                                       BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", IFACE_(stemp->name));
-                                       j++;
+                       
+                       if (first) {
+                               column = uiLayoutColumn(layout, 0);
+                               UI_block_layout_set_current(block, column);
+                               
+                               uiItemL(column, IFACE_(cname), ICON_NODE);
+                               but = block->buttons.last;
+                               
+                               first = 0;
+                       }
+                       
+                       if (num > 1) {
+                               if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
+                                       cur_node_name = items[i].node_name;
+                                       /* XXX Do not use uiItemL here, it would add an empty icon as we are in a menu! */
+                                       uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_(cur_node_name), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+                                                NULL, 0.0, 0.0, 0.0, 0.0, "");
                                }
-                               else
-                                       BLI_strncpy(name, IFACE_(ntype->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;
-                               uiButSetNFunc(but, ui_node_link, argN, NULL);
+                               BLI_snprintf(name, UI_MAX_NAME_STR, "%s", IFACE_(items[i].socket_name));
+                               icon = ICON_BLANK1;
+                       }
+                       else {
+                               BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
+                               icon = ICON_NONE;
                        }
+                       
+                       but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, icon, 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->item = items[i];
+                       UI_but_funcN_set(but, ui_node_link, argN, NULL);
                }
+               
+               if (items)
+                       MEM_freeN(items);
        }
+
+       BLI_array_free(sorted_ntypes);
 }
 
 static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -456,38 +559,40 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       ViewRender *view_render = CTX_data_view_render(C);
        uiBlock *block = uiLayoutGetBlock(layout);
        uiBut *but = (uiBut *)but_p;
        uiLayout *split, *column;
        NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
        bNodeSocket *sock = arg->sock;
-       bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type);
+       bNodeTreeType *ntreetype = arg->ntree->typeinfo;
 
-       uiBlockSetCurLayout(block, layout);
-       split = uiLayoutSplit(layout, 0.0f, FALSE);
+       UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
+       UI_block_layout_set_current(block, layout);
+       split = uiLayoutSplit(layout, 0.0f, false);
 
        arg->bmain = bmain;
        arg->scene = scene;
        arg->layout = split;
 
        if (ntreetype && ntreetype->foreach_nodeclass)
-               ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
+               ntreetype->foreach_nodeclass(view_render, arg, node_menu_column_foreach_cb);
 
-       column = uiLayoutColumn(split, FALSE);
-       uiBlockSetCurLayout(block, column);
+       column = uiLayoutColumn(split, false);
+       UI_block_layout_set_current(block, column);
 
        if (sock->link) {
                uiItemL(column, IFACE_("Link"), ICON_NONE);
                but = block->buttons.last;
-               but->flag = UI_TEXT_LEFT;
+               but->drawflag = UI_BUT_TEXT_LEFT;
 
-               but = uiDefBut(block, BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+               but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
                               NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Remove nodes connected to the input"));
-               uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
+               UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
 
-               but = uiDefBut(block, BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+               but = uiDefBut(block, UI_BTYPE_BUT, 0, IFACE_("Disconnect"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
                               NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Disconnect nodes connected to the input"));
-               uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
+               UI_but_funcN_set(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
        }
 
        ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
@@ -503,10 +608,8 @@ 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);
+       UI_block_layout_set_current(block, layout);
 
        if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
                char name[UI_MAX_NAME_STR];
@@ -516,8 +619,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
        else
                but = uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
 
-       but->type = MENU;
-       but->flag |= UI_TEXT_LEFT | UI_BUT_NODE_LINK;
+       UI_but_type_set_menu_from_pulldown(but);
+
+       but->flag |= UI_BUT_NODE_LINK;
        but->poin = (char *)but;
        but->func_argN = arg;
 
@@ -539,13 +643,13 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
 
        RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
 
-       if (node->typeinfo->uifunc) {
+       if (node->typeinfo->draw_buttons) {
                if (node->type != NODE_GROUP) {
-                       split = uiLayoutSplit(layout, 0.35f, FALSE);
-                       col = uiLayoutColumn(split, FALSE);
-                       col = uiLayoutColumn(split, FALSE);
+                       split = uiLayoutSplit(layout, 0.35f, false);
+                       col = uiLayoutColumn(split, false);
+                       col = uiLayoutColumn(split, false);
 
-                       node->typeinfo->uifunc(col, C, &nodeptr);
+                       node->typeinfo->draw_buttons(col, C, &nodeptr);
                }
        }
 
@@ -555,13 +659,13 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
 
 static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
 {
-       PointerRNA inputptr;
+       PointerRNA inputptr, nodeptr;
        uiBlock *block = uiLayoutGetBlock(layout);
        uiBut *bt;
        uiLayout *split, *row, *col;
        bNode *lnode;
        char label[UI_MAX_NAME_STR];
-       int indent = (depth > 1) ? 2 * (depth - 1) : 0;
+       int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
        int dependency_loop;
 
        if (input->flag & SOCK_UNAVAIL)
@@ -577,21 +681,24 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
 
        /* socket RNA pointer */
        RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
+       RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
 
        /* indented label */
-       memset(label, ' ', indent);
+       for (i = 0; i < indent; i++) {
+               label[i] = ' ';
+       }
        label[indent] = '\0';
-       BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, IFACE_(input->name));
+       BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s:", IFACE_(input->name));
 
        /* split in label and value */
-       split = uiLayoutSplit(layout, 0.35f, FALSE);
+       split = uiLayoutSplit(layout, 0.35f, false);
 
-       row = uiLayoutRow(split, TRUE);
+       row = uiLayoutRow(split, true);
 
        if (depth > 0) {
-               uiBlockSetEmboss(block, UI_EMBOSSN);
+               UI_block_emboss_set(block, UI_EMBOSS_NONE);
 
-               if (lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) {
+               if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
                        int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN;
                        uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
                }
@@ -601,15 +708,15 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
                bt = block->buttons.last;
                bt->rect.xmax = UI_UNIT_X / 2;
 
-               uiBlockSetEmboss(block, UI_EMBOSS);
+               UI_block_emboss_set(block, UI_EMBOSS);
        }
 
        uiItemL(row, label, ICON_NONE);
        bt = block->buttons.last;
-       bt->flag = UI_TEXT_LEFT;
+       bt->drawflag = UI_BUT_TEXT_LEFT;
 
        if (dependency_loop) {
-               row = uiLayoutRow(split, FALSE);
+               row = uiLayoutRow(split, false);
                uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR);
        }
        else if (lnode) {
@@ -625,20 +732,29 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
        }
        else {
                /* input not linked, show value */
-               if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
-                       if (input->type == SOCK_VECTOR) {
-                               row = uiLayoutRow(split, FALSE);
-                               col = uiLayoutColumn(row, FALSE);
-
-                               uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
-                       }
-                       else {
-                               row = uiLayoutRow(split, TRUE);
-                               uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+               if (!(input->flag & SOCK_HIDE_VALUE)) {
+                       switch (input->type) {
+                               case SOCK_FLOAT:
+                               case SOCK_INT:
+                               case SOCK_BOOLEAN:
+                               case SOCK_RGBA:
+                               case SOCK_STRING:
+                                       row = uiLayoutRow(split, true);
+                                       uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+                                       break;
+                               case SOCK_VECTOR:
+                                       row = uiLayoutRow(split, false);
+                                       col = uiLayoutColumn(row, false);
+                                       uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
+                                       break;
+                                       
+                               default:
+                                       row = uiLayoutRow(split, false);
+                                       break;
                        }
                }
                else
-                       row = uiLayoutRow(split, FALSE);
+                       row = uiLayoutRow(split, false);
 
                uiTemplateNodeLink(row, ntree, node, input);
        }