Workspace: Move engines to workspace and Properties Editor cleanup
[blender.git] / source / blender / editors / space_node / node_templates.c
index 9075117a7614e517b5d9db0ac1dc5a93937ca769..c791b9f6eae40d2c69b61b09849bc4db8b35c2de 100644 (file)
  *  \ingroup edinterface
  */
 
+#include <stdlib.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
 
 #include "DNA_node_types.h"
 #include "DNA_screen_types.h"
-#include "DNA_space_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"
@@ -150,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);
                }
        }
@@ -168,7 +169,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
        nodeUpdate(ntree, node_to);
        ntreeUpdateTree(bmain, ntree);
 
-       ED_node_tag_update_nodetree(bmain, ntree);
+       ED_node_tag_update_nodetree(bmain, ntree, node_to);
 }
 
 /* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -183,7 +184,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
        nodeUpdate(ntree, node_to);
        ntreeUpdateTree(bmain, ntree);
 
-       ED_node_tag_update_nodetree(bmain, ntree);
+       ED_node_tag_update_nodetree(bmain, ntree, node_to);
 }
 
 /* add new node connected to this socket, or replace an existing one */
@@ -215,8 +216,22 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
        }
        else if (!node_from) {
                node_from = nodeAddStaticNode(C, ntree, type);
-               node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
-               node_from->locy = node_to->locy;
+               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);
        }
@@ -265,7 +280,7 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
        nodeUpdate(ntree, node_to);
        ntreeUpdateTree(CTX_data_main(C), ntree);
 
-       ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
+       ED_node_tag_update_nodetree(CTX_data_main(C), ntree, node_to);
 }
 
 /****************************** Node Link Menu *******************************/
@@ -406,6 +421,27 @@ 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)
 {
        bNodeTree *ntree = arg->ntree;
@@ -425,7 +461,32 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
                        compatibility = NODE_OLD_SHADING;
        }
 
+       /* generate array of node types sorted by UI name */
+       bNodeType **sorted_ntypes = NULL;
+       BLI_array_declare(sorted_ntypes);
+
        NODE_TYPES_BEGIN(ntype) {
+               if (compatibility && !(ntype->compatibility & compatibility)) {
+                       continue;
+               }
+
+               if (ntype->nclass != nclass) {
+                       continue;
+               }
+
+               if (!ui_node_item_special_poll(ntree, ntype)) {
+                       continue;
+               }
+
+               BLI_array_append(sorted_ntypes, ntype);
+       }
+       NODE_TYPES_END
+
+       qsort(sorted_ntypes, BLI_array_count(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare);
+
+       /* 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];
@@ -433,12 +494,6 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
                int i, num = 0;
                int icon = ICON_NONE;
                
-               if (compatibility && !(ntype->compatibility & compatibility))
-                       continue;
-               
-               if (ntype->nclass != nclass)
-                       continue;
-               
                arg->node_type = ntype;
                
                ui_node_link_items(arg, SOCK_OUT, &items, &totitems);
@@ -488,7 +543,8 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
                if (items)
                        MEM_freeN(items);
        }
-       NODE_TYPES_END
+
+       BLI_array_free(sorted_ntypes);
 }
 
 static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -503,6 +559,7 @@ 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;
@@ -510,7 +567,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
        bNodeSocket *sock = arg->sock;
        bNodeTreeType *ntreetype = arg->ntree->typeinfo;
 
-       UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
+       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);
 
@@ -519,7 +576,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
        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);
        UI_block_layout_set_current(block, column);
@@ -608,7 +665,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
        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)
@@ -627,9 +684,11 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
        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);