Nodes: sort builtin compositor/shader/texture nodes alphabetically in menus
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 26 Apr 2016 22:58:25 +0000 (00:58 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 27 Apr 2016 19:37:14 +0000 (21:37 +0200)
Reviewed By: lukastoenne, dingto, Severin, carter2422

Differential Revision: https://developer.blender.org/D1957

release/scripts/startup/nodeitems_builtins.py
source/blender/editors/space_node/node_templates.c

index 9dca55ede001b9c7fba239525e908abc9aa71313..b93cb857e0a42e30f900e08e33302ef0fba071b1 100644 (file)
@@ -24,13 +24,25 @@ from nodeitems_utils import NodeCategory, NodeItem, NodeItemCustom
 
 # Subclasses for standard node types
 
+def alphabetical(items):
+       # for builtin nodes the convention is to sort by name
+    if isinstance(items, list):
+        return sorted(items, key=lambda item: item.label().lower)
+    return items
+
 class CompositorNodeCategory(NodeCategory):
+    def __init__(self, identifier, name, description="", items=None):
+        super().__init__(identifier, name, description, alphabetical(items))
+
     @classmethod
     def poll(cls, context):
         return (context.space_data.tree_type == 'CompositorNodeTree')
 
 
 class ShaderNewNodeCategory(NodeCategory):
+    def __init__(self, identifier, name, description="", items=None):
+        super().__init__(identifier, name, description, alphabetical(items))
+
     @classmethod
     def poll(cls, context):
         return (context.space_data.tree_type == 'ShaderNodeTree' and
@@ -38,6 +50,9 @@ class ShaderNewNodeCategory(NodeCategory):
 
 
 class ShaderOldNodeCategory(NodeCategory):
+    def __init__(self, identifier, name, description="", items=None):
+        super().__init__(identifier, name, description, alphabetical(items))
+
     @classmethod
     def poll(cls, context):
         return (context.space_data.tree_type == 'ShaderNodeTree' and
@@ -45,6 +60,9 @@ class ShaderOldNodeCategory(NodeCategory):
 
 
 class TextureNodeCategory(NodeCategory):
+    def __init__(self, identifier, name, description="", items=None):
+        super().__init__(identifier, name, description, alphabetical(items))
+
     @classmethod
     def poll(cls, context):
         return context.space_data.tree_type == 'TextureNodeTree'
index 0cbb7ea0220d8c6f4aedbbf043f54914417c26ff..9d1cf65b8acd7b51308f940bec55f338122efd1b 100644 (file)
@@ -32,6 +32,7 @@
 #include "DNA_node_types.h"
 #include "DNA_screen_types.h"
 
+#include "BLI_array.h"
 #include "BLI_listbase.h"
 #include "BLI_string.h"
 
@@ -420,6 +421,13 @@ 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 void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
 {
        bNodeTree *ntree = arg->ntree;
@@ -439,7 +447,26 @@ 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;
+
+               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];
@@ -447,12 +474,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);
@@ -502,7 +523,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)