Refactor the Add menu in Texture Nodes, with manually created menus, inspired by Geometry Nodes and more recently Shader and Compositor. Minor sorting adjustments by splitting categories in groups, with separators in between groups, and sorted alphabetically. Unlike other node editors, this menu will not feature assets for the time being. Doing so would add (more) burden of maintenance to a system that is deemed end-of-life, and likely to be rewritten before long. Part of #111746 Pull Request: https://projects.blender.org/blender/blender/pulls/111838
107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
# SPDX-FileCopyrightText: 2013-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import bpy
|
|
import nodeitems_utils
|
|
from nodeitems_utils import (
|
|
NodeCategory,
|
|
NodeItem,
|
|
NodeItemCustom,
|
|
)
|
|
|
|
|
|
# Subclasses for standard node types
|
|
|
|
class SortedNodeCategory(NodeCategory):
|
|
def __init__(self, identifier, name, description="", items=None):
|
|
# for builtin nodes the convention is to sort by name
|
|
if isinstance(items, list):
|
|
items = sorted(items, key=lambda item: item.label.lower())
|
|
|
|
super().__init__(identifier, name, description=description, items=items)
|
|
|
|
|
|
class CompositorNodeCategory(SortedNodeCategory):
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return (context.space_data.type == 'NODE_EDITOR' and
|
|
context.space_data.tree_type == 'CompositorNodeTree')
|
|
|
|
|
|
class ShaderNodeCategory(SortedNodeCategory):
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return (context.space_data.type == 'NODE_EDITOR' and
|
|
context.space_data.tree_type == 'ShaderNodeTree')
|
|
|
|
|
|
# Menu entry for node group tools.
|
|
def group_tools_draw(_self, layout, _context):
|
|
layout.operator("node.group_make")
|
|
layout.operator("node.group_ungroup")
|
|
layout.separator()
|
|
|
|
|
|
# Maps node tree type to group node type.
|
|
node_tree_group_type = {
|
|
'CompositorNodeTree': 'CompositorNodeGroup',
|
|
'ShaderNodeTree': 'ShaderNodeGroup',
|
|
'TextureNodeTree': 'TextureNodeGroup',
|
|
'GeometryNodeTree': 'GeometryNodeGroup',
|
|
}
|
|
|
|
|
|
# Generic node group items generator for shader, compositor, geometry and texture node groups.
|
|
def node_group_items(context):
|
|
if context is None:
|
|
return
|
|
space = context.space_data
|
|
if not space:
|
|
return
|
|
|
|
yield NodeItemCustom(draw=group_tools_draw)
|
|
|
|
if group_input_output_item_poll(context):
|
|
yield NodeItem("NodeGroupInput")
|
|
yield NodeItem("NodeGroupOutput")
|
|
|
|
ntree = space.edit_tree
|
|
if not ntree:
|
|
return
|
|
|
|
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
|
|
|
for group in context.blend_data.node_groups:
|
|
if group.bl_idname != ntree.bl_idname:
|
|
continue
|
|
# Filter out recursive groups.
|
|
if group.contains_tree(ntree):
|
|
continue
|
|
# Filter out hidden node-trees.
|
|
if group.name.startswith('.'):
|
|
continue
|
|
yield NodeItem(node_tree_group_type[group.bl_idname],
|
|
label=group.name,
|
|
settings={"node_tree": "bpy.data.node_groups[%r]" % group.name})
|
|
|
|
|
|
# only show input/output nodes inside node groups
|
|
def group_input_output_item_poll(context):
|
|
space = context.space_data
|
|
if space.edit_tree in bpy.data.node_groups.values():
|
|
return True
|
|
return False
|
|
|
|
|
|
def register():
|
|
pass
|
|
|
|
|
|
def unregister():
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
register()
|