Shading Nodes: Refactor Add menu #111798

Merged
Pablo Vazquez merged 2 commits from pablovazquez/blender:ui-nodes-shading-menu-refactor into main 2023-09-01 20:46:19 +02:00
6 changed files with 285 additions and 21 deletions

View File

@ -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",

View File

@ -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):
pablovazquez marked this conversation as resolved Outdated

NODE_MT_category_LAYOUT -> NODE_MT_category_layout. The only reason for the caps was to use the same menu idnames as before the refactor. Since this is different that doesn't matter anymore.

`NODE_MT_category_LAYOUT` -> `NODE_MT_category_layout`. The only reason for the caps was to use the same menu idnames as before the refactor. Since this is different that doesn't matter anymore.
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.

View File

@ -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.

View File

@ -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.

View 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)

View File

@ -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