Shading Nodes: Refactor Add menu
Refactor the Add menu in Shading nodes, with manually created menus, inspired by Geometry Nodes and more recently the Compositor. Minor sorting adjustments by splitting categories in groups, with separators in between groups, and sorted alphabetically. Shading node group assets are also populated in the menus. This is the first part of the re-organization of the Add menu, part of #111746 Pull Request: https://projects.blender.org/blender/blender/pulls/111798
This commit is contained in:
committed by
Pablo Vazquez
parent
b36367e663
commit
9db4c0ca4b
@@ -15,6 +15,7 @@ _modules = [
|
||||
"node_add_menu",
|
||||
"node_add_menu_compositor",
|
||||
"node_add_menu_geometry",
|
||||
"node_add_menu_shading",
|
||||
"properties_animviz",
|
||||
"properties_constraint",
|
||||
"properties_data_armature",
|
||||
|
||||
@@ -3,22 +3,26 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
from bl_ui import node_add_menu
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
|
||||
|
||||
def add_node_type(layout, node_type, *, label=None):
|
||||
def add_node_type(layout, node_type, *, label=None, poll=None):
|
||||
"""Add a node type to a menu."""
|
||||
bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type)
|
||||
if not label:
|
||||
label = bl_rna.name if bl_rna else iface_("Unknown")
|
||||
translation_context = bl_rna.translation_context if bl_rna else i18n_contexts.default
|
||||
props = layout.operator("node.add_node", text=label, text_ctxt=translation_context)
|
||||
props.type = node_type
|
||||
props.use_transform = True
|
||||
return props
|
||||
|
||||
if poll == True or poll == None:
|
||||
translation_context = bl_rna.translation_context if bl_rna else i18n_contexts.default
|
||||
props = layout.operator("node.add_node", text=label, text_ctxt=translation_context)
|
||||
props.type = node_type
|
||||
props.use_transform = True
|
||||
return props
|
||||
|
||||
|
||||
def draw_node_group_add_menu(context, layout):
|
||||
@@ -71,7 +75,19 @@ def add_repeat_zone(layout, label):
|
||||
return props
|
||||
|
||||
|
||||
class NODE_MT_category_layout(Menu):
|
||||
bl_idname = "NODE_MT_category_layout"
|
||||
bl_label = "Layout"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "NodeFrame")
|
||||
node_add_menu.add_node_type(layout, "NodeReroute")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
classes = (
|
||||
NODE_MT_category_layout,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
@@ -336,7 +336,7 @@ class NODE_MT_compositing_node_add_all(Menu):
|
||||
layout.menu("NODE_MT_category_COMP_VECTOR")
|
||||
layout.separator()
|
||||
layout.menu("NODE_MT_category_COMP_GROUP")
|
||||
layout.menu("NODE_MT_category_COMP_LAYOUT")
|
||||
layout.menu("NODE_MT_category_layout")
|
||||
|
||||
node_add_menu.draw_root_assets(layout)
|
||||
|
||||
@@ -359,7 +359,6 @@ classes = (
|
||||
NODE_MT_category_COMP_UTIL,
|
||||
NODE_MT_category_COMP_VECTOR,
|
||||
NODE_MT_category_COMP_GROUP,
|
||||
NODE_MT_category_COMP_LAYOUT,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
@@ -653,17 +653,6 @@ class NODE_MT_category_GEO_GROUP(Menu):
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_GEO_LAYOUT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_LAYOUT"
|
||||
bl_label = "Layout"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "NodeFrame")
|
||||
node_add_menu.add_node_type(layout, "NodeReroute")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_geometry_node_add_all(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_add_all"
|
||||
bl_label = ""
|
||||
@@ -690,7 +679,7 @@ class NODE_MT_geometry_node_add_all(Menu):
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES")
|
||||
layout.separator()
|
||||
layout.menu("NODE_MT_category_GEO_GROUP")
|
||||
layout.menu("NODE_MT_category_GEO_LAYOUT")
|
||||
layout.menu("NODE_MT_category_layout")
|
||||
node_add_menu.draw_root_assets(layout)
|
||||
|
||||
|
||||
@@ -736,7 +725,6 @@ classes = (
|
||||
NODE_MT_category_GEO_UTILITIES_MATH,
|
||||
NODE_MT_category_GEO_UTILITIES_ROTATION,
|
||||
NODE_MT_category_GEO_GROUP,
|
||||
NODE_MT_category_GEO_LAYOUT,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
256
scripts/startup/bl_ui/node_add_menu_shading.py
Normal file
256
scripts/startup/bl_ui/node_add_menu_shading.py
Normal file
@@ -0,0 +1,256 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
from bl_ui import node_add_menu
|
||||
from nodeitems_builtins import (
|
||||
eevee_cycles_shader_nodes_poll,
|
||||
line_style_shader_nodes_poll,
|
||||
object_cycles_shader_nodes_poll,
|
||||
object_eevee_cycles_shader_nodes_poll,
|
||||
object_eevee_shader_nodes_poll,
|
||||
world_shader_nodes_poll,
|
||||
)
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_INPUT(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_INPUT"
|
||||
bl_label = "Input"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeAmbientOcclusion")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeAttribute")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBevel")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeCameraData")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVertexColor")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeHairInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeFresnel")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeNewGeometry")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeLayerWeight")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeLightPath")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeObjectInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeParticleInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodePointInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeRGB")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTangent")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexCoord")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeUVMap")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVolumeInfo")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeWireframe")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_OUTPUT(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_OUTPUT"
|
||||
bl_label = "Output"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeOutputMaterial", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeOutputLight", poll=object_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeOutputAOV"),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeOutputWorld", poll=world_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll(context)),
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_SHADER(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_SHADER"
|
||||
bl_label = "Shader"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeAddShader", poll=eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBackground", poll=world_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfDiffuse", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeEmission", poll=eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfGlass", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfGlossy", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfHair", poll=object_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeHoldout", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMixShader", poll=eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfPrincipled", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfHairPrincipled", poll=object_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVolumePrincipled"),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfRefraction", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfSheen", poll=object_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeEeveeSpecular", poll=object_eevee_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSubsurfaceScattering", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfToon", poll=object_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfTranslucent", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBsdfTransparent", poll=object_eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVolumeAbsorption", poll=eevee_cycles_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll(context)),
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_COLOR(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_COLOR"
|
||||
bl_label = "Color"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBrightContrast")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeGamma")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeHueSaturation")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeInvert")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeLightFalloff")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
||||
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=iface_("Mix Color"))
|
||||
ops = props.settings.add()
|
||||
ops.name = "data_type"
|
||||
ops.value = "'RGBA'"
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_CONVERTER(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_CONVERTER"
|
||||
bl_label = "Converter"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBlackbody")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineColor")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMath")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBToBW")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateColor")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll(context)),
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorMath")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeWavelength")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_TEXTURE(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_TEXTURE"
|
||||
bl_label = "Texture"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexEnvironment")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexIES")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexImage")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexPointDensity")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexSky")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_VECTOR(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_VECTOR"
|
||||
bl_label = "Vector"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeBump")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeDisplacement")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMapping")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeNormal")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeNormalMap")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorDisplacement")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorTransform")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_SCRIPT(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_SCRIPT"
|
||||
bl_label = "Script"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeScript")
|
||||
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_SHADE_GROUP(Menu):
|
||||
bl_idname = "NODE_MT_category_SHADE_GROUP"
|
||||
bl_label = "Group"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node_add_menu.draw_node_group_add_menu(context, layout)
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_shading_node_add_all(Menu):
|
||||
bl_idname = "NODE_MT_shading_node_add_all"
|
||||
bl_label = "Add"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.menu("NODE_MT_category_SHADE_INPUT")
|
||||
layout.menu("NODE_MT_category_SHADE_OUTPUT")
|
||||
layout.separator()
|
||||
layout.menu("NODE_MT_category_SHADE_COLOR")
|
||||
layout.menu("NODE_MT_category_SHADE_CONVERTER")
|
||||
layout.menu("NODE_MT_category_SHADE_SHADER")
|
||||
layout.menu("NODE_MT_category_SHADE_TEXTURE")
|
||||
layout.menu("NODE_MT_category_SHADE_VECTOR")
|
||||
layout.separator()
|
||||
layout.menu("NODE_MT_category_SHADE_SCRIPT")
|
||||
layout.separator()
|
||||
layout.menu("NODE_MT_category_SHADE_GROUP")
|
||||
layout.menu("NODE_MT_category_layout")
|
||||
|
||||
node_add_menu.draw_root_assets(layout)
|
||||
|
||||
|
||||
classes = (
|
||||
NODE_MT_shading_node_add_all,
|
||||
NODE_MT_category_SHADE_INPUT,
|
||||
NODE_MT_category_SHADE_OUTPUT,
|
||||
NODE_MT_category_SHADE_COLOR,
|
||||
NODE_MT_category_SHADE_CONVERTER,
|
||||
NODE_MT_category_SHADE_SHADER,
|
||||
NODE_MT_category_SHADE_TEXTURE,
|
||||
NODE_MT_category_SHADE_VECTOR,
|
||||
NODE_MT_category_SHADE_SCRIPT,
|
||||
NODE_MT_category_SHADE_GROUP,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
@@ -239,6 +239,10 @@ class NODE_MT_add(bpy.types.Menu):
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_compositing_node_add_all")
|
||||
elif snode.tree_type == 'ShaderNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_shading_node_add_all")
|
||||
elif nodeitems_utils.has_node_categories(context):
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
props.use_transform = True
|
||||
|
||||
Reference in New Issue
Block a user