# 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 bpy.app.translations import ( pgettext_iface as iface_, contexts as i18n_contexts, ) def add_node_type(layout, node_type, *, label=None, poll=None, search_weight=0.0): """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") if poll is True or poll is 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, search_weight=search_weight) props.type = node_type props.use_transform = True return props def add_node_type_with_subnames(context, layout, node_type, subnames, *, label=None, search_weight=0.0): bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type) if not label: label = bl_rna.name if bl_rna else "Unknown" props = [] props.append(add_node_type(layout, node_type, label=label, search_weight=search_weight)) if getattr(context, "is_menu_search", False): for subname in subnames: sublabel = "{} ▸ {}".format(iface_(label), iface_(subname)) props.append(add_node_type(layout, node_type, label=sublabel, search_weight=search_weight)) return props def draw_node_group_add_menu(context, layout): """Add items to the layout used for interacting with node groups.""" space_node = context.space_data node_tree = space_node.edit_tree all_node_groups = context.blend_data.node_groups if node_tree in all_node_groups.values(): layout.separator() add_node_type(layout, "NodeGroupInput") add_node_type(layout, "NodeGroupOutput") add_empty_group(layout) if node_tree: from nodeitems_builtins import node_tree_group_type prefs = bpy.context.preferences show_hidden = prefs.filepaths.show_hidden_files_datablocks groups = [ group for group in context.blend_data.node_groups if (group.bl_idname == node_tree.bl_idname and not group.contains_tree(node_tree) and (show_hidden or not group.name.startswith('.'))) ] if groups: layout.separator() for group in groups: props = add_node_type(layout, node_tree_group_type[group.bl_idname], label=group.name) ops = props.settings.add() ops.name = "node_tree" ops.value = "bpy.data.node_groups[{!r}]".format(group.name) ops = props.settings.add() ops.name = "width" ops.value = repr(group.default_group_node_width) ops = props.settings.add() ops.name = "name" ops.value = repr(group.name) def draw_assets_for_catalog(layout, catalog_path): layout.template_node_asset_menu_items(catalog_path=catalog_path) def draw_root_assets(layout): layout.menu_contents("NODE_MT_node_add_root_catalogs") def add_node_type_with_searchable_enum(context, layout, node_idname, property_name, search_weight=0.0): add_node_type(layout, node_idname, search_weight=search_weight) if getattr(context, "is_menu_search", False): node_type = getattr(bpy.types, node_idname) for item in node_type.bl_rna.properties[property_name].enum_items_static: props = add_node_type( layout, node_idname, label=node_type.bl_rna.name + " ▸ " + item.name, search_weight=search_weight) prop = props.settings.add() prop.name = property_name prop.value = repr(item.identifier) def add_color_mix_node(context, layout): label = iface_("Mix Color") props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=label) ops = props.settings.add() ops.name = "data_type" ops.value = "'RGBA'" if getattr(context, "is_menu_search", False): for item in bpy.types.ShaderNodeMix.bl_rna.properties["blend_type"].enum_items_static: props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=label + " ▸ " + item.name) prop = props.settings.add() prop.name = "data_type" prop.value = "'RGBA'" prop = props.settings.add() prop.name = "blend_type" prop.value = repr(item.identifier) def add_simulation_zone(layout, label): """Add simulation zone to a menu.""" props = layout.operator("node.add_simulation_zone", text=label, text_ctxt=i18n_contexts.default) props.use_transform = True return props def add_repeat_zone(layout, label): props = layout.operator("node.add_repeat_zone", text=label, text_ctxt=i18n_contexts.default) props.use_transform = True return props def add_foreach_geometry_element_zone(layout, label): props = layout.operator( "node.add_foreach_geometry_element_zone", text=label, text_ctxt=i18n_contexts.default, ) props.use_transform = True return props def add_closure_zone(layout, label): props = layout.operator( "node.add_closure_zone", text=label, text_ctxt=i18n_contexts.default) props.use_transform = True return props def add_empty_group(layout): props = layout.operator("node.add_empty_group", text="New Group", text_ctxt=i18n_contexts.default) props.use_transform = True 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. from bpy.utils import register_class for cls in classes: register_class(cls)