diff options
Diffstat (limited to 'node_wrangler.py')
-rw-r--r-- | node_wrangler.py | 1233 |
1 files changed, 167 insertions, 1066 deletions
diff --git a/node_wrangler.py b/node_wrangler.py index 1a815dc6..cc1b85fe 100644 --- a/node_wrangler.py +++ b/node_wrangler.py @@ -3,7 +3,7 @@ bl_info = { "name": "Node Wrangler", "author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer", - "version": (3, 40), + "version": (3, 41), "blender": (2, 93, 0), "location": "Node Editor Toolbar or Shift-W", "description": "Various tools to enhance and speed up node-based workflow", @@ -72,406 +72,6 @@ rl_outputs = ( RL_entry('use_pass_z', 'Z', 'Depth', True, True), ) -# shader nodes -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_input_nodes_props = ( - ('ShaderNodeAmbientOcclusion', 'AMBIENT_OCCLUSION', 'Ambient Occlusion'), - ('ShaderNodeAttribute', 'ATTRIBUTE', 'Attribute'), - ('ShaderNodeBevel', 'BEVEL', 'Bevel'), - ('ShaderNodeCameraData', 'CAMERA', 'Camera Data'), - ('ShaderNodeFresnel', 'FRESNEL', 'Fresnel'), - ('ShaderNodeNewGeometry', 'NEW_GEOMETRY', 'Geometry'), - ('ShaderNodeHairInfo', 'HAIR_INFO', 'Hair Info'), - ('ShaderNodeLayerWeight', 'LAYER_WEIGHT', 'Layer Weight'), - ('ShaderNodeLightPath', 'LIGHT_PATH', 'Light Path'), - ('ShaderNodeObjectInfo', 'OBJECT_INFO', 'Object Info'), - ('ShaderNodeParticleInfo', 'PARTICLE_INFO', 'Particle Info'), - ('ShaderNodeRGB', 'RGB', 'RGB'), - ('ShaderNodeTangent', 'TANGENT', 'Tangent'), - ('ShaderNodeTexCoord', 'TEX_COORD', 'Texture Coordinate'), - ('ShaderNodeUVMap', 'UVMAP', 'UV Map'), - ('ShaderNodeValue', 'VALUE', 'Value'), - ('ShaderNodeVertexColor', 'VERTEX_COLOR', 'Vertex Color'), - ('ShaderNodeVolumeInfo', 'VOLUME_INFO', 'Volume Info'), - ('ShaderNodeWireframe', 'WIREFRAME', 'Wireframe'), - -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_output_nodes_props = ( - ('ShaderNodeOutputAOV', 'OUTPUT_AOV', 'AOV Output'), - ('ShaderNodeOutputLight', 'OUTPUT_LIGHT', 'Light Output'), - ('ShaderNodeOutputMaterial', 'OUTPUT_MATERIAL', 'Material Output'), - ('ShaderNodeOutputWorld', 'OUTPUT_WORLD', 'World Output'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_shader_nodes_props = ( - ('ShaderNodeAddShader', 'ADD_SHADER', 'Add Shader'), - ('ShaderNodeBsdfAnisotropic', 'BSDF_ANISOTROPIC', 'Anisotropic BSDF'), - ('ShaderNodeBsdfDiffuse', 'BSDF_DIFFUSE', 'Diffuse BSDF'), - ('ShaderNodeEmission', 'EMISSION', 'Emission'), - ('ShaderNodeBsdfGlass', 'BSDF_GLASS', 'Glass BSDF'), - ('ShaderNodeBsdfGlossy', 'BSDF_GLOSSY', 'Glossy BSDF'), - ('ShaderNodeBsdfHair', 'BSDF_HAIR', 'Hair BSDF'), - ('ShaderNodeHoldout', 'HOLDOUT', 'Holdout'), - ('ShaderNodeMixShader', 'MIX_SHADER', 'Mix Shader'), - ('ShaderNodeBsdfPrincipled', 'BSDF_PRINCIPLED', 'Principled BSDF'), - ('ShaderNodeBsdfHairPrincipled', 'BSDF_HAIR_PRINCIPLED', 'Principled Hair BSDF'), - ('ShaderNodeVolumePrincipled', 'PRINCIPLED_VOLUME', 'Principled Volume'), - ('ShaderNodeBsdfRefraction', 'BSDF_REFRACTION', 'Refraction BSDF'), - ('ShaderNodeSubsurfaceScattering', 'SUBSURFACE_SCATTERING', 'Subsurface Scattering'), - ('ShaderNodeBsdfToon', 'BSDF_TOON', 'Toon BSDF'), - ('ShaderNodeBsdfTranslucent', 'BSDF_TRANSLUCENT', 'Translucent BSDF'), - ('ShaderNodeBsdfTransparent', 'BSDF_TRANSPARENT', 'Transparent BSDF'), - ('ShaderNodeBsdfVelvet', 'BSDF_VELVET', 'Velvet BSDF'), - ('ShaderNodeBackground', 'BACKGROUND', 'Background'), - ('ShaderNodeVolumeAbsorption', 'VOLUME_ABSORPTION', 'Volume Absorption'), - ('ShaderNodeVolumeScatter', 'VOLUME_SCATTER', 'Volume Scatter'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping things in alphabetical order so we don't need to sort later. -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -shaders_texture_nodes_props = ( - ('ShaderNodeTexBrick', 'TEX_BRICK', 'Brick Texture'), - ('ShaderNodeTexChecker', 'TEX_CHECKER', 'Checker Texture'), - ('ShaderNodeTexEnvironment', 'TEX_ENVIRONMENT', 'Environment Texture'), - ('ShaderNodeTexGradient', 'TEX_GRADIENT', 'Gradient Texture'), - ('ShaderNodeTexIES', 'TEX_IES', 'IES Texture'), - ('ShaderNodeTexImage', 'TEX_IMAGE', 'Image Texture'), - ('ShaderNodeTexMagic', 'TEX_MAGIC', 'Magic Texture'), - ('ShaderNodeTexMusgrave', 'TEX_MUSGRAVE', 'Musgrave Texture'), - ('ShaderNodeTexNoise', 'TEX_NOISE', 'Noise Texture'), - ('ShaderNodeTexPointDensity', 'TEX_POINTDENSITY', 'Point Density'), - ('ShaderNodeTexSky', 'TEX_SKY', 'Sky Texture'), - ('ShaderNodeTexVoronoi', 'TEX_VORONOI', 'Voronoi Texture'), - ('ShaderNodeTexWave', 'TEX_WAVE', 'Wave Texture'), - ('ShaderNodeTexWhiteNoise', 'TEX_WHITE_NOISE', 'White Noise'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_color_nodes_props = ( - ('ShaderNodeBrightContrast', 'BRIGHTCONTRAST', 'Bright Contrast'), - ('ShaderNodeGamma', 'GAMMA', 'Gamma'), - ('ShaderNodeHueSaturation', 'HUE_SAT', 'Hue Saturation Value'), - ('ShaderNodeInvert', 'INVERT', 'Invert'), - ('ShaderNodeLightFalloff', 'LIGHT_FALLOFF', 'Light Falloff'), - ('ShaderNodeMixRGB', 'MIX_RGB', 'MixRGB'), - ('ShaderNodeRGBCurve', 'CURVE_RGB', 'RGB Curves'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_vector_nodes_props = ( - ('ShaderNodeBump', 'BUMP', 'Bump'), - ('ShaderNodeDisplacement', 'DISPLACEMENT', 'Displacement'), - ('ShaderNodeMapping', 'MAPPING', 'Mapping'), - ('ShaderNodeNormal', 'NORMAL', 'Normal'), - ('ShaderNodeNormalMap', 'NORMAL_MAP', 'Normal Map'), - ('ShaderNodeVectorCurve', 'CURVE_VEC', 'Vector Curves'), - ('ShaderNodeVectorDisplacement', 'VECTOR_DISPLACEMENT', 'Vector Displacement'), - ('ShaderNodeVectorTransform', 'VECT_TRANSFORM', 'Vector Transform'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_converter_nodes_props = ( - ('ShaderNodeBlackbody', 'BLACKBODY', 'Blackbody'), - ('ShaderNodeClamp', 'CLAMP', 'Clamp'), - ('ShaderNodeValToRGB', 'VALTORGB', 'ColorRamp'), - ('ShaderNodeCombineHSV', 'COMBHSV', 'Combine HSV'), - ('ShaderNodeCombineRGB', 'COMBRGB', 'Combine RGB'), - ('ShaderNodeCombineXYZ', 'COMBXYZ', 'Combine XYZ'), - ('ShaderNodeMapRange', 'MAP_RANGE', 'Map Range'), - ('ShaderNodeMath', 'MATH', 'Math'), - ('ShaderNodeRGBToBW', 'RGBTOBW', 'RGB to BW'), - ('ShaderNodeSeparateRGB', 'SEPRGB', 'Separate RGB'), - ('ShaderNodeSeparateXYZ', 'SEPXYZ', 'Separate XYZ'), - ('ShaderNodeSeparateHSV', 'SEPHSV', 'Separate HSV'), - ('ShaderNodeVectorMath', 'VECT_MATH', 'Vector Math'), - ('ShaderNodeWavelength', 'WAVELENGTH', 'Wavelength'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -shaders_layout_nodes_props = ( - ('NodeFrame', 'FRAME', 'Frame'), - ('NodeReroute', 'REROUTE', 'Reroute'), -) - -# compositing nodes -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_input_nodes_props = ( - ('CompositorNodeBokehImage', 'BOKEHIMAGE', 'Bokeh Image'), - ('CompositorNodeImage', 'IMAGE', 'Image'), - ('CompositorNodeMask', 'MASK', 'Mask'), - ('CompositorNodeMovieClip', 'MOVIECLIP', 'Movie Clip'), - ('CompositorNodeRLayers', 'R_LAYERS', 'Render Layers'), - ('CompositorNodeRGB', 'RGB', 'RGB'), - ('CompositorNodeTexture', 'TEXTURE', 'Texture'), - ('CompositorNodeTime', 'TIME', 'Time'), - ('CompositorNodeTrackPos', 'TRACKPOS', 'Track Position'), - ('CompositorNodeValue', 'VALUE', 'Value'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_output_nodes_props = ( - ('CompositorNodeComposite', 'COMPOSITE', 'Composite'), - ('CompositorNodeOutputFile', 'OUTPUT_FILE', 'File Output'), - ('CompositorNodeLevels', 'LEVELS', 'Levels'), - ('CompositorNodeSplitViewer', 'SPLITVIEWER', 'Split Viewer'), - ('CompositorNodeViewer', 'VIEWER', 'Viewer'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_color_nodes_props = ( - ('CompositorNodeAlphaOver', 'ALPHAOVER', 'Alpha Over'), - ('CompositorNodeBrightContrast', 'BRIGHTCONTRAST', 'Bright/Contrast'), - ('CompositorNodeColorBalance', 'COLORBALANCE', 'Color Balance'), - ('CompositorNodeColorCorrection', 'COLORCORRECTION', 'Color Correction'), - ('CompositorNodeGamma', 'GAMMA', 'Gamma'), - ('CompositorNodeHueCorrect', 'HUECORRECT', 'Hue Correct'), - ('CompositorNodeHueSat', 'HUE_SAT', 'Hue Saturation Value'), - ('CompositorNodeInvert', 'INVERT', 'Invert'), - ('CompositorNodeMixRGB', 'MIX_RGB', 'Mix'), - ('CompositorNodeCurveRGB', 'CURVE_RGB', 'RGB Curves'), - ('CompositorNodeTonemap', 'TONEMAP', 'Tonemap'), - ('CompositorNodeZcombine', 'ZCOMBINE', 'Z Combine'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_converter_nodes_props = ( - ('CompositorNodePremulKey', 'PREMULKEY', 'Alpha Convert'), - ('CompositorNodeValToRGB', 'VALTORGB', 'ColorRamp'), - ('CompositorNodeCombHSVA', 'COMBHSVA', 'Combine HSVA'), - ('CompositorNodeCombRGBA', 'COMBRGBA', 'Combine RGBA'), - ('CompositorNodeCombYCCA', 'COMBYCCA', 'Combine YCbCrA'), - ('CompositorNodeCombYUVA', 'COMBYUVA', 'Combine YUVA'), - ('CompositorNodeIDMask', 'ID_MASK', 'ID Mask'), - ('CompositorNodeMath', 'MATH', 'Math'), - ('CompositorNodeRGBToBW', 'RGBTOBW', 'RGB to BW'), - ('CompositorNodeSepRGBA', 'SEPRGBA', 'Separate RGBA'), - ('CompositorNodeSepHSVA', 'SEPHSVA', 'Separate HSVA'), - ('CompositorNodeSepYUVA', 'SEPYUVA', 'Separate YUVA'), - ('CompositorNodeSepYCCA', 'SEPYCCA', 'Separate YCbCrA'), - ('CompositorNodeSetAlpha', 'SETALPHA', 'Set Alpha'), - ('CompositorNodeSwitchView', 'VIEWSWITCH', 'View Switch'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_filter_nodes_props = ( - ('CompositorNodeBilateralblur', 'BILATERALBLUR', 'Bilateral Blur'), - ('CompositorNodeBlur', 'BLUR', 'Blur'), - ('CompositorNodeBokehBlur', 'BOKEHBLUR', 'Bokeh Blur'), - ('CompositorNodeDefocus', 'DEFOCUS', 'Defocus'), - ('CompositorNodeDenoise', 'DENOISE', 'Denoise'), - ('CompositorNodeDespeckle', 'DESPECKLE', 'Despeckle'), - ('CompositorNodeDilateErode', 'DILATEERODE', 'Dilate/Erode'), - ('CompositorNodeDBlur', 'DBLUR', 'Directional Blur'), - ('CompositorNodeFilter', 'FILTER', 'Filter'), - ('CompositorNodeGlare', 'GLARE', 'Glare'), - ('CompositorNodeInpaint', 'INPAINT', 'Inpaint'), - ('CompositorNodePixelate', 'PIXELATE', 'Pixelate'), - ('CompositorNodeSunBeams', 'SUNBEAMS', 'Sun Beams'), - ('CompositorNodeVecBlur', 'VECBLUR', 'Vector Blur'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_vector_nodes_props = ( - ('CompositorNodeMapRange', 'MAP_RANGE', 'Map Range'), - ('CompositorNodeMapValue', 'MAP_VALUE', 'Map Value'), - ('CompositorNodeNormal', 'NORMAL', 'Normal'), - ('CompositorNodeNormalize', 'NORMALIZE', 'Normalize'), - ('CompositorNodeCurveVec', 'CURVE_VEC', 'Vector Curves'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_matte_nodes_props = ( - ('CompositorNodeBoxMask', 'BOXMASK', 'Box Mask'), - ('CompositorNodeChannelMatte', 'CHANNEL_MATTE', 'Channel Key'), - ('CompositorNodeChromaMatte', 'CHROMA_MATTE', 'Chroma Key'), - ('CompositorNodeColorMatte', 'COLOR_MATTE', 'Color Key'), - ('CompositorNodeColorSpill', 'COLOR_SPILL', 'Color Spill'), - ('CompositorNodeCryptomatte', 'CRYPTOMATTE', 'Cryptomatte'), - ('CompositorNodeDiffMatte', 'DIFF_MATTE', 'Difference Key'), - ('CompositorNodeDistanceMatte', 'DISTANCE_MATTE', 'Distance Key'), - ('CompositorNodeDoubleEdgeMask', 'DOUBLEEDGEMASK', 'Double Edge Mask'), - ('CompositorNodeEllipseMask', 'ELLIPSEMASK', 'Ellipse Mask'), - ('CompositorNodeKeying', 'KEYING', 'Keying'), - ('CompositorNodeKeyingScreen', 'KEYINGSCREEN', 'Keying Screen'), - ('CompositorNodeLumaMatte', 'LUMA_MATTE', 'Luminance Key'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_distort_nodes_props = ( - ('CompositorNodeCornerPin', 'CORNERPIN', 'Corner Pin'), - ('CompositorNodeCrop', 'CROP', 'Crop'), - ('CompositorNodeDisplace', 'DISPLACE', 'Displace'), - ('CompositorNodeFlip', 'FLIP', 'Flip'), - ('CompositorNodeLensdist', 'LENSDIST', 'Lens Distortion'), - ('CompositorNodeMapUV', 'MAP_UV', 'Map UV'), - ('CompositorNodeMovieDistortion', 'MOVIEDISTORTION', 'Movie Distortion'), - ('CompositorNodePlaneTrackDeform', 'PLANETRACKDEFORM', 'Plane Track Deform'), - ('CompositorNodeRotate', 'ROTATE', 'Rotate'), - ('CompositorNodeScale', 'SCALE', 'Scale'), - ('CompositorNodeStabilize', 'STABILIZE2D', 'Stabilize 2D'), - ('CompositorNodeTransform', 'TRANSFORM', 'Transform'), - ('CompositorNodeTranslate', 'TRANSLATE', 'Translate'), -) -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -# Keeping things in alphabetical order so we don't need to sort later. -compo_layout_nodes_props = ( - ('NodeFrame', 'FRAME', 'Frame'), - ('NodeReroute', 'REROUTE', 'Reroute'), - ('CompositorNodeSwitch', 'SWITCH', 'Switch'), -) -# Blender Render material nodes -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_input_nodes_props = ( - ('ShaderNodeMaterial', 'MATERIAL', 'Material'), - ('ShaderNodeCameraData', 'CAMERA', 'Camera Data'), - ('ShaderNodeLightData', 'LIGHT', 'Light Data'), - ('ShaderNodeValue', 'VALUE', 'Value'), - ('ShaderNodeRGB', 'RGB', 'RGB'), - ('ShaderNodeTexture', 'TEXTURE', 'Texture'), - ('ShaderNodeGeometry', 'GEOMETRY', 'Geometry'), - ('ShaderNodeExtendedMaterial', 'MATERIAL_EXT', 'Extended Material'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_output_nodes_props = ( - ('ShaderNodeOutput', 'OUTPUT', 'Output'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_color_nodes_props = ( - ('ShaderNodeMixRGB', 'MIX_RGB', 'MixRGB'), - ('ShaderNodeRGBCurve', 'CURVE_RGB', 'RGB Curves'), - ('ShaderNodeInvert', 'INVERT', 'Invert'), - ('ShaderNodeHueSaturation', 'HUE_SAT', 'Hue Saturation Value'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_vector_nodes_props = ( - ('ShaderNodeNormal', 'NORMAL', 'Normal'), - ('ShaderNodeMapping', 'MAPPING', 'Mapping'), - ('ShaderNodeVectorCurve', 'CURVE_VEC', 'Vector Curves'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_converter_nodes_props = ( - ('ShaderNodeValToRGB', 'VALTORGB', 'ColorRamp'), - ('ShaderNodeRGBToBW', 'RGBTOBW', 'RGB to BW'), - ('ShaderNodeMath', 'MATH', 'Math'), - ('ShaderNodeVectorMath', 'VECT_MATH', 'Vector Math'), - ('ShaderNodeSqueeze', 'SQUEEZE', 'Squeeze Value'), - ('ShaderNodeSeparateRGB', 'SEPRGB', 'Separate RGB'), - ('ShaderNodeCombineRGB', 'COMBRGB', 'Combine RGB'), - ('ShaderNodeSeparateHSV', 'SEPHSV', 'Separate HSV'), - ('ShaderNodeCombineHSV', 'COMBHSV', 'Combine HSV'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -blender_mat_layout_nodes_props = ( - ('NodeReroute', 'REROUTE', 'Reroute'), -) - -# Texture Nodes -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_input_nodes_props = ( - ('TextureNodeCurveTime', 'CURVE_TIME', 'Curve Time'), - ('TextureNodeCoordinates', 'COORD', 'Coordinates'), - ('TextureNodeTexture', 'TEXTURE', 'Texture'), - ('TextureNodeImage', 'IMAGE', 'Image'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_output_nodes_props = ( - ('TextureNodeOutput', 'OUTPUT', 'Output'), - ('TextureNodeViewer', 'VIEWER', 'Viewer'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_color_nodes_props = ( - ('TextureNodeMixRGB', 'MIX_RGB', 'Mix RGB'), - ('TextureNodeCurveRGB', 'CURVE_RGB', 'RGB Curves'), - ('TextureNodeInvert', 'INVERT', 'Invert'), - ('TextureNodeHueSaturation', 'HUE_SAT', 'Hue Saturation Value'), - ('TextureNodeCompose', 'COMPOSE', 'Combine RGBA'), - ('TextureNodeDecompose', 'DECOMPOSE', 'Separate RGBA'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_pattern_nodes_props = ( - ('TextureNodeChecker', 'CHECKER', 'Checker'), - ('TextureNodeBricks', 'BRICKS', 'Bricks'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_textures_nodes_props = ( - ('TextureNodeTexNoise', 'TEX_NOISE', 'Noise'), - ('TextureNodeTexDistNoise', 'TEX_DISTNOISE', 'Distorted Noise'), - ('TextureNodeTexClouds', 'TEX_CLOUDS', 'Clouds'), - ('TextureNodeTexBlend', 'TEX_BLEND', 'Blend'), - ('TextureNodeTexVoronoi', 'TEX_VORONOI', 'Voronoi'), - ('TextureNodeTexMagic', 'TEX_MAGIC', 'Magic'), - ('TextureNodeTexMarble', 'TEX_MARBLE', 'Marble'), - ('TextureNodeTexWood', 'TEX_WOOD', 'Wood'), - ('TextureNodeTexMusgrave', 'TEX_MUSGRAVE', 'Musgrave'), - ('TextureNodeTexStucci', 'TEX_STUCCI', 'Stucci'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_converter_nodes_props = ( - ('TextureNodeMath', 'MATH', 'Math'), - ('TextureNodeValToRGB', 'VALTORGB', 'ColorRamp'), - ('TextureNodeRGBToBW', 'RGBTOBW', 'RGB to BW'), - ('TextureNodeValToNor', 'VALTONOR', 'Value to Normal'), - ('TextureNodeDistance', 'DISTANCE', 'Distance'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_distort_nodes_props = ( - ('TextureNodeScale', 'SCALE', 'Scale'), - ('TextureNodeTranslate', 'TRANSLATE', 'Translate'), - ('TextureNodeRotate', 'ROTATE', 'Rotate'), - ('TextureNodeAt', 'AT', 'At'), -) - -# (rna_type.identifier, type, rna_type.name) -# Keeping mixed case to avoid having to translate entries when adding new nodes in operators. -texture_layout_nodes_props = ( - ('NodeReroute', 'REROUTE', 'Reroute'), -) - # list of blend types of "Mix" nodes in a form that can be used as 'items' for EnumProperty. # used list, not tuple for easy merging with other lists. blend_types = [ @@ -596,6 +196,13 @@ def get_nodes_from_category(category_name, context): if category.name == category_name: return sorted(category.items(context), key=lambda node: node.label) +def get_first_enabled_output(node): + for output in node.outputs: + if output.enabled: + return output + else: + return node.outputs[0] + def is_visible_socket(socket): return not socket.hide and socket.enabled and socket.type != 'CUSTOM' @@ -813,8 +420,7 @@ def draw_circle_2d_filled(shader, mx, my, radius, colour=(1.0, 1.0, 1.0, 0.7)): def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)): - area_width = bpy.context.area.width - (16*dpifac()) - 1 - bottom_bar = (16*dpifac()) + 1 + area_width = bpy.context.area.width sides = 16 radius = radius*dpifac() @@ -840,7 +446,7 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) vertices = [(mx,my)] for i in range(sides+1): if (4<=i<=8): - if my > bottom_bar and mx < area_width: + if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my vertices.append((cosine,sine)) @@ -854,7 +460,7 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) vertices = [(mx,my)] for i in range(sides+1): if (0<=i<=4): - if my > bottom_bar and mx < area_width: + if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my vertices.append((cosine,sine)) @@ -868,7 +474,7 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) vertices = [(mx,my)] for i in range(sides+1): if (8<=i<=12): - if my > bottom_bar and mx < area_width: + if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my vertices.append((cosine,sine)) @@ -882,7 +488,7 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) vertices = [(mx,my)] for i in range(sides+1): if (12<=i<=16): - if my > bottom_bar and mx < area_width: + if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my vertices.append((cosine,sine)) @@ -911,18 +517,15 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False) m1x = min(m1x, area_width) m2x = min(m2x, area_width) - if m1y > bottom_bar and m2y > bottom_bar: - vertices.extend([(m1x,m1y), (m2x,m1y), - (m2x,m1y+radius), (m1x,m1y+radius)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) - id_last += 4 + vertices.extend([(m1x,m1y), (m2x,m1y), + (m2x,m1y+radius), (m1x,m1y+radius)]) + indices.extend([(id_last, id_last+1, id_last+3), + (id_last+3, id_last+1, id_last+2)]) + id_last += 4 # Right edge m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False) m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False) - m1y = max(m1y, bottom_bar) - m2y = max(m2y, bottom_bar) if m1x < area_width and m2x < area_width: vertices.extend([(m1x,m2y), (m1x+radius,m2y), (m1x+radius,m1y), (m1x,m1y)]) @@ -935,11 +538,10 @@ def draw_rounded_node_border(shader, node, radius=8, colour=(1.0, 1.0, 1.0, 0.7) m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy-ndimy, clip=False) m1x = min(m1x, area_width) m2x = min(m2x, area_width) - if m1y > bottom_bar and m2y > bottom_bar: - vertices.extend([(m1x,m2y), (m2x,m2y), - (m2x,m1y-radius), (m1x,m1y-radius)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) + vertices.extend([(m1x,m2y), (m2x,m2y), + (m2x,m1y-radius), (m1x,m1y-radius)]) + indices.extend([(id_last, id_last+1, id_last+3), + (id_last+3, id_last+1, id_last+2)]) # now draw all edges in one batch if len(vertices) != 0: @@ -1051,7 +653,7 @@ def get_internal_socket(socket): return iterator[i] def is_viewer_link(link, output_node): - if "Emission Viewer" in link.to_node.name or link.to_node == output_node and link.to_socket == output_node.inputs[0]: + if link.to_node == output_node and link.to_socket == output_node.inputs[0]: return True if link.to_node.type == 'GROUP_OUTPUT': socket = get_internal_socket(link.to_socket) @@ -1068,8 +670,6 @@ def get_output_location(tree): # get right-most location sorted_by_xloc = (sorted(tree.nodes, key=lambda x: x.location.x)) max_xloc_node = sorted_by_xloc[-1] - if max_xloc_node.name == 'Emission Viewer': - max_xloc_node = sorted_by_xloc[-2] # get average y location sum_yloc = 0 @@ -1686,7 +1286,7 @@ class NWAddAttrNode(Operator, NWBase): class NWPreviewNode(Operator, NWBase): bl_idname = "node.nw_preview_node" bl_label = "Preview Node" - bl_description = "Connect active node to Emission Shader for shadeless previews, or to the geometry node tree's output" + bl_description = "Connect active node to the Node Group output or the Material Output" bl_options = {'REGISTER', 'UNDO'} # If false, the operator is not executed if the current node group happens to be a geometry nodes group. @@ -1697,7 +1297,6 @@ class NWPreviewNode(Operator, NWBase): def __init__(self): self.shader_output_type = "" self.shader_output_ident = "" - self.shader_viewer_ident = "" @classmethod def poll(cls, context): @@ -1748,16 +1347,13 @@ class NWPreviewNode(Operator, NWBase): if space.id not in [light for light in bpy.data.lights]: # cannot use bpy.data.lights directly as iterable self.shader_output_type = "OUTPUT_MATERIAL" self.shader_output_ident = "ShaderNodeOutputMaterial" - self.shader_viewer_ident = "ShaderNodeEmission" else: self.shader_output_type = "OUTPUT_LIGHT" self.shader_output_ident = "ShaderNodeOutputLight" - self.shader_viewer_ident = "ShaderNodeEmission" elif shader_type == 'WORLD': self.shader_output_type = "OUTPUT_WORLD" self.shader_output_ident = "ShaderNodeOutputWorld" - self.shader_viewer_ident = "ShaderNodeBackground" def get_shader_output_node(self, tree): for node in tree.nodes: @@ -1820,8 +1416,7 @@ class NWPreviewNode(Operator, NWBase): self.used_viewer_sockets_active_mat = [] materialout = self.get_shader_output_node(bpy.context.space_data.node_tree) if materialout: - emission = self.get_viewer_node(materialout) - self.search_sockets((emission if emission else materialout), self.used_viewer_sockets_active_mat) + self.search_sockets(materialout, self.used_viewer_sockets_active_mat) return socket in self.used_viewer_sockets_active_mat def is_socket_used_other_mats(self, socket): @@ -1834,18 +1429,9 @@ class NWPreviewNode(Operator, NWBase): # get viewer node materialout = self.get_shader_output_node(mat.node_tree) if materialout: - emission = self.get_viewer_node(materialout) - self.search_sockets((emission if emission else materialout), self.used_viewer_sockets_other_mats) + self.search_sockets(materialout, self.used_viewer_sockets_other_mats) return socket in self.used_viewer_sockets_other_mats - @staticmethod - def get_viewer_node(materialout): - input_socket = materialout.inputs[0] - if len(input_socket.links) > 0: - node = input_socket.links[0].from_node - if node.type == 'EMISSION' and node.name == "Emission Viewer": - return node - def invoke(self, context, event): space = context.space_data # Ignore operator when running in wrong context. @@ -1854,7 +1440,6 @@ class NWPreviewNode(Operator, NWBase): shader_type = space.shader_type self.init_shader_variables(space, shader_type) - shader_types = [x[1] for x in shaders_shader_nodes_props] mlocx = event.mouse_region_x mlocy = event.mouse_region_y select_node = bpy.ops.node.select(location=(mlocx, mlocy), extend=False) @@ -1864,8 +1449,7 @@ class NWPreviewNode(Operator, NWBase): base_node_tree = space.node_tree active = nodes.active - # For geometry node trees we just connect to the group output, - # because there is no "viewer node" yet. + # For geometry node trees we just connect to the group output if space.tree_type == "GeometryNodeTree": valid = False if active: @@ -1903,7 +1487,6 @@ class NWPreviewNode(Operator, NWBase): out_i = valid_outputs[0] make_links = [] # store sockets for new links - delete_nodes = [] # store unused nodes to delete in the end if active.outputs: # If there is no 'GEOMETRY' output type - We can't preview the node if out_i is None: @@ -1944,10 +1527,6 @@ class NWPreviewNode(Operator, NWBase): tree = socket.id_data tree.outputs.remove(socket) - # Delete nodes - for tree, node in delete_nodes: - tree.nodes.remove(node) - nodes.active = active active.select = True force_update(context) @@ -1955,10 +1534,11 @@ class NWPreviewNode(Operator, NWBase): # What follows is code for the shader editor - output_types = [x[1] for x in shaders_output_nodes_props] + output_types = [x.nodetype for x in + get_nodes_from_category('Output', context)] valid = False if active: - if (active.name != "Emission Viewer") and (active.type not in output_types): + if active.rna_type.identifier not in output_types: for out in active.outputs: if is_visible_socket(out): valid = True @@ -1976,7 +1556,7 @@ class NWPreviewNode(Operator, NWBase): materialout = base_node_tree.nodes.new(self.shader_output_ident) materialout.location = get_output_location(base_node_tree) materialout.select = False - # Analyze outputs, add "Emission Viewer" if needed, make links + # Analyze outputs out_i = None valid_outputs = [] for i, out in enumerate(active.outputs): @@ -1994,56 +1574,11 @@ class NWPreviewNode(Operator, NWBase): out_i = valid_outputs[0] make_links = [] # store sockets for new links - delete_nodes = [] # store unused nodes to delete in the end if active.outputs: - # If output type not 'SHADER' - "Emission Viewer" needed - if active.outputs[out_i].type != 'SHADER': - socket_type = 'NodeSocketColor' - # get Emission Viewer node - emission_exists = False - emission_placeholder = base_node_tree.nodes[0] - for node in base_node_tree.nodes: - if "Emission Viewer" in node.name: - emission_exists = True - emission_placeholder = node - if not emission_exists: - emission = base_node_tree.nodes.new(self.shader_viewer_ident) - emission.hide = True - emission.location = [materialout.location.x, (materialout.location.y + 40)] - emission.label = "Viewer" - emission.name = "Emission Viewer" - emission.use_custom_color = True - emission.color = (0.6, 0.5, 0.4) - emission.select = False - else: - emission = emission_placeholder - output_socket = emission.inputs[0] - - # If Viewer is connected to output by user, don't change those connections (patch by gandalf3) - if emission.outputs[0].links.__len__() > 0: - if not emission.outputs[0].links[0].to_node == materialout: - make_links.append((emission.outputs[0], materialout.inputs[0])) - else: - make_links.append((emission.outputs[0], materialout.inputs[0])) - - # Set brightness of viewer to compensate for Film and CM exposure - if context.scene.render.engine == 'CYCLES' and hasattr(context.scene, 'cycles'): - intensity = 1/context.scene.cycles.film_exposure # Film exposure is a multiplier - else: - intensity = 1 - - intensity /= pow(2, (context.scene.view_settings.exposure)) # CM exposure is measured in stops/EVs (2^x) - emission.inputs[1].default_value = intensity - - else: - # Output type is 'SHADER', no Viewer needed. Delete Viewer if exists. - socket_type = 'NodeSocketShader' - materialout_index = 1 if active.outputs[out_i].name == "Volume" else 0 - make_links.append((active.outputs[out_i], materialout.inputs[materialout_index])) - output_socket = materialout.inputs[materialout_index] - for node in base_node_tree.nodes: - if node.name == 'Emission Viewer': - delete_nodes.append((base_node_tree, node)) + socket_type = 'NodeSocketShader' + materialout_index = 1 if active.outputs[out_i].name == "Volume" else 0 + make_links.append((active.outputs[out_i], materialout.inputs[materialout_index])) + output_socket = materialout.inputs[materialout_index] for li_from, li_to in make_links: base_node_tree.links.new(li_from, li_to) @@ -2069,10 +1604,6 @@ class NWPreviewNode(Operator, NWBase): tree = socket.id_data tree.outputs.remove(socket) - # Delete nodes - for tree, node in delete_nodes: - tree.nodes.remove(node) - nodes.active = active active.select = True @@ -2094,14 +1625,27 @@ class NWFrameSelected(Operator, NWBase): description='The visual name of the frame node', default=' ' ) + use_custom_color_prop: BoolProperty( + name="Custom Color", + description="Use custom color for the frame node", + default=False + ) color_prop: FloatVectorProperty( name="Color", description="The color of the frame node", - default=(0.6, 0.6, 0.6), + default=(0.604, 0.604, 0.604), min=0, max=1, step=1, precision=3, subtype='COLOR_GAMMA', size=3 ) + def draw(self, context): + layout = self.layout + layout.prop(self, 'label_prop') + layout.prop(self, 'use_custom_color_prop') + col = layout.column() + col.active = self.use_custom_color_prop + col.prop(self, 'color_prop', text="") + def execute(self, context): nodes, links = get_nodes_links(context) selected = [] @@ -2112,7 +1656,7 @@ class NWFrameSelected(Operator, NWBase): bpy.ops.node.add_node(type='NodeFrame') frm = nodes.active frm.label = self.label_prop - frm.use_custom_color = True + frm.use_custom_color = self.use_custom_color_prop frm.color = self.color_prop for node in selected: @@ -2170,51 +1714,17 @@ class NWSwitchNodeType(Operator, NWBase): bl_label = "Switch Node Type" bl_options = {'REGISTER', 'UNDO'} - to_type: EnumProperty( - name="Switch to type", - items=list(shaders_input_nodes_props) + - list(shaders_output_nodes_props) + - list(shaders_shader_nodes_props) + - list(shaders_texture_nodes_props) + - list(shaders_color_nodes_props) + - list(shaders_vector_nodes_props) + - list(shaders_converter_nodes_props) + - list(shaders_layout_nodes_props) + - list(compo_input_nodes_props) + - list(compo_output_nodes_props) + - list(compo_color_nodes_props) + - list(compo_converter_nodes_props) + - list(compo_filter_nodes_props) + - list(compo_vector_nodes_props) + - list(compo_matte_nodes_props) + - list(compo_distort_nodes_props) + - list(compo_layout_nodes_props) + - list(blender_mat_input_nodes_props) + - list(blender_mat_output_nodes_props) + - list(blender_mat_color_nodes_props) + - list(blender_mat_vector_nodes_props) + - list(blender_mat_converter_nodes_props) + - list(blender_mat_layout_nodes_props) + - list(texture_input_nodes_props) + - list(texture_output_nodes_props) + - list(texture_color_nodes_props) + - list(texture_pattern_nodes_props) + - list(texture_textures_nodes_props) + - list(texture_converter_nodes_props) + - list(texture_distort_nodes_props) + - list(texture_layout_nodes_props) - ) - - geo_to_type: StringProperty( + to_type: StringProperty( name="Switch to type", default = '', ) def execute(self, context): - nodes, links = get_nodes_links(context) to_type = self.to_type - if self.geo_to_type != '': - to_type = self.geo_to_type + if len(to_type) == 0: + return {'CANCELLED'} + + nodes, links = get_nodes_links(context) # Those types of nodes will not swap. src_excludes = ('NodeFrame') # Those attributes of nodes will be copied if possible @@ -2511,8 +2021,8 @@ class NWMergeNodes(Operator, NWBase): mode = 'MIX' if (merge_type != 'MATH' and merge_type != 'GEOMETRY') and tree_type == 'GEOMETRY': merge_type = 'AUTO' - # The math nodes used for geometry nodes are of type 'ShaderNode' - if merge_type == 'MATH' and tree_type == 'GEOMETRY': + # The MixRGB node and math nodes used for geometry nodes are of type 'ShaderNode' + if (merge_type == 'MATH' or merge_type == 'MIX') and tree_type == 'GEOMETRY': node_type = 'ShaderNode' selected_mix = [] # entry = [index, loc] selected_shader = [] # entry = [index, loc] @@ -2532,7 +2042,8 @@ class NWMergeNodes(Operator, NWBase): ('VALUE', [t[0] for t in operations], selected_math), ('VECTOR', [], selected_vector), ): - output_type = node.outputs[0].type + output = get_first_enabled_output(node) + output_type = output.type valid_mode = mode in types_list # When mode is 'MIX' we have to cheat since the mix node is not used in # geometry nodes. @@ -2583,7 +2094,7 @@ class NWMergeNodes(Operator, NWBase): # Change the node type for math nodes in a geometry node tree. if tree_type == 'GEOMETRY': - if nodes_list is selected_math or nodes_list is selected_vector: + if nodes_list is selected_math or nodes_list is selected_vector or nodes_list is selected_mix: node_type = 'ShaderNode' if mode == 'MIX': mode = 'ADD' @@ -2708,8 +2219,9 @@ class NWMergeNodes(Operator, NWBase): # Special case: # Two nodes were selected and first selected has no output links, second selected has output links. # Then add links from last add to all links 'to_socket' of out links of second selected. + first_selected_output = get_first_enabled_output(first_selected) if len(nodes_list) == 2: - if not first_selected.outputs[0].links: + if not first_selected_output.links: second_selected = nodes[nodes_list[1][0]] for ss_link in second_selected.outputs[0].links: # Prevent cyclic dependencies when nodes to be merged are linked to one another. @@ -2717,16 +2229,16 @@ class NWMergeNodes(Operator, NWBase): if not self.link_creates_cycle(ss_link, invalid_nodes): links.new(last_add.outputs[0], ss_link.to_socket) # add links from last_add to all links 'to_socket' of out links of first selected. - for fs_link in first_selected.outputs[0].links: + for fs_link in first_selected_output.links: # Link only if "to_node" index not in invalid indexes list. if not self.link_creates_cycle(fs_link, invalid_nodes): links.new(last_add.outputs[0], fs_link.to_socket) # add link from "first" selected and "first" add node node_to = nodes[count_after - 1] - links.new(first_selected.outputs[0], node_to.inputs[first]) + links.new(first_selected_output, node_to.inputs[first]) if node_to.type == 'ZCOMBINE': for fs_out in first_selected.outputs: - if fs_out != first_selected.outputs[0] and fs_out.name in ('Z', 'Depth'): + if fs_out != first_selected_output and fs_out.name in ('Z', 'Depth'): links.new(fs_out, node_to.inputs[1]) break # add links between added ADD nodes and between selected and ADD nodes @@ -2736,20 +2248,20 @@ class NWMergeNodes(Operator, NWBase): node_to = nodes[index - 1] node_to_input_i = first node_to_z_i = 1 # if z combine - link z to first z input - links.new(node_from.outputs[0], node_to.inputs[node_to_input_i]) + links.new(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i]) if node_to.type == 'ZCOMBINE': for from_out in node_from.outputs: - if from_out != node_from.outputs[0] and from_out.name in ('Z', 'Depth'): + if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'): links.new(from_out, node_to.inputs[node_to_z_i]) if len(nodes_list) > 1: node_from = nodes[nodes_list[i + 1][0]] node_to = nodes[index] node_to_input_i = second node_to_z_i = 3 # if z combine - link z to second z input - links.new(node_from.outputs[0], node_to.inputs[node_to_input_i]) + links.new(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i]) if node_to.type == 'ZCOMBINE': for from_out in node_from.outputs: - if from_out != node_from.outputs[0] and from_out.name in ('Z', 'Depth'): + if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'): links.new(from_out, node_to.inputs[node_to_z_i]) index -= 1 # set "last" of added nodes as active @@ -3072,71 +2584,74 @@ class NWAddTextureSetup(Operator, NWBase): @classmethod def poll(cls, context): - valid = False if nw_check(context): space = context.space_data if space.tree_type == 'ShaderNodeTree': - valid = True - return valid + return True + return False def execute(self, context): nodes, links = get_nodes_links(context) - shader_types = [x[1] for x in shaders_shader_nodes_props if x[1] not in {'MIX_SHADER', 'ADD_SHADER'}] - texture_types = [x[1] for x in shaders_texture_nodes_props] + + texture_types = [x.nodetype for x in + get_nodes_from_category('Texture', context)] selected_nodes = [n for n in nodes if n.select] - for t_node in selected_nodes: - valid = False + + for node in selected_nodes: + if not node.inputs: + continue + input_index = 0 - if t_node.inputs: - for index, i in enumerate(t_node.inputs): - if not i.is_linked: - valid = True - input_index = index + target_input = node.inputs[0] + for input in node.inputs: + if input.enabled: + input_index += 1 + if not input.is_linked: + target_input = input break - if valid: - locx = t_node.location.x - locy = t_node.location.y - t_node.dimensions.y/2 - - xoffset = [500, 700] - is_texture = False - if t_node.type in texture_types + ['MAPPING']: - xoffset = [290, 500] - is_texture = True - - coordout = 2 - image_type = 'ShaderNodeTexImage' - - if (t_node.type in texture_types and t_node.type != 'TEX_IMAGE') or (t_node.type == 'BACKGROUND'): - coordout = 0 # image texture uses UVs, procedural textures and Background shader use Generated - if t_node.type == 'BACKGROUND': - image_type = 'ShaderNodeTexEnvironment' - - if not is_texture: - tex = nodes.new(image_type) - tex.location = [locx - 200, locy + 112] - nodes.active = tex - links.new(tex.outputs[0], t_node.inputs[input_index]) - - t_node.select = False - if self.add_mapping or is_texture: - if t_node.type != 'MAPPING': - m = nodes.new('ShaderNodeMapping') - m.location = [locx - xoffset[0], locy + 141] - m.width = 240 - else: - m = t_node - coord = nodes.new('ShaderNodeTexCoord') - coord.location = [locx - (200 if t_node.type == 'MAPPING' else xoffset[1]), locy + 124] - - if not is_texture: - links.new(m.outputs[0], tex.inputs[0]) - links.new(coord.outputs[coordout], m.inputs[0]) - else: - nodes.active = m - links.new(m.outputs[0], t_node.inputs[input_index]) - links.new(coord.outputs[coordout], m.inputs[0]) else: - self.report({'WARNING'}, "No free inputs for node: "+t_node.name) + self.report({'WARNING'}, "No free inputs for node: " + node.name) + continue + + x_offset = 0 + padding = 40.0 + locx = node.location.x + locy = node.location.y - (input_index * padding) + + is_texture_node = node.rna_type.identifier in texture_types + use_environment_texture = node.type == 'BACKGROUND' + + # Add an image texture before normal shader nodes. + if not is_texture_node: + image_texture_type = 'ShaderNodeTexEnvironment' if use_environment_texture else 'ShaderNodeTexImage' + image_texture_node = nodes.new(image_texture_type) + x_offset = x_offset + image_texture_node.width + padding + image_texture_node.location = [locx - x_offset, locy] + nodes.active = image_texture_node + links.new(image_texture_node.outputs[0], target_input) + + # The mapping setup following this will connect to the firrst input of this image texture. + target_input = image_texture_node.inputs[0] + + node.select = False + + if is_texture_node or self.add_mapping: + # Add Mapping node. + mapping_node = nodes.new('ShaderNodeMapping') + x_offset = x_offset + mapping_node.width + padding + mapping_node.location = [locx - x_offset, locy] + links.new(mapping_node.outputs[0], target_input) + + # Add Texture Coordinates node. + tex_coord_node = nodes.new('ShaderNodeTexCoord') + x_offset = x_offset + tex_coord_node.width + padding + tex_coord_node.location = [locx - x_offset, locy] + + is_procedural_texture = is_texture_node and node.type != 'TEX_IMAGE' + use_generated_coordinates = is_procedural_texture or use_environment_texture + tex_coord_output = tex_coord_node.outputs[0 if use_generated_coordinates else 2] + links.new(tex_coord_output, mapping_node.inputs[0]) + return {'FINISHED'} @@ -3759,37 +3274,32 @@ class NWLinkToOutputNode(Operator): def execute(self, context): nodes, links = get_nodes_links(context) active = nodes.active - output_node = None output_index = None tree_type = context.space_data.tree_type - if tree_type == 'ShaderNodeTree': - output_types = [x[1] for x in shaders_output_nodes_props] + ['OUTPUT'] - elif tree_type == 'CompositorNodeTree': - output_types = ['COMPOSITE'] - elif tree_type == 'TextureNodeTree': - output_types = ['OUTPUT'] - elif tree_type == 'GeometryNodeTree': - output_types = ['GROUP_OUTPUT'] + shader_outputs = {'OBJECT': 'ShaderNodeOutputMaterial', + 'WORLD': 'ShaderNodeOutputWorld', + 'LINESTYLE': 'ShaderNodeOutputLineStyle'} + output_type = { + 'ShaderNodeTree': shader_outputs[context.space_data.shader_type], + 'CompositorNodeTree': 'CompositorNodeComposite', + 'TextureNodeTree': 'TextureNodeOutput', + 'GeometryNodeTree': 'NodeGroupOutput', + }[tree_type] for node in nodes: - if node.type in output_types: + # check whether the node is an output node and, + # if supported, whether it's the active one + if node.rna_type.identifier == output_type \ + and (node.is_active_output if hasattr(node, 'is_active_output') + else True): output_node = node break - if not output_node: + else: # No output node exists bpy.ops.node.select_all(action="DESELECT") - if tree_type == 'ShaderNodeTree': - if context.space_data.shader_type == 'OBJECT': - output_node = nodes.new('ShaderNodeOutputMaterial') - elif context.space_data.shader_type == 'WORLD': - output_node = nodes.new('ShaderNodeOutputWorld') - elif tree_type == 'CompositorNodeTree': - output_node = nodes.new('CompositorNodeComposite') - elif tree_type == 'TextureNodeTree': - output_node = nodes.new('TextureNodeOutput') - elif tree_type == 'GeometryNodeTree': - output_node = nodes.new('NodeGroupOutput') + output_node = nodes.new(output_type) output_node.location.x = active.location.x + active.dimensions.x + 80 output_node.location.y = active.location.y - if (output_node and active.outputs): + + if active.outputs: for i, output in enumerate(active.outputs): if is_visible_socket(output): output_index = i @@ -3803,7 +3313,7 @@ class NWLinkToOutputNode(Operator): if tree_type == 'ShaderNodeTree': if active.outputs[output_index].name == 'Volume': out_input_index = 1 - elif active.outputs[output_index].type != 'SHADER': # connect to displacement if not a shader + elif active.outputs[output_index].name == 'Displacement': out_input_index = 2 elif tree_type == 'GeometryNodeTree': if active.outputs[output_index].type != 'GEOMETRY': @@ -4417,12 +3927,10 @@ class NWConnectionListOutputs(Menu, NWBase): nodes, links = get_nodes_links(context) n1 = nodes[context.scene.NWLazySource] - index=0 - for o in n1.outputs: + for index, output in enumerate(n1.outputs): # Only show sockets that are exposed. - if o.enabled: - layout.operator(NWCallInputsMenu.bl_idname, text=o.name, icon="RADIOBUT_OFF").from_socket=index - index+=1 + if output.enabled: + layout.operator(NWCallInputsMenu.bl_idname, text=output.name, icon="RADIOBUT_OFF").from_socket=index class NWConnectionListInputs(Menu, NWBase): @@ -4435,17 +3943,15 @@ class NWConnectionListInputs(Menu, NWBase): n2 = nodes[context.scene.NWLazyTarget] - index = 0 - for i in n2.inputs: + for index, input in enumerate(n2.inputs): # Only show sockets that are exposed. # This prevents, for example, the scale value socket # of the vector math node being added to the list when # the mode is not 'SCALE'. - if i.enabled: - op = layout.operator(NWMakeLink.bl_idname, text=i.name, icon="FORWARD") + if input.enabled: + op = layout.operator(NWMakeLink.bl_idname, text=input.name, icon="FORWARD") op.from_socket = context.scene.NWSourceSocket op.to_socket = index - index+=1 class NWMergeMathMenu(Menu, NWBase): @@ -4628,391 +4134,17 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): def draw(self, context): layout = self.layout - tree = context.space_data.node_tree - if tree.type == 'SHADER': - layout.menu(NWSwitchShadersInputSubmenu.bl_idname) - layout.menu(NWSwitchShadersOutputSubmenu.bl_idname) - layout.menu(NWSwitchShadersShaderSubmenu.bl_idname) - layout.menu(NWSwitchShadersTextureSubmenu.bl_idname) - layout.menu(NWSwitchShadersColorSubmenu.bl_idname) - layout.menu(NWSwitchShadersVectorSubmenu.bl_idname) - layout.menu(NWSwitchShadersConverterSubmenu.bl_idname) - layout.menu(NWSwitchShadersLayoutSubmenu.bl_idname) - if tree.type == 'COMPOSITING': - layout.menu(NWSwitchCompoInputSubmenu.bl_idname) - layout.menu(NWSwitchCompoOutputSubmenu.bl_idname) - layout.menu(NWSwitchCompoColorSubmenu.bl_idname) - layout.menu(NWSwitchCompoConverterSubmenu.bl_idname) - layout.menu(NWSwitchCompoFilterSubmenu.bl_idname) - layout.menu(NWSwitchCompoVectorSubmenu.bl_idname) - layout.menu(NWSwitchCompoMatteSubmenu.bl_idname) - layout.menu(NWSwitchCompoDistortSubmenu.bl_idname) - layout.menu(NWSwitchCompoLayoutSubmenu.bl_idname) - if tree.type == 'TEXTURE': - layout.menu(NWSwitchTexInputSubmenu.bl_idname) - layout.menu(NWSwitchTexOutputSubmenu.bl_idname) - layout.menu(NWSwitchTexColorSubmenu.bl_idname) - layout.menu(NWSwitchTexPatternSubmenu.bl_idname) - layout.menu(NWSwitchTexTexturesSubmenu.bl_idname) - layout.menu(NWSwitchTexConverterSubmenu.bl_idname) - layout.menu(NWSwitchTexDistortSubmenu.bl_idname) - layout.menu(NWSwitchTexLayoutSubmenu.bl_idname) - if tree.type == 'GEOMETRY': - categories = [c for c in node_categories_iter(context) + categories = [c for c in node_categories_iter(context) if c.name not in ['Group', 'Script']] - for cat in categories: - idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu" - if hasattr(bpy.types, idname): - layout.menu(idname) - else: - layout.label(text="Unable to load altered node lists.") - layout.label(text="Please re-enable Node Wrangler.") - break - - -class NWSwitchShadersInputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_input_submenu" - bl_label = "Input" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_input_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersOutputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_output_submenu" - bl_label = "Output" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_output_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersShaderSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_shader_submenu" - bl_label = "Shader" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_shader_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersTextureSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_texture_submenu" - bl_label = "Texture" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_texture_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersColorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_color_submenu" - bl_label = "Color" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_color_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersVectorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_vector_submenu" - bl_label = "Vector" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_vector_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersConverterSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_converter_submenu" - bl_label = "Converter" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_converter_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchShadersLayoutSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_shaders_layout_submenu" - bl_label = "Layout" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in shaders_layout_nodes_props: - if node_type != 'FRAME': - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoInputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_input_submenu" - bl_label = "Input" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_input_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoOutputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_output_submenu" - bl_label = "Output" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_output_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoColorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_color_submenu" - bl_label = "Color" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_color_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoConverterSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_converter_submenu" - bl_label = "Converter" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_converter_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoFilterSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_filter_submenu" - bl_label = "Filter" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_filter_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoVectorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_vector_submenu" - bl_label = "Vector" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_vector_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoMatteSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_matte_submenu" - bl_label = "Matte" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_matte_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoDistortSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_distort_submenu" - bl_label = "Distort" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_distort_nodes_props: - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchCompoLayoutSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_compo_layout_submenu" - bl_label = "Layout" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in compo_layout_nodes_props: - if node_type != 'FRAME': - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatInputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_input_submenu" - bl_label = "Input" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_input_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatOutputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_output_submenu" - bl_label = "Output" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_output_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatColorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_color_submenu" - bl_label = "Color" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_color_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatVectorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_vector_submenu" - bl_label = "Vector" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_vector_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatConverterSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_converter_submenu" - bl_label = "Converter" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_converter_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchMatLayoutSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_mat_layout_submenu" - bl_label = "Layout" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(blender_mat_layout_nodes_props, key=lambda k: k[2]): - if node_type != 'FRAME': - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexInputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_input_submenu" - bl_label = "Input" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_input_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexOutputSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_output_submenu" - bl_label = "Output" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_output_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexColorSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_color_submenu" - bl_label = "Color" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_color_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexPatternSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_pattern_submenu" - bl_label = "Pattern" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_pattern_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexTexturesSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_textures_submenu" - bl_label = "Textures" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_textures_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexConverterSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_converter_submenu" - bl_label = "Converter" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_converter_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexDistortSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_distort_submenu" - bl_label = "Distort" - - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_distort_nodes_props, key=lambda k: k[2]): - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident - - -class NWSwitchTexLayoutSubmenu(Menu, NWBase): - bl_idname = "NODE_MT_nw_switch_tex_layout_submenu" - bl_label = "Layout" + for cat in categories: + idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu" + if hasattr(bpy.types, idname): + layout.menu(idname) + else: + layout.label(text="Unable to load altered node lists.") + layout.label(text="Please re-enable Node Wrangler.") + break - def draw(self, context): - layout = self.layout - for ident, node_type, rna_name in sorted(texture_layout_nodes_props, key=lambda k: k[2]): - if node_type != 'FRAME': - props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name) - props.to_type = ident def draw_switch_category_submenu(self, context): layout = self.layout @@ -5027,7 +4159,7 @@ def draw_switch_category_submenu(self, context): node.draw(self, layout, context) continue props = layout.operator(NWSwitchNodeType.bl_idname, text=node.label) - props.geo_to_type = node.nodetype + props.to_type = node.nodetype # # APPENDAGES TO EXISTING UI @@ -5071,12 +4203,12 @@ def reset_nodes_button(self, context): node_ignore = ["FRAME","REROUTE", "GROUP"] # Check if active node is in the selection and respective type - if (len(node_selected) == 1) and node_active.select and node_active.type not in node_ignore: + if (len(node_selected) == 1) and node_active and node_active.select and node_active.type not in node_ignore: row = self.layout.row() row.operator("node.nw_reset_nodes", text="Reset Node", icon="FILE_REFRESH") self.layout.separator() - elif (len(node_selected) == 1) and node_active.select and node_active.type == "FRAME": + elif (len(node_selected) == 1) and node_active and node_active.select and node_active.type == "FRAME": row = self.layout.row() row.operator("node.nw_reset_nodes", text="Reset Nodes in Frame", icon="FILE_REFRESH") self.layout.separator() @@ -5245,8 +4377,8 @@ kmi_defs = ( (NWDeleteUnused.bl_idname, 'X', 'PRESS', False, False, True, None, "Delete unused nodes"), # Frame Selected (NWFrameSelected.bl_idname, 'P', 'PRESS', False, True, False, None, "Frame selected nodes"), - # Swap Outputs - (NWSwapLinks.bl_idname, 'S', 'PRESS', False, False, True, None, "Swap Outputs"), + # Swap Links + (NWSwapLinks.bl_idname, 'S', 'PRESS', False, False, True, None, "Swap Links"), # Preview Node (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', True, True, False, (('run_in_geometry_nodes', False),), "Preview node output"), (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', False, True, True, (('run_in_geometry_nodes', True),), "Preview node output"), @@ -5330,37 +4462,6 @@ classes = ( NWLinkUseOutputsNamesMenu, NWAttributeMenu, NWSwitchNodeTypeMenu, - NWSwitchShadersInputSubmenu, - NWSwitchShadersOutputSubmenu, - NWSwitchShadersShaderSubmenu, - NWSwitchShadersTextureSubmenu, - NWSwitchShadersColorSubmenu, - NWSwitchShadersVectorSubmenu, - NWSwitchShadersConverterSubmenu, - NWSwitchShadersLayoutSubmenu, - NWSwitchCompoInputSubmenu, - NWSwitchCompoOutputSubmenu, - NWSwitchCompoColorSubmenu, - NWSwitchCompoConverterSubmenu, - NWSwitchCompoFilterSubmenu, - NWSwitchCompoVectorSubmenu, - NWSwitchCompoMatteSubmenu, - NWSwitchCompoDistortSubmenu, - NWSwitchCompoLayoutSubmenu, - NWSwitchMatInputSubmenu, - NWSwitchMatOutputSubmenu, - NWSwitchMatColorSubmenu, - NWSwitchMatVectorSubmenu, - NWSwitchMatConverterSubmenu, - NWSwitchMatLayoutSubmenu, - NWSwitchTexInputSubmenu, - NWSwitchTexOutputSubmenu, - NWSwitchTexColorSubmenu, - NWSwitchTexPatternSubmenu, - NWSwitchTexTexturesSubmenu, - NWSwitchTexConverterSubmenu, - NWSwitchTexDistortSubmenu, - NWSwitchTexLayoutSubmenu, ) def register(): @@ -5417,7 +4518,7 @@ def register(): # switch submenus switch_category_menus.clear() for cat in node_categories_iter(None): - if cat.name not in ['Group', 'Script'] and cat.identifier.startswith('GEO'): + if cat.name not in ['Group', 'Script']: idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu" switch_category_type = type(idname, (bpy.types.Menu,), { "bl_space_type": 'NODE_EDITOR', |