Nodes: Swap Node Operator
Implement a native method to swap between different node and zone types. This implementation repurposes the existing menu definitions as base classes, from which both an "Add" and a "Swap" version would be generated from. This allows both menus to have the same layout, but use their own operators for handling the different node/zone types. In this PR, support for all node editors has been implemented. Invoking the menu is currently bound to `Shift + S`, same as the old implementation in Node Wrangler. Since "Swap" is implemented as a regular menu, features that menus already have such as type-to-search and adding to Quick Favorites don't require any extra caveats to consider. Resolves #133452 Pull Request: https://projects.blender.org/blender/blender/pulls/143997
This commit is contained in:
@@ -408,15 +408,6 @@ class NWAttributeMenu(bpy.types.Menu):
|
|||||||
l.label(text="No attributes on objects with this material")
|
l.label(text="No attributes on objects with this material")
|
||||||
|
|
||||||
|
|
||||||
class NWSwitchNodeTypeMenu(Menu, NWBaseMenu):
|
|
||||||
bl_idname = "NODE_MT_nw_switch_node_type_menu"
|
|
||||||
bl_label = "Switch Type to..."
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
layout.label(text="This operator is removed due to the changes of node menus.", icon='ERROR')
|
|
||||||
layout.label(text="A native implementation of the function is expected in the future.")
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# APPENDAGES TO EXISTING UI
|
# APPENDAGES TO EXISTING UI
|
||||||
#
|
#
|
||||||
@@ -499,7 +490,6 @@ classes = (
|
|||||||
NWLinkUseNodeNameMenu,
|
NWLinkUseNodeNameMenu,
|
||||||
NWLinkUseOutputsNamesMenu,
|
NWLinkUseOutputsNamesMenu,
|
||||||
NWAttributeMenu,
|
NWAttributeMenu,
|
||||||
NWSwitchNodeTypeMenu,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -357,8 +357,6 @@ kmi_defs = (
|
|||||||
(('name', interface.NWLinkActiveToSelectedMenu.bl_idname),), "Link active to selected (menu)"),
|
(('name', interface.NWLinkActiveToSelectedMenu.bl_idname),), "Link active to selected (menu)"),
|
||||||
('wm.call_menu', 'C', 'PRESS', False, True, False,
|
('wm.call_menu', 'C', 'PRESS', False, True, False,
|
||||||
(('name', interface.NWCopyToSelectedMenu.bl_idname),), "Copy to selected (menu)"),
|
(('name', interface.NWCopyToSelectedMenu.bl_idname),), "Copy to selected (menu)"),
|
||||||
('wm.call_menu', 'S', 'PRESS', False, True, False,
|
|
||||||
(('name', interface.NWSwitchNodeTypeMenu.bl_idname),), "Switch node type menu"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
|
|||||||
@@ -2231,6 +2231,7 @@ def km_node_editor(params):
|
|||||||
("node.link_make", {"type": 'J', "value": 'PRESS', "shift": True},
|
("node.link_make", {"type": 'J', "value": 'PRESS', "shift": True},
|
||||||
{"properties": [("replace", True)]}),
|
{"properties": [("replace", True)]}),
|
||||||
op_menu("NODE_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
|
op_menu("NODE_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
|
||||||
|
op_menu("NODE_MT_swap", {"type": 'S', "value": 'PRESS', "shift": True}),
|
||||||
("node.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True},
|
("node.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True},
|
||||||
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
|
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
|
||||||
("node.duplicate_move_linked", {"type": 'D', "value": 'PRESS', "alt": True},
|
("node.duplicate_move_linked", {"type": 'D', "value": 'PRESS', "alt": True},
|
||||||
|
|||||||
@@ -28,6 +28,84 @@ from bpy.app.translations import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
math_nodes = {
|
||||||
|
"ShaderNodeMath",
|
||||||
|
"ShaderNodeVectorMath",
|
||||||
|
"FunctionNodeIntegerMath",
|
||||||
|
"FunctionNodeBooleanMath",
|
||||||
|
"FunctionNodeBitMath",
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_nodes = {
|
||||||
|
"GeometryNodeMenuSwitch",
|
||||||
|
"GeometryNodeIndexSwitch",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# A context manager for temporarily unparenting nodes from their frames
|
||||||
|
# This gets rid of issues with framed nodes using relative coordinates
|
||||||
|
class temporary_unframe:
|
||||||
|
def __init__(self, nodes):
|
||||||
|
self.parent_dict = {}
|
||||||
|
for node in nodes:
|
||||||
|
if node.parent is not None:
|
||||||
|
self.parent_dict[node] = node.parent
|
||||||
|
node.parent = None
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, _type, _value, _traceback):
|
||||||
|
for node, parent in self.parent_dict.items():
|
||||||
|
node.parent = parent
|
||||||
|
|
||||||
|
|
||||||
|
def cast_value(source, target):
|
||||||
|
source_type = source.type
|
||||||
|
target_type = target.type
|
||||||
|
|
||||||
|
value = source.default_value
|
||||||
|
|
||||||
|
def to_bool(value): return value > 0
|
||||||
|
def single_value_to_color(value): return Vector((value, value, value, 1.0))
|
||||||
|
def single_value_to_vector(value): return Vector([value,] * len(target.default_value))
|
||||||
|
def color_to_float(color): return (0.2126 * color[0]) + (0.7152 * color[1]) + (0.0722 * color[2])
|
||||||
|
def vector_to_float(vector): return sum(vector) / len(vector)
|
||||||
|
|
||||||
|
func_map = {
|
||||||
|
('VALUE', 'INT'): int,
|
||||||
|
('VALUE', 'BOOLEAN'): to_bool,
|
||||||
|
('VALUE', 'RGBA'): single_value_to_color,
|
||||||
|
('VALUE', 'VECTOR'): single_value_to_vector,
|
||||||
|
('INT', 'VALUE'): float,
|
||||||
|
('INT', 'BOOLEAN'): to_bool,
|
||||||
|
('INT', 'RGBA'): single_value_to_color,
|
||||||
|
('INT', 'VECTOR'): single_value_to_vector,
|
||||||
|
('BOOLEAN', 'VALUE'): float,
|
||||||
|
('BOOLEAN', 'INT'): int,
|
||||||
|
('BOOLEAN', 'RGBA'): single_value_to_color,
|
||||||
|
('BOOLEAN', 'VECTOR'): single_value_to_vector,
|
||||||
|
('RGBA', 'VALUE'): color_to_float,
|
||||||
|
('RGBA', 'INT'): lambda color: int(color_to_float(color)),
|
||||||
|
('RGBA', 'BOOLEAN'): lambda color: to_bool(color_to_float(color)),
|
||||||
|
('RGBA', 'VECTOR'): lambda color: color[:len(target.default_value)],
|
||||||
|
('VECTOR', 'VALUE'): vector_to_float,
|
||||||
|
('VECTOR', 'INT'): lambda vector: int(vector_to_float(vector)),
|
||||||
|
# Even negative vectors get implicitly converted to True, hence to_bool is not used
|
||||||
|
('VECTOR', 'BOOLEAN'): lambda vector: bool(vector_to_float(vector)),
|
||||||
|
('VECTOR', 'RGBA'): lambda vector: list(vector).extend([0.0] * (len(target.default_value) - len(vector)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if source_type == target_type:
|
||||||
|
return value
|
||||||
|
|
||||||
|
cast_func = func_map.get((source_type, target_type))
|
||||||
|
if cast_func is not None:
|
||||||
|
return cast_func(value)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class NodeSetting(PropertyGroup):
|
class NodeSetting(PropertyGroup):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
@@ -39,14 +117,7 @@ class NodeSetting(PropertyGroup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Base class for node "Add" operators.
|
class NodeOperator:
|
||||||
class NodeAddOperator:
|
|
||||||
|
|
||||||
use_transform: BoolProperty(
|
|
||||||
name="Use Transform",
|
|
||||||
description="Start transform operator after inserting the node",
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
settings: CollectionProperty(
|
settings: CollectionProperty(
|
||||||
name="Settings",
|
name="Settings",
|
||||||
description="Settings to be applied on the newly created node",
|
description="Settings to be applied on the newly created node",
|
||||||
@@ -54,6 +125,77 @@ class NodeAddOperator:
|
|||||||
options={'SKIP_SAVE'},
|
options={'SKIP_SAVE'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def description(cls, _context, properties):
|
||||||
|
from nodeitems_builtins import node_tree_group_type
|
||||||
|
|
||||||
|
nodetype = properties["type"]
|
||||||
|
if nodetype in node_tree_group_type.values():
|
||||||
|
for setting in properties.settings:
|
||||||
|
if setting.name == "node_tree":
|
||||||
|
node_group = eval(setting.value)
|
||||||
|
if node_group.description:
|
||||||
|
return node_group.description
|
||||||
|
bl_rna = bpy.types.Node.bl_rna_get_subclass(nodetype)
|
||||||
|
if bl_rna is not None:
|
||||||
|
return tip_(bl_rna.description)
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Deselect all nodes in the tree.
|
||||||
|
@staticmethod
|
||||||
|
def deselect_nodes(context):
|
||||||
|
space = context.space_data
|
||||||
|
tree = space.edit_tree
|
||||||
|
for n in tree.nodes:
|
||||||
|
n.select = False
|
||||||
|
|
||||||
|
def create_node(self, context, node_type):
|
||||||
|
space = context.space_data
|
||||||
|
tree = space.edit_tree
|
||||||
|
|
||||||
|
try:
|
||||||
|
node = tree.nodes.new(type=node_type)
|
||||||
|
except RuntimeError as ex:
|
||||||
|
self.report({'ERROR'}, str(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
node.select = True
|
||||||
|
tree.nodes.active = node
|
||||||
|
node.location = space.cursor_location
|
||||||
|
return node
|
||||||
|
|
||||||
|
def apply_node_settings(self, node):
|
||||||
|
for setting in self.settings:
|
||||||
|
# XXX catch exceptions here?
|
||||||
|
value = eval(setting.value)
|
||||||
|
node_data = node
|
||||||
|
node_attr_name = setting.name
|
||||||
|
|
||||||
|
# Support path to nested data.
|
||||||
|
if '.' in node_attr_name:
|
||||||
|
node_data_path, node_attr_name = node_attr_name.rsplit(".", 1)
|
||||||
|
node_data = node.path_resolve(node_data_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
setattr(node_data, node_attr_name, value)
|
||||||
|
except AttributeError as ex:
|
||||||
|
self.report(
|
||||||
|
{'ERROR_INVALID_INPUT'},
|
||||||
|
rpt_("Node has no attribute {:s}").format(setting.name))
|
||||||
|
print(str(ex))
|
||||||
|
# Continue despite invalid attribute
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
# Base class for node "Add" operators.
|
||||||
|
class NodeAddOperator(NodeOperator):
|
||||||
|
use_transform: BoolProperty(
|
||||||
|
name="Use Transform",
|
||||||
|
description="Start transform operator after inserting the node",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def store_mouse_cursor(context, event):
|
def store_mouse_cursor(context, event):
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
@@ -72,49 +214,6 @@ class NodeAddOperator:
|
|||||||
else:
|
else:
|
||||||
space.cursor_location = tree.view_center
|
space.cursor_location = tree.view_center
|
||||||
|
|
||||||
# Deselect all nodes in the tree.
|
|
||||||
@staticmethod
|
|
||||||
def deselect_nodes(context):
|
|
||||||
space = context.space_data
|
|
||||||
tree = space.edit_tree
|
|
||||||
for n in tree.nodes:
|
|
||||||
n.select = False
|
|
||||||
|
|
||||||
def create_node(self, context, node_type):
|
|
||||||
space = context.space_data
|
|
||||||
tree = space.edit_tree
|
|
||||||
|
|
||||||
try:
|
|
||||||
node = tree.nodes.new(type=node_type)
|
|
||||||
except RuntimeError as ex:
|
|
||||||
self.report({'ERROR'}, str(ex))
|
|
||||||
return None
|
|
||||||
|
|
||||||
for setting in self.settings:
|
|
||||||
# XXX catch exceptions here?
|
|
||||||
value = eval(setting.value)
|
|
||||||
node_data = node
|
|
||||||
node_attr_name = setting.name
|
|
||||||
|
|
||||||
# Support path to nested data.
|
|
||||||
if '.' in node_attr_name:
|
|
||||||
node_data_path, node_attr_name = node_attr_name.rsplit(".", 1)
|
|
||||||
node_data = node.path_resolve(node_data_path)
|
|
||||||
|
|
||||||
try:
|
|
||||||
setattr(node_data, node_attr_name, value)
|
|
||||||
except AttributeError as ex:
|
|
||||||
self.report(
|
|
||||||
{'ERROR_INVALID_INPUT'},
|
|
||||||
rpt_("Node has no attribute {:s}").format(setting.name))
|
|
||||||
print(str(ex))
|
|
||||||
# Continue despite invalid attribute
|
|
||||||
|
|
||||||
node.select = True
|
|
||||||
tree.nodes.active = node
|
|
||||||
node.location = space.cursor_location
|
|
||||||
return node
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
@@ -135,6 +234,176 @@ class NodeAddOperator:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class NodeSwapOperator(NodeOperator):
|
||||||
|
properties_to_pass = (
|
||||||
|
'color',
|
||||||
|
'hide',
|
||||||
|
'label',
|
||||||
|
'mute',
|
||||||
|
'parent',
|
||||||
|
'show_options',
|
||||||
|
'show_preview',
|
||||||
|
'show_texture',
|
||||||
|
'use_alpha',
|
||||||
|
'use_clamp',
|
||||||
|
'use_custom_color',
|
||||||
|
"operation",
|
||||||
|
"domain",
|
||||||
|
"data_type",
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
if (context.area is None) or (context.area.type != "NODE_EDITOR"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if len(context.selected_nodes) <= 0:
|
||||||
|
cls.poll_message_set("No nodes selected.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def transfer_node_properties(self, old_node, new_node):
|
||||||
|
for attr in self.properties_to_pass:
|
||||||
|
if (attr in self.settings):
|
||||||
|
return
|
||||||
|
|
||||||
|
if hasattr(old_node, attr) and hasattr(new_node, attr):
|
||||||
|
try:
|
||||||
|
setattr(new_node, attr, getattr(old_node, attr))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def transfer_input_values(self, old_node, new_node):
|
||||||
|
if (old_node.bl_idname in math_nodes) and (new_node.bl_idname in math_nodes):
|
||||||
|
for source_input, target_input in zip(old_node.inputs, new_node.inputs):
|
||||||
|
|
||||||
|
new_value = cast_value(source=source_input, target=target_input)
|
||||||
|
|
||||||
|
if new_value is not None:
|
||||||
|
target_input.default_value = new_value
|
||||||
|
|
||||||
|
else:
|
||||||
|
for input in old_node.inputs:
|
||||||
|
try:
|
||||||
|
new_socket = new_node.inputs[input.name]
|
||||||
|
new_value = cast_value(source=input, target=new_socket)
|
||||||
|
|
||||||
|
settings_name = f'inputs["{input.name}"].default_value'
|
||||||
|
already_defined = (settings_name in self.settings)
|
||||||
|
|
||||||
|
if (new_value is not None) and not already_defined:
|
||||||
|
new_socket.default_value = new_value
|
||||||
|
|
||||||
|
except (AttributeError, KeyError, TypeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def transfer_links(tree, old_node, new_node, is_input):
|
||||||
|
both_math_nodes = (old_node.bl_idname in math_nodes) and (new_node.bl_idname in math_nodes)
|
||||||
|
|
||||||
|
if is_input:
|
||||||
|
if both_math_nodes:
|
||||||
|
for i, input in enumerate(old_node.inputs):
|
||||||
|
for link in input.links[:]:
|
||||||
|
try:
|
||||||
|
new_socket = new_node.inputs[i]
|
||||||
|
|
||||||
|
if new_socket.hide or not new_socket.enabled:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tree.links.new(link.from_socket, new_socket)
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for input in old_node.inputs:
|
||||||
|
links = sorted(input.links, key=lambda link: link.multi_input_sort_id)
|
||||||
|
|
||||||
|
for link in links:
|
||||||
|
try:
|
||||||
|
new_socket = new_node.inputs[input.name]
|
||||||
|
|
||||||
|
if new_socket.hide or not new_socket.enabled:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tree.links.new(link.from_socket, new_socket)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
if both_math_nodes:
|
||||||
|
for i, output in enumerate(old_node.outputs):
|
||||||
|
for link in output.links[:]:
|
||||||
|
try:
|
||||||
|
new_socket = new_node.outputs[i]
|
||||||
|
|
||||||
|
if new_socket.hide or not new_socket.enabled:
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_link = tree.links.new(new_socket, link.to_socket)
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
for output in old_node.outputs:
|
||||||
|
for link in output.links[:]:
|
||||||
|
try:
|
||||||
|
new_socket = new_node.outputs[output.name]
|
||||||
|
|
||||||
|
if new_socket.hide or not new_socket.enabled:
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_link = tree.links.new(new_socket, link.to_socket)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if link.to_socket.is_multi_input:
|
||||||
|
new_link.swap_multi_input_sort_id(link)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_switch_items(node):
|
||||||
|
switch_type = node.bl_idname
|
||||||
|
|
||||||
|
if switch_type == "GeometryNodeMenuSwitch":
|
||||||
|
return node.enum_definition.enum_items
|
||||||
|
elif switch_type == "GeometryNodeIndexSwitch":
|
||||||
|
return node.index_switch_items
|
||||||
|
|
||||||
|
def transfer_switch_data(self, old_node, new_node):
|
||||||
|
old_switch_items = self.get_switch_items(old_node)
|
||||||
|
new_switch_items = self.get_switch_items(new_node)
|
||||||
|
|
||||||
|
new_switch_items.clear()
|
||||||
|
|
||||||
|
if new_node.bl_idname == "GeometryNodeMenuSwitch":
|
||||||
|
for i, old_item in enumerate(old_switch_items[:]):
|
||||||
|
# Change the menu item names to numerical indices
|
||||||
|
# This makes it so that later functions that match by socket name work on the switches
|
||||||
|
if hasattr(old_item, "name"):
|
||||||
|
old_item.name = str(i)
|
||||||
|
|
||||||
|
new_switch_items.new(str(i))
|
||||||
|
|
||||||
|
if (old_switch_value := old_node.inputs[0].default_value) != '':
|
||||||
|
new_node.inputs[0].default_value = str(old_switch_value)
|
||||||
|
|
||||||
|
elif new_node.bl_idname == "GeometryNodeIndexSwitch":
|
||||||
|
for i, old_item in enumerate(old_switch_items[:]):
|
||||||
|
# Change the menu item names to numerical indices
|
||||||
|
# This makes it so that later functions that match by socket name work on the switches
|
||||||
|
if hasattr(old_item, "name"):
|
||||||
|
old_item.name = str(i)
|
||||||
|
|
||||||
|
new_switch_items.new()
|
||||||
|
|
||||||
|
if (old_switch_value := old_node.inputs[0].default_value) != '':
|
||||||
|
new_node.inputs[0].default_value = int(old_switch_value)
|
||||||
|
|
||||||
|
|
||||||
# Simple basic operator for adding a node.
|
# Simple basic operator for adding a node.
|
||||||
class NODE_OT_add_node(NodeAddOperator, Operator):
|
class NODE_OT_add_node(NodeAddOperator, Operator):
|
||||||
"""Add a node to the active tree"""
|
"""Add a node to the active tree"""
|
||||||
@@ -158,6 +427,7 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
|
|||||||
if self.properties.is_property_set("type"):
|
if self.properties.is_property_set("type"):
|
||||||
self.deselect_nodes(context)
|
self.deselect_nodes(context)
|
||||||
if node := self.create_node(context, self.type):
|
if node := self.create_node(context, self.type):
|
||||||
|
self.apply_node_settings(node)
|
||||||
if self.visible_output:
|
if self.visible_output:
|
||||||
for socket in node.outputs:
|
for socket in node.outputs:
|
||||||
if socket.name != self.visible_output:
|
if socket.name != self.visible_output:
|
||||||
@@ -166,22 +436,91 @@ class NODE_OT_add_node(NodeAddOperator, Operator):
|
|||||||
else:
|
else:
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def description(cls, _context, properties):
|
|
||||||
from nodeitems_builtins import node_tree_group_type
|
|
||||||
|
|
||||||
nodetype = properties["type"]
|
class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||||
if nodetype in node_tree_group_type.values():
|
"""Replace the selected nodes with the specified type"""
|
||||||
for setting in properties.settings:
|
bl_idname = "node.swap_node"
|
||||||
if setting.name == "node_tree":
|
bl_label = "Swap Node"
|
||||||
node_group = eval(setting.value)
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
if node_group.description:
|
|
||||||
return node_group.description
|
type: StringProperty(
|
||||||
bl_rna = bpy.types.Node.bl_rna_get_subclass(nodetype)
|
name="Node Type",
|
||||||
if bl_rna is not None:
|
description="Node type",
|
||||||
return tip_(bl_rna.description)
|
)
|
||||||
else:
|
|
||||||
return ""
|
visible_output: StringProperty(
|
||||||
|
name="Output Name",
|
||||||
|
description="If provided, all outputs that are named differently will be hidden",
|
||||||
|
options={'SKIP_SAVE'},
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_zone_pair(tree, node):
|
||||||
|
# Get paired output node
|
||||||
|
if hasattr(node, "paired_output"):
|
||||||
|
return node, node.paired_output
|
||||||
|
|
||||||
|
# Get paired input node
|
||||||
|
for input_node in tree.nodes:
|
||||||
|
if hasattr(input_node, "paired_output"):
|
||||||
|
if input_node.paired_output == node:
|
||||||
|
return input_node, node
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
tree = context.space_data.edit_tree
|
||||||
|
|
||||||
|
for old_node in context.selected_nodes[:]:
|
||||||
|
if tree.nodes.get(old_node.name) is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if old_node.bl_idname == self.type:
|
||||||
|
self.apply_node_settings(old_node)
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_node = self.create_node(context, self.type)
|
||||||
|
self.apply_node_settings(new_node)
|
||||||
|
self.transfer_node_properties(old_node, new_node)
|
||||||
|
|
||||||
|
if self.visible_output:
|
||||||
|
for socket in new_node.outputs:
|
||||||
|
if socket.name != self.visible_output:
|
||||||
|
socket.hide = True
|
||||||
|
|
||||||
|
with temporary_unframe((old_node,)):
|
||||||
|
new_node.location = old_node.location
|
||||||
|
new_node.select = True
|
||||||
|
|
||||||
|
zone_pair = self.get_zone_pair(tree, old_node)
|
||||||
|
|
||||||
|
if zone_pair is not None:
|
||||||
|
input_node, output_node = zone_pair
|
||||||
|
|
||||||
|
if input_node.select and output_node.select:
|
||||||
|
with temporary_unframe((input_node, output_node)):
|
||||||
|
new_node.location = (input_node.location + output_node.location) / 2
|
||||||
|
new_node.select = True
|
||||||
|
|
||||||
|
self.transfer_input_values(input_node, new_node)
|
||||||
|
|
||||||
|
self.transfer_links(tree, input_node, new_node, is_input=True)
|
||||||
|
self.transfer_links(tree, output_node, new_node, is_input=False)
|
||||||
|
|
||||||
|
for node in zone_pair:
|
||||||
|
tree.nodes.remove(node)
|
||||||
|
else:
|
||||||
|
if (old_node.bl_idname in switch_nodes) and (new_node.bl_idname in switch_nodes):
|
||||||
|
self.transfer_switch_data(old_node, new_node)
|
||||||
|
|
||||||
|
self.transfer_input_values(old_node, new_node)
|
||||||
|
|
||||||
|
self.transfer_links(tree, old_node, new_node, is_input=True)
|
||||||
|
self.transfer_links(tree, old_node, new_node, is_input=False)
|
||||||
|
|
||||||
|
tree.nodes.remove(old_node)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class NODE_OT_add_empty_group(NodeAddOperator, bpy.types.Operator):
|
class NODE_OT_add_empty_group(NodeAddOperator, bpy.types.Operator):
|
||||||
@@ -190,12 +529,19 @@ class NODE_OT_add_empty_group(NodeAddOperator, bpy.types.Operator):
|
|||||||
bl_description = "Add a group node with an empty group"
|
bl_description = "Add a group node with an empty group"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
# Override inherited method from NodeOperator
|
||||||
|
# Return None so that bl_description is used
|
||||||
|
@classmethod
|
||||||
|
def description(cls, _context, properties):
|
||||||
|
...
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from nodeitems_builtins import node_tree_group_type
|
from nodeitems_builtins import node_tree_group_type
|
||||||
tree = context.space_data.edit_tree
|
tree = context.space_data.edit_tree
|
||||||
group = self.create_empty_group(tree.bl_idname)
|
group = self.create_empty_group(tree.bl_idname)
|
||||||
self.deselect_nodes(context)
|
self.deselect_nodes(context)
|
||||||
node = self.create_node(context, node_tree_group_type[tree.bl_idname])
|
node = self.create_node(context, node_tree_group_type[tree.bl_idname])
|
||||||
|
self.apply_node_settings(node)
|
||||||
node.node_tree = group
|
node.node_tree = group
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -213,7 +559,45 @@ class NODE_OT_add_empty_group(NodeAddOperator, bpy.types.Operator):
|
|||||||
return group
|
return group
|
||||||
|
|
||||||
|
|
||||||
class NodeAddZoneOperator(NodeAddOperator):
|
class NODE_OT_swap_empty_group(NodeSwapOperator, bpy.types.Operator):
|
||||||
|
bl_idname = "node.swap_empty_group"
|
||||||
|
bl_label = "Swap Empty Group"
|
||||||
|
bl_description = "Replace active node with an empty group"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
# Override inherited method from NodeOperator
|
||||||
|
# Return None so that bl_description is used
|
||||||
|
@classmethod
|
||||||
|
def description(cls, _context, properties):
|
||||||
|
...
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
from nodeitems_builtins import node_tree_group_type
|
||||||
|
tree = context.space_data.edit_tree
|
||||||
|
group = self.create_empty_group(tree.bl_idname)
|
||||||
|
|
||||||
|
bpy.ops.node.swap_node('INVOKE_DEFAULT', type=node_tree_group_type[tree.bl_idname])
|
||||||
|
|
||||||
|
for node in context.selected_nodes:
|
||||||
|
node.node_tree = group
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_empty_group(idname):
|
||||||
|
group = bpy.data.node_groups.new(name="NodeGroup", type=idname)
|
||||||
|
input_node = group.nodes.new('NodeGroupInput')
|
||||||
|
input_node.select = False
|
||||||
|
input_node.location.x = -200 - input_node.width
|
||||||
|
|
||||||
|
output_node = group.nodes.new('NodeGroupOutput')
|
||||||
|
output_node.is_active_output = True
|
||||||
|
output_node.select = False
|
||||||
|
output_node.location.x = 200
|
||||||
|
return group
|
||||||
|
|
||||||
|
|
||||||
|
class ZoneOperator:
|
||||||
offset: FloatVectorProperty(
|
offset: FloatVectorProperty(
|
||||||
name="Offset",
|
name="Offset",
|
||||||
description="Offset of nodes from the cursor when added",
|
description="Offset of nodes from the cursor when added",
|
||||||
@@ -221,6 +605,25 @@ class NodeAddZoneOperator(NodeAddOperator):
|
|||||||
default=(150, 0),
|
default=(150, 0),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
zone_tooltips = {
|
||||||
|
"GeometryNodeSimulationInput": "Simulate the execution of nodes across a time span",
|
||||||
|
"GeometryNodeRepeatInput": "Execute nodes with a dynamic number of repetitions",
|
||||||
|
"GeometryNodeForeachGeometryElementInput": "Perform operations separately for each geometry element (e.g. vertices, edges, etc.)",
|
||||||
|
"NodeClosureInput": "Wrap nodes inside a closure that can be executed at a different part of the nodetree",
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def description(cls, _context, properties):
|
||||||
|
input_node_type = getattr(properties, "input_node_type", None)
|
||||||
|
|
||||||
|
# For Add Zone operators, use class variable instead of operator property
|
||||||
|
if input_node_type is None:
|
||||||
|
input_node_type = cls.input_node_type
|
||||||
|
|
||||||
|
return cls.zone_tooltips.get(input_node_type, None)
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAddZoneOperator(ZoneOperator, NodeAddOperator):
|
||||||
add_default_geometry_link = True
|
add_default_geometry_link = True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@@ -230,6 +633,10 @@ class NodeAddZoneOperator(NodeAddOperator):
|
|||||||
self.deselect_nodes(context)
|
self.deselect_nodes(context)
|
||||||
input_node = self.create_node(context, self.input_node_type)
|
input_node = self.create_node(context, self.input_node_type)
|
||||||
output_node = self.create_node(context, self.output_node_type)
|
output_node = self.create_node(context, self.output_node_type)
|
||||||
|
|
||||||
|
self.apply_node_settings(input_node)
|
||||||
|
self.apply_node_settings(output_node)
|
||||||
|
|
||||||
if input_node is None or output_node is None:
|
if input_node is None or output_node is None:
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
@@ -249,6 +656,145 @@ class NodeAddZoneOperator(NodeAddOperator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_OT_add_zone(NodeAddZoneOperator, Operator):
|
||||||
|
bl_idname = "node.add_zone"
|
||||||
|
bl_label = "Add Zone"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
input_node_type: StringProperty(
|
||||||
|
name="Input Node",
|
||||||
|
description="Specifies the input node used the created zone",
|
||||||
|
)
|
||||||
|
|
||||||
|
output_node_type: StringProperty(
|
||||||
|
name="Output Node",
|
||||||
|
description="Specifies the output node used the created zone",
|
||||||
|
)
|
||||||
|
|
||||||
|
add_default_geometry_link: BoolProperty(
|
||||||
|
name="Add Geometry Link",
|
||||||
|
description="When enabled, create a link between geometry sockets in this zone",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||||
|
bl_idname = "node.swap_zone"
|
||||||
|
bl_label = "Swap Zone"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
input_node_type: StringProperty(
|
||||||
|
name="Input Node",
|
||||||
|
description="Specifies the input node used the created zone",
|
||||||
|
)
|
||||||
|
|
||||||
|
output_node_type: StringProperty(
|
||||||
|
name="Output Node",
|
||||||
|
description="Specifies the output node used the created zone",
|
||||||
|
)
|
||||||
|
|
||||||
|
add_default_geometry_link: BoolProperty(
|
||||||
|
name="Add Geometry Link",
|
||||||
|
description="When enabled, create a link between geometry sockets in this zone",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_zone_pair(tree, node):
|
||||||
|
# Get paired output node
|
||||||
|
if hasattr(node, "paired_output"):
|
||||||
|
return node, node.paired_output
|
||||||
|
|
||||||
|
# Get paired input node
|
||||||
|
for input_node in tree.nodes:
|
||||||
|
if hasattr(input_node, "paired_output"):
|
||||||
|
if input_node.paired_output == node:
|
||||||
|
return input_node, node
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
tree = context.space_data.edit_tree
|
||||||
|
|
||||||
|
for old_node in context.selected_nodes[:]:
|
||||||
|
if tree.nodes.get(old_node.name) is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
zone_pair = self.get_zone_pair(tree, old_node)
|
||||||
|
|
||||||
|
if (old_node.bl_idname in {self.input_node_type, self.output_node_type}):
|
||||||
|
if zone_pair is not None:
|
||||||
|
old_input_node, old_output_node = zone_pair
|
||||||
|
self.apply_node_settings(old_input_node)
|
||||||
|
self.apply_node_settings(old_output_node)
|
||||||
|
else:
|
||||||
|
self.apply_node_settings(old_node)
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
input_node = self.create_node(context, self.input_node_type)
|
||||||
|
output_node = self.create_node(context, self.output_node_type)
|
||||||
|
|
||||||
|
self.apply_node_settings(input_node)
|
||||||
|
self.apply_node_settings(output_node)
|
||||||
|
|
||||||
|
if input_node is None or output_node is None:
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
# Simulation input must be paired with the output.
|
||||||
|
input_node.pair_with_output(output_node)
|
||||||
|
|
||||||
|
if zone_pair is not None:
|
||||||
|
old_input_node, old_output_node = zone_pair
|
||||||
|
|
||||||
|
with temporary_unframe((old_input_node, old_output_node)):
|
||||||
|
input_node.location = old_input_node.location
|
||||||
|
output_node.location = old_output_node.location
|
||||||
|
|
||||||
|
self.transfer_node_properties(old_input_node, input_node)
|
||||||
|
self.transfer_node_properties(old_output_node, output_node)
|
||||||
|
|
||||||
|
self.transfer_input_values(old_input_node, input_node)
|
||||||
|
self.transfer_input_values(old_output_node, output_node)
|
||||||
|
|
||||||
|
self.transfer_links(tree, old_input_node, input_node, is_input=True)
|
||||||
|
self.transfer_links(tree, old_input_node, input_node, is_input=False)
|
||||||
|
|
||||||
|
self.transfer_links(tree, old_output_node, output_node, is_input=True)
|
||||||
|
self.transfer_links(tree, old_output_node, output_node, is_input=False)
|
||||||
|
|
||||||
|
for node in zone_pair:
|
||||||
|
tree.nodes.remove(node)
|
||||||
|
else:
|
||||||
|
with temporary_unframe((old_node,)):
|
||||||
|
input_node.location = old_node.location
|
||||||
|
output_node.location = old_node.location
|
||||||
|
|
||||||
|
input_node.location -= Vector(self.offset)
|
||||||
|
output_node.location += Vector(self.offset)
|
||||||
|
|
||||||
|
self.transfer_node_properties(old_node, input_node)
|
||||||
|
self.transfer_node_properties(old_node, output_node)
|
||||||
|
|
||||||
|
self.transfer_input_values(old_node, input_node)
|
||||||
|
|
||||||
|
self.transfer_links(tree, old_node, input_node, is_input=True)
|
||||||
|
self.transfer_links(tree, old_node, output_node, is_input=False)
|
||||||
|
|
||||||
|
tree.nodes.remove(old_node)
|
||||||
|
|
||||||
|
if tree.type == "GEOMETRY" and self.add_default_geometry_link:
|
||||||
|
# Connect geometry sockets by default if available.
|
||||||
|
# Get the sockets by their types, because the name is not guaranteed due to i18n.
|
||||||
|
from_socket = next(s for s in input_node.outputs if s.type == 'GEOMETRY')
|
||||||
|
to_socket = next(s for s in output_node.inputs if s.type == 'GEOMETRY')
|
||||||
|
|
||||||
|
if not (from_socket.is_linked or to_socket.is_linked):
|
||||||
|
tree.links.new(to_socket, from_socket)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class NODE_OT_add_simulation_zone(NodeAddZoneOperator, Operator):
|
class NODE_OT_add_simulation_zone(NodeAddZoneOperator, Operator):
|
||||||
"""Add simulation zone input and output nodes to the active tree"""
|
"""Add simulation zone input and output nodes to the active tree"""
|
||||||
bl_idname = "node.add_simulation_zone"
|
bl_idname = "node.add_simulation_zone"
|
||||||
@@ -750,8 +1296,12 @@ classes = (
|
|||||||
|
|
||||||
NODE_FH_image_node,
|
NODE_FH_image_node,
|
||||||
|
|
||||||
NODE_OT_add_empty_group,
|
|
||||||
NODE_OT_add_node,
|
NODE_OT_add_node,
|
||||||
|
NODE_OT_swap_node,
|
||||||
|
NODE_OT_add_empty_group,
|
||||||
|
NODE_OT_swap_empty_group,
|
||||||
|
NODE_OT_add_zone,
|
||||||
|
NODE_OT_swap_zone,
|
||||||
NODE_OT_add_simulation_zone,
|
NODE_OT_add_simulation_zone,
|
||||||
NODE_OT_add_repeat_zone,
|
NODE_OT_add_repeat_zone,
|
||||||
NODE_OT_add_foreach_geometry_element_zone,
|
NODE_OT_add_foreach_geometry_element_zone,
|
||||||
|
|||||||
@@ -25,112 +25,20 @@ from bpy.app.translations import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: This is kept for compatibility's sake, as some scripts import node_add_menu.add_node_type
|
||||||
def add_node_type(layout, node_type, *, label=None, poll=None, search_weight=0.0, translate=True):
|
def add_node_type(layout, node_type, *, label=None, poll=None, search_weight=0.0, translate=True):
|
||||||
"""Add a node type to a menu."""
|
"""Add a node type to a menu."""
|
||||||
bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type)
|
return AddNodeMenu.node_operator(
|
||||||
if not label:
|
layout,
|
||||||
label = bl_rna.name if bl_rna else iface_("Unknown")
|
node_type,
|
||||||
|
label=label,
|
||||||
if poll is True or poll is None:
|
poll=poll,
|
||||||
translation_context = bl_rna.translation_context if bl_rna else i18n_contexts.default
|
search_weight=search_weight,
|
||||||
props = layout.operator(
|
translate=translate)
|
||||||
"node.add_node",
|
|
||||||
text=label,
|
|
||||||
text_ctxt=translation_context,
|
|
||||||
translate=translate,
|
|
||||||
search_weight=search_weight)
|
|
||||||
props.type = node_type
|
|
||||||
props.use_transform = True
|
|
||||||
return props
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def add_node_type_with_outputs(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:
|
|
||||||
item_props = add_node_type(
|
|
||||||
layout,
|
|
||||||
node_type,
|
|
||||||
label="{:s} \u25B8 {:s}".format(iface_(label), iface_(subname)),
|
|
||||||
search_weight=search_weight,
|
|
||||||
translate=False,
|
|
||||||
)
|
|
||||||
item_props.visible_output = subname
|
|
||||||
props.append(item_props)
|
|
||||||
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):
|
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)
|
return AddNodeMenu.node_operator_with_searchable_enum(context, layout, node_idname, property_name, search_weight)
|
||||||
if getattr(context, "is_menu_search", False):
|
|
||||||
node_type = getattr(bpy.types, node_idname)
|
|
||||||
translation_context = node_type.bl_rna.properties[property_name].translation_context
|
|
||||||
for item in node_type.bl_rna.properties[property_name].enum_items_static:
|
|
||||||
props = add_node_type(
|
|
||||||
layout,
|
|
||||||
node_idname,
|
|
||||||
label="{:s} \u25B8 {:s}".format(iface_(node_type.bl_rna.name), iface_(item.name, translation_context)),
|
|
||||||
translate=False,
|
|
||||||
search_weight=search_weight,
|
|
||||||
)
|
|
||||||
prop = props.settings.add()
|
|
||||||
prop.name = property_name
|
|
||||||
prop.value = repr(item.identifier)
|
|
||||||
|
|
||||||
|
|
||||||
def add_node_type_with_searchable_enum_socket(
|
def add_node_type_with_searchable_enum_socket(
|
||||||
@@ -139,45 +47,32 @@ def add_node_type_with_searchable_enum_socket(
|
|||||||
node_idname,
|
node_idname,
|
||||||
socket_identifier,
|
socket_identifier,
|
||||||
enum_names,
|
enum_names,
|
||||||
search_weight=0.0,
|
search_weight=0.0):
|
||||||
):
|
return AddNodeMenu.node_operator_with_searchable_enum_socket(
|
||||||
add_node_type(layout, node_idname, search_weight=search_weight)
|
context, layout, node_idname, socket_identifier, enum_names, search_weight)
|
||||||
if getattr(context, "is_menu_search", False):
|
|
||||||
node_type = getattr(bpy.types, node_idname)
|
|
||||||
for enum_name in enum_names:
|
def add_node_type_with_outputs(context, layout, node_type, subnames, *, label=None, search_weight=0.0):
|
||||||
props = add_node_type(
|
return AddNodeMenu.node_operator_with_outputs(
|
||||||
layout,
|
context,
|
||||||
node_idname,
|
layout,
|
||||||
label="{:s} \u25B8 {:s}".format(iface_(node_type.bl_rna.name), iface_(enum_name)),
|
node_type,
|
||||||
translate=False,
|
subnames,
|
||||||
search_weight=search_weight)
|
label=label,
|
||||||
prop = props.settings.add()
|
search_weight=search_weight)
|
||||||
prop.name = f'inputs["{socket_identifier}"].default_value'
|
|
||||||
prop.value = repr(enum_name)
|
|
||||||
|
|
||||||
|
|
||||||
def add_color_mix_node(context, layout):
|
def add_color_mix_node(context, layout):
|
||||||
label = iface_("Mix Color")
|
return AddNodeMenu.color_mix_node(context, layout)
|
||||||
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=label, translate=False)
|
|
||||||
ops = props.settings.add()
|
|
||||||
ops.name = "data_type"
|
|
||||||
ops.value = "'RGBA'"
|
|
||||||
|
|
||||||
if getattr(context, "is_menu_search", False):
|
|
||||||
translation_context = bpy.types.ShaderNodeMix.bl_rna.properties["blend_type"].translation_context
|
def add_empty_group(layout):
|
||||||
for item in bpy.types.ShaderNodeMix.bl_rna.properties["blend_type"].enum_items_static:
|
return AddNodeMenu.new_empty_group(layout)
|
||||||
props = node_add_menu.add_node_type(
|
|
||||||
layout,
|
|
||||||
"ShaderNodeMix",
|
def draw_node_group_add_menu(context, layout):
|
||||||
label="{:s} \u25B8 {:s}".format(label, iface_(item.name, translation_context)),
|
"""Add items to the layout used for interacting with node groups."""
|
||||||
translate=False,
|
return AddNodeMenu.draw_group_menu(context, layout)
|
||||||
)
|
|
||||||
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):
|
def add_simulation_zone(layout, label):
|
||||||
@@ -210,26 +105,385 @@ def add_closure_zone(layout, label):
|
|||||||
return props
|
return props
|
||||||
|
|
||||||
|
|
||||||
def add_empty_group(layout):
|
class NodeMenu(Menu):
|
||||||
props = layout.operator("node.add_empty_group", text="New Group", text_ctxt=i18n_contexts.default)
|
"""A baseclass defining the shared methods for AddNodeMenu and SwapNodeMenu"""
|
||||||
props.use_transform = True
|
draw_assets: bool
|
||||||
return props
|
use_transform: bool
|
||||||
|
|
||||||
|
main_operator_id: str
|
||||||
|
zone_operator_id: str
|
||||||
|
new_empty_group_operator_id: str
|
||||||
|
|
||||||
|
root_asset_menu: str
|
||||||
|
pathing_dict: dict[str, str]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def node_operator(cls, layout, node_type, *, label=None, poll=None, search_weight=0.0, translate=True):
|
||||||
|
"""The main operator defined for the node menu.
|
||||||
|
\n(e.g. 'Add Node' for AddNodeMenu, or 'Swap Node' for SwapNodeMenu)"""
|
||||||
|
|
||||||
|
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(
|
||||||
|
cls.main_operator_id,
|
||||||
|
text=label,
|
||||||
|
text_ctxt=translation_context,
|
||||||
|
translate=translate,
|
||||||
|
search_weight=search_weight)
|
||||||
|
props.type = node_type
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def node_operator_with_searchable_enum(cls, context, layout, node_idname, property_name, search_weight=0.0):
|
||||||
|
"""Similar to `node_operator`, but with extra entries based on a enum property while in search"""
|
||||||
|
operators = []
|
||||||
|
operators.append(cls.node_operator(layout, node_idname, search_weight=search_weight))
|
||||||
|
|
||||||
|
if getattr(context, "is_menu_search", False):
|
||||||
|
node_type = getattr(bpy.types, node_idname)
|
||||||
|
translation_context = node_type.bl_rna.properties[property_name].translation_context
|
||||||
|
for item in node_type.bl_rna.properties[property_name].enum_items_static:
|
||||||
|
props = cls.node_operator(
|
||||||
|
layout,
|
||||||
|
node_idname,
|
||||||
|
label="{:s} \u25B8 {:s}".format(
|
||||||
|
iface_(
|
||||||
|
node_type.bl_rna.name),
|
||||||
|
iface_(
|
||||||
|
item.name,
|
||||||
|
translation_context)),
|
||||||
|
translate=False,
|
||||||
|
search_weight=search_weight)
|
||||||
|
prop = props.settings.add()
|
||||||
|
prop.name = property_name
|
||||||
|
prop.value = repr(item.identifier)
|
||||||
|
operators.append(props)
|
||||||
|
|
||||||
|
for props in operators:
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return operators
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def node_operator_with_searchable_enum_socket(
|
||||||
|
cls,
|
||||||
|
context,
|
||||||
|
layout,
|
||||||
|
node_idname,
|
||||||
|
socket_identifier,
|
||||||
|
enum_names,
|
||||||
|
search_weight=0.0):
|
||||||
|
"""Similar to `node_operator`, but with extra entries based on a enum socket while in search"""
|
||||||
|
operators = []
|
||||||
|
operators.append(cls.node_operator(layout, node_idname, search_weight=search_weight))
|
||||||
|
if getattr(context, "is_menu_search", False):
|
||||||
|
node_type = getattr(bpy.types, node_idname)
|
||||||
|
for enum_name in enum_names:
|
||||||
|
props = cls.node_operator(
|
||||||
|
layout,
|
||||||
|
node_idname,
|
||||||
|
label="{:s} \u25B8 {:s}".format(iface_(node_type.bl_rna.name), iface_(enum_name)),
|
||||||
|
translate=False,
|
||||||
|
search_weight=search_weight)
|
||||||
|
prop = props.settings.add()
|
||||||
|
prop.name = f'inputs["{socket_identifier}"].default_value'
|
||||||
|
prop.value = repr(enum_name)
|
||||||
|
operators.append(props)
|
||||||
|
|
||||||
|
for props in operators:
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return operators
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def node_operator_with_outputs(cls, context, layout, node_type, subnames, *, label=None, search_weight=0.0):
|
||||||
|
"""Similar to `node_operator`, but with extra entries based on a enum socket while in search"""
|
||||||
|
bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type)
|
||||||
|
if not label:
|
||||||
|
label = bl_rna.name if bl_rna else "Unknown"
|
||||||
|
|
||||||
|
operators = []
|
||||||
|
operators.append(cls.node_operator(layout, node_type, label=label, search_weight=search_weight))
|
||||||
|
|
||||||
|
if getattr(context, "is_menu_search", False):
|
||||||
|
for subname in subnames:
|
||||||
|
item_props = cls.node_operator(layout, node_type, label="{:s} \u25B8 {:s}".format(
|
||||||
|
iface_(label), iface_(subname)), search_weight=search_weight, translate=False)
|
||||||
|
item_props.visible_output = subname
|
||||||
|
operators.append(item_props)
|
||||||
|
|
||||||
|
for props in operators:
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return operators
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def color_mix_node(cls, context, layout):
|
||||||
|
"""The 'Mix Color' node, with its different blend modes available while in search"""
|
||||||
|
label = iface_("Mix Color")
|
||||||
|
|
||||||
|
operators = []
|
||||||
|
props = cls.node_operator(layout, "ShaderNodeMix", label=label, translate=False)
|
||||||
|
ops = props.settings.add()
|
||||||
|
ops.name = "data_type"
|
||||||
|
ops.value = "'RGBA'"
|
||||||
|
operators.append(props)
|
||||||
|
|
||||||
|
if getattr(context, "is_menu_search", False):
|
||||||
|
translation_context = bpy.types.ShaderNodeMix.bl_rna.properties["blend_type"].translation_context
|
||||||
|
for item in bpy.types.ShaderNodeMix.bl_rna.properties["blend_type"].enum_items_static:
|
||||||
|
props = cls.node_operator(
|
||||||
|
layout,
|
||||||
|
"ShaderNodeMix",
|
||||||
|
label="{:s} \u25B8 {:s}".format(
|
||||||
|
label,
|
||||||
|
iface_(
|
||||||
|
item.name,
|
||||||
|
translation_context)),
|
||||||
|
translate=False)
|
||||||
|
prop = props.settings.add()
|
||||||
|
prop.name = "data_type"
|
||||||
|
prop.value = "'RGBA'"
|
||||||
|
prop = props.settings.add()
|
||||||
|
prop.name = "blend_type"
|
||||||
|
prop.value = repr(item.identifier)
|
||||||
|
operators.append(props)
|
||||||
|
|
||||||
|
for props in operators:
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return operators
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_empty_group(cls, layout):
|
||||||
|
"""Group Node with a newly created empty group as its assigned nodetree"""
|
||||||
|
props = layout.operator(cls.new_empty_group_operator_id, text="New Group", text_ctxt=i18n_contexts.default)
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_group_menu(cls, context, layout):
|
||||||
|
"""Show operators 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()
|
||||||
|
cls.node_operator(layout, "NodeGroupInput")
|
||||||
|
cls.node_operator(layout, "NodeGroupOutput")
|
||||||
|
|
||||||
|
operators = []
|
||||||
|
operators.append(cls.new_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 = cls.node_operator(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)
|
||||||
|
operators.append(props)
|
||||||
|
|
||||||
|
for props in operators:
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return operators
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_menu(cls, layout, path):
|
||||||
|
"""Takes the given menu path and draws the corresponding menu.
|
||||||
|
\n Menu paths are either explicitly defined, or based on bl_label if not."""
|
||||||
|
if cls.pathing_dict is None:
|
||||||
|
raise ValueError("`pathing_dict` was not set for {}".format(cls))
|
||||||
|
|
||||||
|
layout.menu(cls.pathing_dict[path])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def simulation_zone(cls, layout, label):
|
||||||
|
props = layout.operator(cls.zone_operator_id, text=label)
|
||||||
|
props.input_node_type = "GeometryNodeSimulationInput"
|
||||||
|
props.output_node_type = "GeometryNodeSimulationOutput"
|
||||||
|
props.add_default_geometry_link = True
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def repeat_zone(cls, layout, label):
|
||||||
|
props = layout.operator(cls.zone_operator_id, text=label)
|
||||||
|
props.input_node_type = "GeometryNodeRepeatInput"
|
||||||
|
props.output_node_type = "GeometryNodeRepeatOutput"
|
||||||
|
props.add_default_geometry_link = True
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def for_each_element_zone(cls, layout, label):
|
||||||
|
props = layout.operator(cls.zone_operator_id, text=label)
|
||||||
|
props.input_node_type = "GeometryNodeForeachGeometryElementInput"
|
||||||
|
props.output_node_type = "GeometryNodeForeachGeometryElementOutput"
|
||||||
|
props.add_default_geometry_link = False
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def closure_zone(cls, layout, label):
|
||||||
|
props = layout.operator(cls.zone_operator_id, text=label)
|
||||||
|
props.input_node_type = "NodeClosureInput"
|
||||||
|
props.output_node_type = "NodeClosureOutput"
|
||||||
|
props.add_default_geometry_link = False
|
||||||
|
|
||||||
|
if hasattr(props, "use_transform"):
|
||||||
|
props.use_transform = cls.use_transform
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_root_assets(cls, layout):
|
||||||
|
if cls.draw_assets:
|
||||||
|
layout.menu_contents(cls.root_asset_menu)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_layout(Menu):
|
class AddNodeMenu(NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_layout"
|
draw_assets = True
|
||||||
|
use_transform = True
|
||||||
|
|
||||||
|
main_operator_id = "node.add_node"
|
||||||
|
zone_operator_id = "node.add_zone"
|
||||||
|
new_empty_group_operator_id = "node.add_empty_group"
|
||||||
|
|
||||||
|
root_asset_menu = "NODE_MT_node_add_root_catalogs"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_assets_for_catalog(cls, layout, catalog_path):
|
||||||
|
if cls.draw_assets:
|
||||||
|
layout.template_node_asset_menu_items(catalog_path=catalog_path, operator='ADD')
|
||||||
|
|
||||||
|
|
||||||
|
class SwapNodeMenu(NodeMenu):
|
||||||
|
draw_assets = True
|
||||||
|
# NOTE: Swap operators don't have a `use_transform` property, so defining it here has no effect
|
||||||
|
|
||||||
|
main_operator_id = "node.swap_node"
|
||||||
|
zone_operator_id = "node.swap_zone"
|
||||||
|
new_empty_group_operator_id = "node.swap_empty_group"
|
||||||
|
|
||||||
|
root_asset_menu = "NODE_MT_node_swap_root_catalogs"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_assets_for_catalog(cls, layout, catalog_path):
|
||||||
|
if cls.draw_assets:
|
||||||
|
layout.template_node_asset_menu_items(catalog_path=catalog_path, operator='SWAP')
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_MT_group_base(NodeMenu):
|
||||||
|
bl_label = "Group"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
self.draw_group_menu(context, layout)
|
||||||
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_MT_layout_base(NodeMenu):
|
||||||
bl_label = "Layout"
|
bl_label = "Layout"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "NodeFrame", search_weight=-1)
|
self.node_operator(layout, "NodeFrame", search_weight=-1)
|
||||||
node_add_menu.add_node_type(layout, "NodeReroute")
|
self.node_operator(layout, "NodeReroute")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
|
add_base_pathing_dict = {
|
||||||
|
"Group": "NODE_MT_group_add",
|
||||||
|
"Layout": "NODE_MT_category_layout",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
swap_base_pathing_dict = {
|
||||||
|
"Group": "NODE_MT_group_swap",
|
||||||
|
"Layout": "NODE_MT_layout_swap",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def generate_menu(bl_idname: str, template: Menu, layout_base: Menu, pathing_dict: dict = None):
|
||||||
|
return type(bl_idname, (template, layout_base), {"bl_idname": bl_idname, "pathing_dict": pathing_dict})
|
||||||
|
|
||||||
|
|
||||||
|
def generate_menus(menus: dict, template: Menu, base_dict: dict):
|
||||||
|
import copy
|
||||||
|
pathing_dict = copy.copy(base_dict)
|
||||||
|
menus = tuple(
|
||||||
|
generate_menu(bl_idname, template, layout_base, pathing_dict)
|
||||||
|
for bl_idname, layout_base in menus.items()
|
||||||
|
)
|
||||||
|
generate_pathing_dict(pathing_dict, menus)
|
||||||
|
return menus
|
||||||
|
|
||||||
|
|
||||||
|
def generate_pathing_dict(pathing_dict, menus):
|
||||||
|
for menu in menus:
|
||||||
|
if hasattr(menu, "menu_path"):
|
||||||
|
menu_path = menu.menu_path
|
||||||
|
else:
|
||||||
|
menu_path = menu.bl_label
|
||||||
|
|
||||||
|
pathing_dict[menu_path] = menu.bl_idname
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
NODE_MT_category_layout,
|
generate_menu("NODE_MT_group_add", template=AddNodeMenu, layout_base=NODE_MT_group_base),
|
||||||
|
generate_menu("NODE_MT_group_swap", template=SwapNodeMenu, layout_base=NODE_MT_group_base),
|
||||||
|
generate_menu("NODE_MT_category_layout", template=AddNodeMenu, layout_base=NODE_MT_layout_base),
|
||||||
|
generate_menu("NODE_MT_layout_swap", template=SwapNodeMenu, layout_base=NODE_MT_layout_base),
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__": # only for live edit.
|
if __name__ == "__main__": # only for live edit.
|
||||||
|
|||||||
@@ -9,373 +9,395 @@ from bpy.app.translations import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_input(Menu):
|
class NODE_MT_compositor_node_input_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_input"
|
|
||||||
bl_label = "Input"
|
bl_label = "Input"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
del context
|
del context
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_compositor_input_constant")
|
self.draw_menu(layout, path="Input/Constant")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "NodeGroupInput")
|
self.node_operator(layout, "NodeGroupInput")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBokehImage")
|
self.node_operator(layout, "CompositorNodeBokehImage")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeImage")
|
self.node_operator(layout, "CompositorNodeImage")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeImageInfo")
|
self.node_operator(layout, "CompositorNodeImageInfo")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeImageCoordinates")
|
self.node_operator(layout, "CompositorNodeImageCoordinates")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeMask")
|
self.node_operator(layout, "CompositorNodeMask")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeMovieClip")
|
self.node_operator(layout, "CompositorNodeMovieClip")
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_input_scene")
|
self.draw_menu(layout, path="Input/Scene")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_input_constant(Menu):
|
class NODE_MT_compositor_node_input_constant_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_input_constant"
|
|
||||||
bl_label = "Constant"
|
bl_label = "Constant"
|
||||||
|
menu_path = "Input/Constant"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeRGB")
|
self.node_operator(layout, "CompositorNodeRGB")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
self.node_operator(layout, "ShaderNodeValue")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeNormal")
|
self.node_operator(layout, "CompositorNodeNormal")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Constant")
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_input_scene(Menu):
|
class NODE_MT_compositor_node_input_scene_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_input_scene"
|
|
||||||
bl_label = "Scene"
|
bl_label = "Scene"
|
||||||
|
menu_path = "Input/Scene"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeRLayers")
|
self.node_operator(layout, "CompositorNodeRLayers")
|
||||||
node_add_menu.add_node_type_with_outputs(context, layout, "CompositorNodeSceneTime", ["Frame", "Seconds"])
|
self.node_operator_with_outputs(context, layout, "CompositorNodeSceneTime", ["Frame", "Seconds"])
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeTime")
|
self.node_operator(layout, "CompositorNodeTime")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Scene")
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_output(Menu):
|
class NODE_MT_compositor_node_output_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_output"
|
|
||||||
bl_label = "Output"
|
bl_label = "Output"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
del context
|
del context
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "NodeGroupOutput")
|
self.node_operator(layout, "NodeGroupOutput")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeViewer")
|
self.node_operator(layout, "CompositorNodeViewer")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeOutputFile")
|
self.node_operator(layout, "CompositorNodeOutputFile")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_color(Menu):
|
class NODE_MT_compositor_node_color_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_color"
|
|
||||||
bl_label = "Color"
|
bl_label = "Color"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_compositor_color_adjust")
|
self.draw_menu(layout, path="Color/Adjust")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_color_mix")
|
self.draw_menu(layout, path="Color/Mix")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodePremulKey")
|
self.node_operator(layout, "CompositorNodePremulKey")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBlackbody")
|
self.node_operator(layout, "ShaderNodeBlackbody")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
self.node_operator(layout, "ShaderNodeValToRGB")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeConvertColorSpace")
|
self.node_operator(layout, "CompositorNodeConvertColorSpace")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeConvertToDisplay")
|
self.node_operator(layout, "CompositorNodeConvertToDisplay")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeSetAlpha")
|
self.node_operator(layout, "CompositorNodeSetAlpha")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeInvert")
|
self.node_operator(layout, "CompositorNodeInvert")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeRGBToBW")
|
self.node_operator(layout, "CompositorNodeRGBToBW")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_color_adjust(Menu):
|
class NODE_MT_compositor_node_color_adjust_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_color_adjust"
|
|
||||||
bl_label = "Adjust"
|
bl_label = "Adjust"
|
||||||
|
menu_path = "Color/Adjust"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBrightContrast")
|
self.node_operator(layout, "CompositorNodeBrightContrast")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeColorBalance")
|
self.node_operator(layout, "CompositorNodeColorBalance")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeColorCorrection")
|
self.node_operator(layout, "CompositorNodeColorCorrection")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeExposure")
|
self.node_operator(layout, "CompositorNodeExposure")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeGamma")
|
self.node_operator(layout, "ShaderNodeGamma")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeHueCorrect")
|
self.node_operator(layout, "CompositorNodeHueCorrect")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeHueSat")
|
self.node_operator(layout, "CompositorNodeHueSat")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCurveRGB")
|
self.node_operator(layout, "CompositorNodeCurveRGB")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeTonemap")
|
self.node_operator(layout, "CompositorNodeTonemap")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Color/Adjust")
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_color_mix(Menu):
|
class NODE_MT_compositor_node_color_mix_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_color_mix"
|
|
||||||
bl_label = "Mix"
|
bl_label = "Mix"
|
||||||
|
menu_path = "Color/Mix"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeAlphaOver")
|
self.node_operator(layout, "CompositorNodeAlphaOver")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCombineColor")
|
self.node_operator(layout, "CompositorNodeCombineColor")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeSeparateColor")
|
self.node_operator(layout, "CompositorNodeSeparateColor")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeZcombine")
|
self.node_operator(layout, "CompositorNodeZcombine")
|
||||||
node_add_menu.add_color_mix_node(context, layout)
|
self.color_mix_node(context, layout)
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Color/Mix")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_filter(Menu):
|
class NODE_MT_compositor_node_filter_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_filter"
|
|
||||||
bl_label = "Filter"
|
bl_label = "Filter"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_compositor_filter_blur")
|
self.draw_menu(layout, path="Filter/Blur")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeAntiAliasing")
|
self.node_operator(layout, "CompositorNodeAntiAliasing")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeConvolve")
|
self.node_operator(layout, "CompositorNodeConvolve")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDenoise")
|
self.node_operator(layout, "CompositorNodeDenoise")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDespeckle")
|
self.node_operator(layout, "CompositorNodeDespeckle")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDilateErode")
|
self.node_operator(layout, "CompositorNodeDilateErode")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeInpaint")
|
self.node_operator(layout, "CompositorNodeInpaint")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type_with_searchable_enum_socket(
|
self.node_operator_with_searchable_enum_socket(
|
||||||
context, layout, "CompositorNodeFilter", "Type", [
|
context, layout, "CompositorNodeFilter", "Type", [
|
||||||
"Soften", "Box Sharpen", "Diamond Sharpen", "Laplace", "Sobel", "Prewitt", "Kirsch", "Shadow"])
|
"Soften", "Box Sharpen", "Diamond Sharpen", "Laplace", "Sobel", "Prewitt", "Kirsch", "Shadow"])
|
||||||
node_add_menu.add_node_type_with_searchable_enum_socket(
|
self.node_operator_with_searchable_enum_socket(
|
||||||
context, layout, "CompositorNodeGlare", "Type", [
|
context, layout, "CompositorNodeGlare", "Type", [
|
||||||
"Bloom", "Ghosts", "Streaks", "Fog Glow", "Simple Star", "Sun Beams", "Kernel"])
|
"Bloom", "Ghosts", "Streaks", "Fog Glow", "Simple Star", "Sun Beams", "Kernel"])
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeKuwahara")
|
self.node_operator(layout, "CompositorNodeKuwahara")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodePixelate")
|
self.node_operator(layout, "CompositorNodePixelate")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodePosterize")
|
self.node_operator(layout, "CompositorNodePosterize")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_filter_blur(Menu):
|
class NODE_MT_compositor_node_filter_blur_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_filter_blur"
|
|
||||||
bl_label = "Blur"
|
bl_label = "Blur"
|
||||||
|
menu_path = "Filter/Blur"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBilateralblur")
|
self.node_operator(layout, "CompositorNodeBilateralblur")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBlur")
|
self.node_operator(layout, "CompositorNodeBlur")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBokehBlur")
|
self.node_operator(layout, "CompositorNodeBokehBlur")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDefocus")
|
self.node_operator(layout, "CompositorNodeDefocus")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDBlur")
|
self.node_operator(layout, "CompositorNodeDBlur")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeVecBlur")
|
self.node_operator(layout, "CompositorNodeVecBlur")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Filter/Blur")
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_group(Menu):
|
class NODE_MT_compositor_node_keying_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_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_category_compositor_keying(Menu):
|
|
||||||
bl_idname = "NODE_MT_category_compositor_keying"
|
|
||||||
bl_label = "Keying"
|
bl_label = "Keying"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeChannelMatte")
|
self.node_operator(layout, "CompositorNodeChannelMatte")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeChromaMatte")
|
self.node_operator(layout, "CompositorNodeChromaMatte")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeColorMatte")
|
self.node_operator(layout, "CompositorNodeColorMatte")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeColorSpill")
|
self.node_operator(layout, "CompositorNodeColorSpill")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDiffMatte")
|
self.node_operator(layout, "CompositorNodeDiffMatte")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDistanceMatte")
|
self.node_operator(layout, "CompositorNodeDistanceMatte")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeKeying")
|
self.node_operator(layout, "CompositorNodeKeying")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeKeyingScreen")
|
self.node_operator(layout, "CompositorNodeKeyingScreen")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeLumaMatte")
|
self.node_operator(layout, "CompositorNodeLumaMatte")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_mask(Menu):
|
class NODE_MT_compositor_node_mask_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_mask"
|
|
||||||
bl_label = "Mask"
|
bl_label = "Mask"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatteV2")
|
self.node_operator(layout, "CompositorNodeCryptomatteV2")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatte")
|
self.node_operator(layout, "CompositorNodeCryptomatte")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeBoxMask")
|
self.node_operator(layout, "CompositorNodeBoxMask")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeEllipseMask")
|
self.node_operator(layout, "CompositorNodeEllipseMask")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDoubleEdgeMask")
|
self.node_operator(layout, "CompositorNodeDoubleEdgeMask")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeIDMask")
|
self.node_operator(layout, "CompositorNodeIDMask")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_tracking(Menu):
|
class NODE_MT_compositor_node_tracking_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_tracking"
|
|
||||||
bl_label = "Tracking"
|
bl_label = "Tracking"
|
||||||
bl_translation_context = i18n_contexts.id_movieclip
|
bl_translation_context = i18n_contexts.id_movieclip
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodePlaneTrackDeform")
|
self.node_operator(layout, "CompositorNodePlaneTrackDeform")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeStabilize")
|
self.node_operator(layout, "CompositorNodeStabilize")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeTrackPos")
|
self.node_operator(layout, "CompositorNodeTrackPos")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_transform(Menu):
|
class NODE_MT_compositor_node_transform_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_transform"
|
|
||||||
bl_label = "Transform"
|
bl_label = "Transform"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeRotate")
|
self.node_operator(layout, "CompositorNodeRotate")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeScale")
|
self.node_operator(layout, "CompositorNodeScale")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeTransform")
|
self.node_operator(layout, "CompositorNodeTransform")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeTranslate")
|
self.node_operator(layout, "CompositorNodeTranslate")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCornerPin")
|
self.node_operator(layout, "CompositorNodeCornerPin")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeCrop")
|
self.node_operator(layout, "CompositorNodeCrop")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeDisplace")
|
self.node_operator(layout, "CompositorNodeDisplace")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeFlip")
|
self.node_operator(layout, "CompositorNodeFlip")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeMapUV")
|
self.node_operator(layout, "CompositorNodeMapUV")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeLensdist")
|
self.node_operator(layout, "CompositorNodeLensdist")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeMovieDistortion")
|
self.node_operator(layout, "CompositorNodeMovieDistortion")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_texture(Menu):
|
class NODE_MT_compositor_node_texture_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_texture"
|
|
||||||
bl_label = "Texture"
|
bl_label = "Texture"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
self.node_operator(layout, "ShaderNodeTexBrick")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
self.node_operator(layout, "ShaderNodeTexChecker")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGabor")
|
self.node_operator(layout, "ShaderNodeTexGabor")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
self.node_operator(layout, "ShaderNodeTexGradient")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
self.node_operator(layout, "ShaderNodeTexMagic")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
self.node_operator(layout, "ShaderNodeTexNoise")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
self.node_operator(layout, "ShaderNodeTexVoronoi")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
self.node_operator(layout, "ShaderNodeTexWave")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
self.node_operator(layout, "ShaderNodeTexWhiteNoise")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_utilities(Menu):
|
class NODE_MT_compositor_node_utilities_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_utilities"
|
|
||||||
bl_label = "Utilities"
|
bl_label = "Utilities"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
self.node_operator(layout, "ShaderNodeMapRange")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
self.node_operator(layout, "ShaderNodeMix")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
self.node_operator(layout, "ShaderNodeClamp")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
self.node_operator(layout, "ShaderNodeFloatCurve")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeLevels")
|
self.node_operator(layout, "CompositorNodeLevels")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeNormalize")
|
self.node_operator(layout, "CompositorNodeNormalize")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeSplit")
|
self.node_operator(layout, "CompositorNodeSplit")
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeSwitch")
|
self.node_operator(layout, "CompositorNodeSwitch")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMenuSwitch")
|
self.node_operator(layout, "GeometryNodeMenuSwitch")
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout, "CompositorNodeSwitchView",
|
layout, "CompositorNodeSwitchView",
|
||||||
label="Switch Stereo View")
|
label="Switch Stereo View")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "CompositorNodeRelativeToPixel")
|
self.node_operator(layout, "CompositorNodeRelativeToPixel")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_compositor_vector(Menu):
|
class NODE_MT_compositor_node_vector_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_compositor_vector"
|
|
||||||
bl_label = "Vector"
|
bl_label = "Vector"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
self.node_operator(layout, "ShaderNodeCombineXYZ")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
self.node_operator(layout, "ShaderNodeSeparateXYZ")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label="Mix Vector")
|
props = self.node_operator(layout, "ShaderNodeMix", label="Mix Vector")
|
||||||
ops = props.settings.add()
|
ops = props.settings.add()
|
||||||
ops.name = "data_type"
|
ops.name = "data_type"
|
||||||
ops.value = "'VECTOR'"
|
ops.value = "'VECTOR'"
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRadialTiling")
|
self.node_operator(layout, "ShaderNodeRadialTiling")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
self.node_operator(layout, "ShaderNodeVectorCurve")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
self.node_operator(layout, "ShaderNodeVectorRotate")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_compositor_node_add_all(Menu):
|
class NODE_MT_compositor_node_all_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_compositor_node_add_all"
|
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
menu_path = "Root"
|
||||||
|
bl_translation_context = i18n_contexts.operator_default
|
||||||
|
|
||||||
|
# NOTE: Menus are looked up via their label, this is so that both the Add
|
||||||
|
# & Swap menus can share the same layout while each using their
|
||||||
|
# corresponding menus
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_compositor_input")
|
self.draw_menu(layout, "Input")
|
||||||
layout.menu("NODE_MT_category_compositor_output")
|
self.draw_menu(layout, "Output")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_color")
|
self.draw_menu(layout, "Color")
|
||||||
layout.menu("NODE_MT_category_compositor_filter")
|
self.draw_menu(layout, "Filter")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_keying")
|
self.draw_menu(layout, "Keying")
|
||||||
layout.menu("NODE_MT_category_compositor_mask")
|
self.draw_menu(layout, "Mask")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_tracking")
|
self.draw_menu(layout, "Tracking")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_texture")
|
self.draw_menu(layout, "Texture")
|
||||||
layout.menu("NODE_MT_category_compositor_transform")
|
self.draw_menu(layout, "Transform")
|
||||||
layout.menu("NODE_MT_category_compositor_utilities")
|
self.draw_menu(layout, "Utilities")
|
||||||
layout.menu("NODE_MT_category_compositor_vector")
|
self.draw_menu(layout, "Vector")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_compositor_group")
|
self.draw_menu(layout, "Group")
|
||||||
layout.menu("NODE_MT_category_layout")
|
self.draw_menu(layout, "Layout")
|
||||||
|
|
||||||
node_add_menu.draw_root_assets(layout)
|
self.draw_root_assets(layout)
|
||||||
|
|
||||||
|
|
||||||
|
add_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_category_compositor_input": NODE_MT_compositor_node_input_base,
|
||||||
|
"NODE_MT_category_compositor_input_constant": NODE_MT_compositor_node_input_constant_base,
|
||||||
|
"NODE_MT_category_compositor_input_scene": NODE_MT_compositor_node_input_scene_base,
|
||||||
|
"NODE_MT_category_compositor_output": NODE_MT_compositor_node_output_base,
|
||||||
|
"NODE_MT_category_compositor_color": NODE_MT_compositor_node_color_base,
|
||||||
|
"NODE_MT_category_compositor_color_adjust": NODE_MT_compositor_node_color_adjust_base,
|
||||||
|
"NODE_MT_category_compositor_color_mix": NODE_MT_compositor_node_color_mix_base,
|
||||||
|
"NODE_MT_category_compositor_filter": NODE_MT_compositor_node_filter_base,
|
||||||
|
"NODE_MT_category_compositor_filter_blur": NODE_MT_compositor_node_filter_blur_base,
|
||||||
|
"NODE_MT_category_compositor_texture": NODE_MT_compositor_node_texture_base,
|
||||||
|
"NODE_MT_category_compositor_keying": NODE_MT_compositor_node_keying_base,
|
||||||
|
"NODE_MT_category_compositor_mask": NODE_MT_compositor_node_mask_base,
|
||||||
|
"NODE_MT_category_compositor_tracking": NODE_MT_compositor_node_tracking_base,
|
||||||
|
"NODE_MT_category_compositor_transform": NODE_MT_compositor_node_transform_base,
|
||||||
|
"NODE_MT_category_compositor_utilities": NODE_MT_compositor_node_utilities_base,
|
||||||
|
"NODE_MT_category_compositor_vector": NODE_MT_compositor_node_vector_base,
|
||||||
|
"NODE_MT_compositor_node_add_all": NODE_MT_compositor_node_all_base,
|
||||||
|
}
|
||||||
|
add_menus = node_add_menu.generate_menus(
|
||||||
|
add_menus,
|
||||||
|
template=node_add_menu.AddNodeMenu,
|
||||||
|
base_dict=node_add_menu.add_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
swap_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_compositor_node_input_swap": NODE_MT_compositor_node_input_base,
|
||||||
|
"NODE_MT_compositor_node_input_constant_swap": NODE_MT_compositor_node_input_constant_base,
|
||||||
|
"NODE_MT_compositor_node_input_scene_swap": NODE_MT_compositor_node_input_scene_base,
|
||||||
|
"NODE_MT_compositor_node_output_swap": NODE_MT_compositor_node_output_base,
|
||||||
|
"NODE_MT_compositor_node_color_swap": NODE_MT_compositor_node_color_base,
|
||||||
|
"NODE_MT_compositor_node_color_adjust_swap": NODE_MT_compositor_node_color_adjust_base,
|
||||||
|
"NODE_MT_compositor_node_color_mix_swap": NODE_MT_compositor_node_color_mix_base,
|
||||||
|
"NODE_MT_compositor_node_filter_swap": NODE_MT_compositor_node_filter_base,
|
||||||
|
"NODE_MT_compositor_node_filter_blur_swap": NODE_MT_compositor_node_filter_blur_base,
|
||||||
|
"NODE_MT_compositor_node_texture_swap": NODE_MT_compositor_node_texture_base,
|
||||||
|
"NODE_MT_compositor_node_keying_swap": NODE_MT_compositor_node_keying_base,
|
||||||
|
"NODE_MT_compositor_node_mask_swap": NODE_MT_compositor_node_mask_base,
|
||||||
|
"NODE_MT_compositor_node_tracking_swap": NODE_MT_compositor_node_tracking_base,
|
||||||
|
"NODE_MT_compositor_node_transform_swap": NODE_MT_compositor_node_transform_base,
|
||||||
|
"NODE_MT_compositor_node_utilities_swap": NODE_MT_compositor_node_utilities_base,
|
||||||
|
"NODE_MT_compositor_node_vector_swap": NODE_MT_compositor_node_vector_base,
|
||||||
|
"NODE_MT_compositor_node_swap_all": NODE_MT_compositor_node_all_base,
|
||||||
|
}
|
||||||
|
swap_menus = node_add_menu.generate_menus(
|
||||||
|
swap_menus,
|
||||||
|
template=node_add_menu.SwapNodeMenu,
|
||||||
|
base_dict=node_add_menu.swap_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
NODE_MT_compositor_node_add_all,
|
*add_menus,
|
||||||
NODE_MT_category_compositor_input,
|
*swap_menus,
|
||||||
NODE_MT_category_compositor_input_constant,
|
|
||||||
NODE_MT_category_compositor_input_scene,
|
|
||||||
NODE_MT_category_compositor_output,
|
|
||||||
NODE_MT_category_compositor_color,
|
|
||||||
NODE_MT_category_compositor_color_adjust,
|
|
||||||
NODE_MT_category_compositor_color_mix,
|
|
||||||
NODE_MT_category_compositor_filter,
|
|
||||||
NODE_MT_category_compositor_filter_blur,
|
|
||||||
NODE_MT_category_compositor_texture,
|
|
||||||
NODE_MT_category_compositor_keying,
|
|
||||||
NODE_MT_category_compositor_mask,
|
|
||||||
NODE_MT_category_compositor_tracking,
|
|
||||||
NODE_MT_category_compositor_transform,
|
|
||||||
NODE_MT_category_compositor_utilities,
|
|
||||||
NODE_MT_category_compositor_vector,
|
|
||||||
NODE_MT_category_compositor_group,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__": # only for live edit.
|
if __name__ == "__main__": # only for live edit.
|
||||||
|
|||||||
@@ -10,336 +10,352 @@ from bpy.app.translations import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
|
class NODE_MT_gn_attribute_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_ATTRIBUTE"
|
|
||||||
bl_label = "Attribute"
|
bl_label = "Attribute"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeAttributeStatistic")
|
self.node_operator(layout, "GeometryNodeAttributeStatistic")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize")
|
self.node_operator(layout, "GeometryNodeAttributeDomainSize")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeBlurAttribute")
|
self.node_operator(layout, "GeometryNodeBlurAttribute")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCaptureAttribute")
|
self.node_operator(layout, "GeometryNodeCaptureAttribute")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute")
|
self.node_operator(layout, "GeometryNodeRemoveAttribute")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedAttribute", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeStoreNamedAttribute", search_weight=1.0)
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_COLOR(Menu):
|
class NODE_MT_gn_utilities_color_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_COLOR"
|
|
||||||
bl_label = "Color"
|
bl_label = "Color"
|
||||||
|
menu_path = "Utilities/Color"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBlackbody")
|
self.node_operator(layout, "ShaderNodeBlackbody")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeGamma")
|
self.node_operator(layout, "ShaderNodeGamma")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
self.node_operator(layout, "ShaderNodeValToRGB")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
|
self.node_operator(layout, "ShaderNodeRGBCurve")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineColor")
|
self.node_operator(layout, "FunctionNodeCombineColor")
|
||||||
node_add_menu.add_color_mix_node(context, layout)
|
self.color_mix_node(context, layout)
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateColor")
|
self.node_operator(layout, "FunctionNodeSeparateColor")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Color")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_CURVE(Menu):
|
class NODE_MT_gn_curve_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE"
|
|
||||||
bl_label = "Curve"
|
bl_label = "Curve"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE_READ")
|
self.draw_menu(layout, path="Curve/Read")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE_SAMPLE")
|
self.draw_menu(layout, path="Curve/Sample")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE_WRITE")
|
self.draw_menu(layout, path="Curve/Write")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE_OPERATIONS")
|
self.draw_menu(layout, path="Curve/Operations")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE")
|
self.draw_menu(layout, path="Curve/Primitives")
|
||||||
layout.menu("NODE_MT_geometry_node_curve_topology")
|
self.draw_menu(layout, path="Curve/Topology")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_CURVE_READ(Menu):
|
class NODE_MT_gn_curve_read_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_READ"
|
|
||||||
bl_label = "Read"
|
bl_label = "Read"
|
||||||
|
menu_path = "Curve/Read"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveHandlePositions")
|
self.node_operator(layout, "GeometryNodeInputCurveHandlePositions")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveLength")
|
self.node_operator(layout, "GeometryNodeCurveLength")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputTangent")
|
self.node_operator(layout, "GeometryNodeInputTangent")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveTilt")
|
self.node_operator(layout, "GeometryNodeInputCurveTilt")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveEndpointSelection")
|
self.node_operator(layout, "GeometryNodeCurveEndpointSelection")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveHandleTypeSelection")
|
self.node_operator(layout, "GeometryNodeCurveHandleTypeSelection")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineCyclic")
|
self.node_operator(layout, "GeometryNodeInputSplineCyclic")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSplineLength")
|
self.node_operator(layout, "GeometryNodeSplineLength")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSplineParameter")
|
self.node_operator(layout, "GeometryNodeSplineParameter")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineResolution")
|
self.node_operator(layout, "GeometryNodeInputSplineResolution")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Read")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_CURVE_SAMPLE(Menu):
|
class NODE_MT_gn_curve_sample_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_SAMPLE"
|
|
||||||
bl_label = "Sample"
|
bl_label = "Sample"
|
||||||
|
menu_path = "Curve/Sample"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleCurve")
|
self.node_operator(layout, "GeometryNodeSampleCurve")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Sample")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_CURVE_WRITE(Menu):
|
class NODE_MT_gn_curve_write_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_WRITE"
|
|
||||||
bl_label = "Write"
|
bl_label = "Write"
|
||||||
|
menu_path = "Curve/Write"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveNormal")
|
self.node_operator(layout, "GeometryNodeSetCurveNormal")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveRadius")
|
self.node_operator(layout, "GeometryNodeSetCurveRadius")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveTilt")
|
self.node_operator(layout, "GeometryNodeSetCurveTilt")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveHandlePositions")
|
self.node_operator(layout, "GeometryNodeSetCurveHandlePositions")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSetHandles")
|
self.node_operator(layout, "GeometryNodeCurveSetHandles")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineCyclic")
|
self.node_operator(layout, "GeometryNodeSetSplineCyclic")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineResolution")
|
self.node_operator(layout, "GeometryNodeSetSplineResolution")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSplineType")
|
self.node_operator(layout, "GeometryNodeCurveSplineType")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Write")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_CURVE_OPERATIONS(Menu):
|
class NODE_MT_gn_curve_operations_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE_OPERATIONS"
|
|
||||||
bl_label = "Operations"
|
bl_label = "Operations"
|
||||||
|
menu_path = "Curve/Operations"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveToMesh")
|
self.node_operator(layout, "GeometryNodeCurveToMesh")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveToPoints")
|
self.node_operator(layout, "GeometryNodeCurveToPoints")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvesToGreasePencil")
|
self.node_operator(layout, "GeometryNodeCurvesToGreasePencil")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDeformCurvesOnSurface")
|
self.node_operator(layout, "GeometryNodeDeformCurvesOnSurface")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFillCurve")
|
self.node_operator(layout, "GeometryNodeFillCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFilletCurve")
|
self.node_operator(layout, "GeometryNodeFilletCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInterpolateCurves")
|
self.node_operator(layout, "GeometryNodeInterpolateCurves")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeResampleCurve")
|
self.node_operator(layout, "GeometryNodeResampleCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeReverseCurve")
|
self.node_operator(layout, "GeometryNodeReverseCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideCurve")
|
self.node_operator(layout, "GeometryNodeSubdivideCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeTrimCurve")
|
self.node_operator(layout, "GeometryNodeTrimCurve")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Operations")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu):
|
class NODE_MT_gn_curve_primitives_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE"
|
|
||||||
bl_label = "Primitives"
|
bl_label = "Primitives"
|
||||||
|
menu_path = "Curve/Primitives"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveArc")
|
self.node_operator(layout, "GeometryNodeCurveArc")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveBezierSegment")
|
self.node_operator(layout, "GeometryNodeCurvePrimitiveBezierSegment")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveCircle")
|
self.node_operator(layout, "GeometryNodeCurvePrimitiveCircle")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveLine")
|
self.node_operator(layout, "GeometryNodeCurvePrimitiveLine")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSpiral")
|
self.node_operator(layout, "GeometryNodeCurveSpiral")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveQuadraticBezier")
|
self.node_operator(layout, "GeometryNodeCurveQuadraticBezier")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveQuadrilateral")
|
self.node_operator(layout, "GeometryNodeCurvePrimitiveQuadrilateral")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveStar")
|
self.node_operator(layout, "GeometryNodeCurveStar")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Primitives")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_curve_topology(Menu):
|
class NODE_MT_gn_curve_topology_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_curve_topology"
|
|
||||||
bl_label = "Topology"
|
bl_label = "Topology"
|
||||||
|
menu_path = "Curve/Topology"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveOfPoint")
|
self.node_operator(layout, "GeometryNodeCurveOfPoint")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeOffsetPointInCurve")
|
self.node_operator(layout, "GeometryNodeOffsetPointInCurve")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePointsOfCurve")
|
self.node_operator(layout, "GeometryNodePointsOfCurve")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Curve/Topology")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_grease_pencil_read(Menu):
|
class NODE_MT_gn_grease_pencil_read_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_grease_pencil_read"
|
|
||||||
bl_label = "Read"
|
bl_label = "Read"
|
||||||
|
menu_path = "Grease Pencil/Read"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputNamedLayerSelection")
|
self.node_operator(layout, "GeometryNodeInputNamedLayerSelection")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Read")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_grease_pencil_write(Menu):
|
class NODE_MT_gn_grease_pencil_write_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_grease_pencil_write"
|
|
||||||
bl_label = "Write"
|
bl_label = "Write"
|
||||||
|
menu_path = "Grease Pencil/Write"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetGreasePencilColor")
|
self.node_operator(layout, "GeometryNodeSetGreasePencilColor")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetGreasePencilDepth")
|
self.node_operator(layout, "GeometryNodeSetGreasePencilDepth")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetGreasePencilSoftness")
|
self.node_operator(layout, "GeometryNodeSetGreasePencilSoftness")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Write")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_grease_pencil_operations(Menu):
|
class NODE_MT_gn_grease_pencil_operations_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_grease_pencil_operations"
|
|
||||||
bl_label = "Operations"
|
bl_label = "Operations"
|
||||||
|
menu_path = "Grease Pencil/Operations"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGreasePencilToCurves")
|
self.node_operator(layout, "GeometryNodeGreasePencilToCurves")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMergeLayers")
|
self.node_operator(layout, "GeometryNodeMergeLayers")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Grease Pencil/Operations")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_grease_pencil(Menu):
|
class NODE_MT_gn_grease_pencil_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_grease_pencil"
|
|
||||||
bl_label = "Grease Pencil"
|
bl_label = "Grease Pencil"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_grease_pencil_read")
|
self.draw_menu(layout, path="Grease Pencil/Read")
|
||||||
layout.menu("NODE_MT_geometry_node_grease_pencil_write")
|
self.draw_menu(layout, path="Grease Pencil/Write")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_grease_pencil_operations")
|
self.draw_menu(layout, path="Grease Pencil/Operations")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
|
class NODE_MT_gn_geometry_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY"
|
|
||||||
bl_label = "Geometry"
|
bl_label = "Geometry"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_READ")
|
self.draw_menu(layout, path="Geometry/Read")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE")
|
self.draw_menu(layout, path="Geometry/Sample")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_WRITE")
|
self.draw_menu(layout, path="Geometry/Write")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS")
|
self.draw_menu(layout, path="Geometry/Operations")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGeometryToInstance")
|
self.node_operator(layout, "GeometryNodeGeometryToInstance")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeJoinGeometry", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeJoinGeometry", search_weight=1.0)
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_GEOMETRY_READ(Menu):
|
class NODE_MT_gn_geometry_read_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_READ"
|
|
||||||
bl_label = "Read"
|
bl_label = "Read"
|
||||||
|
menu_path = "Geometry/Read"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputID")
|
self.node_operator(layout, "GeometryNodeInputID")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputIndex")
|
self.node_operator(layout, "GeometryNodeInputIndex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputNamedAttribute", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeInputNamedAttribute", search_weight=1.0)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputNormal")
|
self.node_operator(layout, "GeometryNodeInputNormal")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputPosition", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeInputPosition", search_weight=1.0)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputRadius")
|
self.node_operator(layout, "GeometryNodeInputRadius")
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeToolSelection")
|
self.node_operator(layout, "GeometryNodeToolSelection")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeToolActiveElement")
|
self.node_operator(layout, "GeometryNodeToolActiveElement")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Read")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_GEOMETRY_WRITE(Menu):
|
class NODE_MT_gn_geometry_write_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_WRITE"
|
|
||||||
bl_label = "Write"
|
bl_label = "Write"
|
||||||
|
menu_path = "Geometry/Write"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetGeometryName")
|
self.node_operator(layout, "GeometryNodeSetGeometryName")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetID")
|
self.node_operator(layout, "GeometryNodeSetID")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetPosition", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeSetPosition", search_weight=1.0)
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeToolSetSelection")
|
self.node_operator(layout, "GeometryNodeToolSetSelection")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Write")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS(Menu):
|
class NODE_MT_gn_geometry_operations_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS"
|
|
||||||
bl_label = "Operations"
|
bl_label = "Operations"
|
||||||
|
menu_path = "Geometry/Operations"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeBake")
|
self.node_operator(layout, "GeometryNodeBake")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeBoundBox")
|
self.node_operator(layout, "GeometryNodeBoundBox")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeConvexHull")
|
self.node_operator(layout, "GeometryNodeConvexHull")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDeleteGeometry")
|
self.node_operator(layout, "GeometryNodeDeleteGeometry")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDuplicateElements")
|
self.node_operator(layout, "GeometryNodeDuplicateElements")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMergeByDistance")
|
self.node_operator(layout, "GeometryNodeMergeByDistance")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSortElements")
|
self.node_operator(layout, "GeometryNodeSortElements")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeTransform", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeTransform", search_weight=1.0)
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
|
self.node_operator(layout, "GeometryNodeSeparateComponents")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSeparateGeometry")
|
self.node_operator(layout, "GeometryNodeSeparateGeometry")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSplitToInstances")
|
self.node_operator(layout, "GeometryNodeSplitToInstances")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Operations")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE(Menu):
|
class NODE_MT_gn_geometry_sample_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE"
|
|
||||||
bl_label = "Sample"
|
bl_label = "Sample"
|
||||||
|
menu_path = "Geometry/Sample"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeProximity")
|
self.node_operator(layout, "GeometryNodeProximity")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeIndexOfNearest")
|
self.node_operator(layout, "GeometryNodeIndexOfNearest")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeRaycast")
|
self.node_operator(layout, "GeometryNodeRaycast")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleIndex")
|
self.node_operator(layout, "GeometryNodeSampleIndex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearest")
|
self.node_operator(layout, "GeometryNodeSampleNearest")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Sample")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INPUT(Menu):
|
class NODE_MT_gn_input_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT"
|
|
||||||
bl_label = "Input"
|
bl_label = "Input"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT_CONSTANT")
|
self.draw_menu(layout, path="Input/Constant")
|
||||||
if context.space_data.node_tree_sub_type != 'TOOL':
|
if context.space_data.node_tree_sub_type != 'TOOL':
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT_GIZMO")
|
self.draw_menu(layout, path="Input/Gizmo")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT_GROUP")
|
self.draw_menu(layout, path="Input/Group")
|
||||||
layout.menu("NODE_MT_category_import")
|
self.draw_menu(layout, path="Input/Import")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT_SCENE")
|
self.draw_menu(layout, path="Input/Scene")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INPUT_CONSTANT(Menu):
|
class NODE_MT_gn_input_constant_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_CONSTANT"
|
|
||||||
bl_label = "Constant"
|
bl_label = "Constant"
|
||||||
bl_translation_context = i18n_contexts.id_nodetree
|
bl_translation_context = i18n_contexts.id_nodetree
|
||||||
|
menu_path = "Input/Constant"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputBool")
|
self.node_operator(layout, "FunctionNodeInputBool")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputCollection")
|
self.node_operator(layout, "GeometryNodeInputCollection")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputColor")
|
self.node_operator(layout, "FunctionNodeInputColor")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputImage")
|
self.node_operator(layout, "GeometryNodeInputImage")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputInt")
|
self.node_operator(layout, "FunctionNodeInputInt")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterial")
|
self.node_operator(layout, "GeometryNodeInputMaterial")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputObject")
|
self.node_operator(layout, "GeometryNodeInputObject")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputRotation")
|
self.node_operator(layout, "FunctionNodeInputRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputString")
|
self.node_operator(layout, "FunctionNodeInputString")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
self.node_operator(layout, "ShaderNodeValue")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputVector")
|
self.node_operator(layout, "FunctionNodeInputVector")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Constant")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INPUT_GROUP(Menu):
|
class NODE_MT_gn_input_group_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_GROUP"
|
|
||||||
bl_label = "Group"
|
bl_label = "Group"
|
||||||
|
menu_path = "Input/Group"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "NodeGroupInput")
|
self.node_operator(layout, "NodeGroupInput")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Group")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INPUT_SCENE(Menu):
|
class NODE_MT_gn_input_scene_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_SCENE"
|
|
||||||
bl_label = "Scene"
|
bl_label = "Scene"
|
||||||
|
menu_path = "Input/Scene"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeTool3DCursor")
|
self.node_operator(layout, "GeometryNodeTool3DCursor")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputActiveCamera")
|
self.node_operator(layout, "GeometryNodeInputActiveCamera")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context,
|
context,
|
||||||
layout,
|
layout,
|
||||||
"GeometryNodeCameraInfo",
|
"GeometryNodeCameraInfo",
|
||||||
@@ -355,655 +371,752 @@ class NODE_MT_geometry_node_GEO_INPUT_SCENE(Menu):
|
|||||||
"Orthographic Scale",
|
"Orthographic Scale",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCollectionInfo")
|
self.node_operator(layout, "GeometryNodeCollectionInfo")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImageInfo")
|
self.node_operator(layout, "GeometryNodeImageInfo")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeIsViewport")
|
self.node_operator(layout, "GeometryNodeIsViewport")
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "GeometryNodeToolMousePosition",
|
context, layout, "GeometryNodeToolMousePosition",
|
||||||
["Mouse X", "Mouse Y", "Region Width", "Region Height"],
|
["Mouse X", "Mouse Y", "Region Width", "Region Height"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeObjectInfo")
|
self.node_operator(layout, "GeometryNodeObjectInfo")
|
||||||
node_add_menu.add_node_type_with_outputs(context, layout, "GeometryNodeInputSceneTime", ["Frame", "Seconds"])
|
self.node_operator_with_outputs(context, layout, "GeometryNodeInputSceneTime", ["Frame", "Seconds"])
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSelfObject")
|
self.node_operator(layout, "GeometryNodeSelfObject")
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "GeometryNodeViewportTransform",
|
context, layout, "GeometryNodeViewportTransform",
|
||||||
["Projection", "View", "Is Orthographic"],
|
["Projection", "View", "Is Orthographic"],
|
||||||
)
|
)
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Scene")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INPUT_GIZMO(Menu):
|
class NODE_MT_gn_input_gizmo_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_GIZMO"
|
|
||||||
bl_label = "Gizmo"
|
bl_label = "Gizmo"
|
||||||
|
menu_path = "Input/Gizmo"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGizmoDial")
|
self.node_operator(layout, "GeometryNodeGizmoDial")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGizmoLinear")
|
self.node_operator(layout, "GeometryNodeGizmoLinear")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGizmoTransform")
|
self.node_operator(layout, "GeometryNodeGizmoTransform")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Gizmo")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_INSTANCE(Menu):
|
class NODE_MT_gn_instance_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_INSTANCE"
|
|
||||||
bl_label = "Instances"
|
bl_label = "Instances"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInstanceOnPoints", search_weight=2.0)
|
self.node_operator(layout, "GeometryNodeInstanceOnPoints", search_weight=2.0)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInstancesToPoints")
|
self.node_operator(layout, "GeometryNodeInstancesToPoints")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeRealizeInstances", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeRealizeInstances", search_weight=1.0)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeRotateInstances")
|
self.node_operator(layout, "GeometryNodeRotateInstances")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleInstances")
|
self.node_operator(layout, "GeometryNodeScaleInstances")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeTranslateInstances")
|
self.node_operator(layout, "GeometryNodeTranslateInstances")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetInstanceTransform")
|
self.node_operator(layout, "GeometryNodeSetInstanceTransform")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceBounds")
|
self.node_operator(layout, "GeometryNodeInputInstanceBounds")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInstanceTransform")
|
self.node_operator(layout, "GeometryNodeInstanceTransform")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceRotation")
|
self.node_operator(layout, "GeometryNodeInputInstanceRotation")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceScale")
|
self.node_operator(layout, "GeometryNodeInputInstanceScale")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
|
class NODE_MT_gn_material_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MATERIAL"
|
|
||||||
bl_label = "Material"
|
bl_label = "Material"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeReplaceMaterial")
|
self.node_operator(layout, "GeometryNodeReplaceMaterial")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterialIndex")
|
self.node_operator(layout, "GeometryNodeInputMaterialIndex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMaterialSelection")
|
self.node_operator(layout, "GeometryNodeMaterialSelection")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterial", search_weight=1.0)
|
self.node_operator(layout, "GeometryNodeSetMaterial", search_weight=1.0)
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterialIndex")
|
self.node_operator(layout, "GeometryNodeSetMaterialIndex")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MESH(Menu):
|
class NODE_MT_gn_mesh_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH"
|
|
||||||
bl_label = "Mesh"
|
bl_label = "Mesh"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MESH_READ")
|
self.draw_menu(layout, path="Mesh/Read")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MESH_SAMPLE")
|
self.draw_menu(layout, path="Mesh/Sample")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MESH_WRITE")
|
self.draw_menu(layout, path="Mesh/Write")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MESH_OPERATIONS")
|
self.draw_menu(layout, path="Mesh/Operations")
|
||||||
layout.menu("NODE_MT_category_PRIMITIVES_MESH")
|
self.draw_menu(layout, path="Mesh/Primitives")
|
||||||
layout.menu("NODE_MT_geometry_node_mesh_topology")
|
self.draw_menu(layout, path="Mesh/Topology")
|
||||||
layout.menu("NODE_MT_category_GEO_UV")
|
self.draw_menu(layout, path="Mesh/UV")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MESH_READ(Menu):
|
class NODE_MT_gn_mesh_read_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH_READ"
|
|
||||||
bl_label = "Read"
|
bl_label = "Read"
|
||||||
|
menu_path = "Mesh/Read"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeAngle")
|
self.node_operator(layout, "GeometryNodeInputMeshEdgeAngle")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeNeighbors")
|
self.node_operator(layout, "GeometryNodeInputMeshEdgeNeighbors")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeVertices")
|
self.node_operator(layout, "GeometryNodeInputMeshEdgeVertices")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgesToFaceGroups")
|
self.node_operator(layout, "GeometryNodeEdgesToFaceGroups")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceArea")
|
self.node_operator(layout, "GeometryNodeInputMeshFaceArea")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshFaceSetBoundaries")
|
self.node_operator(layout, "GeometryNodeMeshFaceSetBoundaries")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceNeighbors")
|
self.node_operator(layout, "GeometryNodeInputMeshFaceNeighbors")
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeToolFaceSet")
|
self.node_operator(layout, "GeometryNodeToolFaceSet")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceIsPlanar")
|
self.node_operator(layout, "GeometryNodeInputMeshFaceIsPlanar")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputShadeSmooth")
|
self.node_operator(layout, "GeometryNodeInputShadeSmooth")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputEdgeSmooth")
|
self.node_operator(layout, "GeometryNodeInputEdgeSmooth")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshIsland")
|
self.node_operator(layout, "GeometryNodeInputMeshIsland")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputShortestEdgePaths")
|
self.node_operator(layout, "GeometryNodeInputShortestEdgePaths")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors")
|
self.node_operator(layout, "GeometryNodeInputMeshVertexNeighbors")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Read")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MESH_SAMPLE(Menu):
|
class NODE_MT_gn_mesh_sample_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH_SAMPLE"
|
|
||||||
bl_label = "Sample"
|
bl_label = "Sample"
|
||||||
|
menu_path = "Mesh/Sample"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearestSurface")
|
self.node_operator(layout, "GeometryNodeSampleNearestSurface")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleUVSurface")
|
self.node_operator(layout, "GeometryNodeSampleUVSurface")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Sample")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MESH_WRITE(Menu):
|
class NODE_MT_gn_mesh_write_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH_WRITE"
|
|
||||||
bl_label = "Write"
|
bl_label = "Write"
|
||||||
|
menu_path = "Mesh/Write"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if context.space_data.node_tree_sub_type == 'TOOL':
|
if context.space_data.node_tree_sub_type == 'TOOL':
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeToolSetFaceSet")
|
self.node_operator(layout, "GeometryNodeToolSetFaceSet")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetMeshNormal")
|
self.node_operator(layout, "GeometryNodeSetMeshNormal")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetShadeSmooth")
|
self.node_operator(layout, "GeometryNodeSetShadeSmooth")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Write")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
|
class NODE_MT_gn_mesh_operations_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH_OPERATIONS"
|
|
||||||
bl_label = "Operations"
|
bl_label = "Operations"
|
||||||
|
menu_path = "Mesh/Operations"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDualMesh")
|
self.node_operator(layout, "GeometryNodeDualMesh")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToCurves")
|
self.node_operator(layout, "GeometryNodeEdgePathsToCurves")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToSelection")
|
self.node_operator(layout, "GeometryNodeEdgePathsToSelection")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeExtrudeMesh")
|
self.node_operator(layout, "GeometryNodeExtrudeMesh")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFlipFaces")
|
self.node_operator(layout, "GeometryNodeFlipFaces")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
|
self.node_operator(layout, "GeometryNodeMeshBoolean")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
|
self.node_operator(layout, "GeometryNodeMeshToCurve")
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToDensityGrid")
|
self.node_operator(layout, "GeometryNodeMeshToDensityGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
|
self.node_operator(layout, "GeometryNodeMeshToPoints")
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFGrid")
|
self.node_operator(layout, "GeometryNodeMeshToSDFGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
|
self.node_operator(layout, "GeometryNodeMeshToVolume")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
|
self.node_operator(layout, "GeometryNodeScaleElements")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
|
self.node_operator(layout, "GeometryNodeSplitEdges")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideMesh")
|
self.node_operator(layout, "GeometryNodeSubdivideMesh")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivisionSurface")
|
self.node_operator(layout, "GeometryNodeSubdivisionSurface")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeTriangulate")
|
self.node_operator(layout, "GeometryNodeTriangulate")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Operations")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_PRIMITIVES_MESH(Menu):
|
class NODE_MT_gn_mesh_primitives_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_PRIMITIVES_MESH"
|
|
||||||
bl_label = "Primitives"
|
bl_label = "Primitives"
|
||||||
|
menu_path = "Mesh/Primitives"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCone")
|
self.node_operator(layout, "GeometryNodeMeshCone")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCube")
|
self.node_operator(layout, "GeometryNodeMeshCube")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCylinder")
|
self.node_operator(layout, "GeometryNodeMeshCylinder")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshGrid")
|
self.node_operator(layout, "GeometryNodeMeshGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshIcoSphere")
|
self.node_operator(layout, "GeometryNodeMeshIcoSphere")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCircle")
|
self.node_operator(layout, "GeometryNodeMeshCircle")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshLine")
|
self.node_operator(layout, "GeometryNodeMeshLine")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshUVSphere")
|
self.node_operator(layout, "GeometryNodeMeshUVSphere")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Primitives")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_import(Menu):
|
class NODE_MT_gn_input_import_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_import"
|
|
||||||
bl_label = "Import"
|
bl_label = "Import"
|
||||||
|
menu_path = "Input/Import"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportCSV", label="CSV (.csv)")
|
self.node_operator(layout, "GeometryNodeImportCSV", label="CSV (.csv)")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportOBJ", label="Wavefront (.obj)")
|
self.node_operator(layout, "GeometryNodeImportOBJ", label="Wavefront (.obj)")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportPLY", label="Stanford PLY (.ply)")
|
self.node_operator(layout, "GeometryNodeImportPLY", label="Stanford PLY (.ply)")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportSTL", label="STL (.stl)")
|
self.node_operator(layout, "GeometryNodeImportSTL", label="STL (.stl)")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportText", label="Text (.txt)")
|
self.node_operator(layout, "GeometryNodeImportText", label="Text (.txt)")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImportVDB", label="OpenVDB (.vdb)")
|
self.node_operator(layout, "GeometryNodeImportVDB", label="OpenVDB (.vdb)")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Input/Import")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_mesh_topology(Menu):
|
class NODE_MT_gn_mesh_topology_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_mesh_topology"
|
|
||||||
bl_label = "Topology"
|
bl_label = "Topology"
|
||||||
|
menu_path = "Mesh/Topology"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfEdge")
|
self.node_operator(layout, "GeometryNodeCornersOfEdge")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfFace")
|
self.node_operator(layout, "GeometryNodeCornersOfFace")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfVertex")
|
self.node_operator(layout, "GeometryNodeCornersOfVertex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfCorner")
|
self.node_operator(layout, "GeometryNodeEdgesOfCorner")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfVertex")
|
self.node_operator(layout, "GeometryNodeEdgesOfVertex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner")
|
self.node_operator(layout, "GeometryNodeFaceOfCorner")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace")
|
self.node_operator(layout, "GeometryNodeOffsetCornerInFace")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner")
|
self.node_operator(layout, "GeometryNodeVertexOfCorner")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/Topology")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_OUTPUT(Menu):
|
class NODE_MT_gn_output_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_OUTPUT"
|
|
||||||
bl_label = "Output"
|
bl_label = "Output"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "NodeGroupOutput")
|
self.node_operator(layout, "NodeGroupOutput")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeViewer")
|
self.node_operator(layout, "GeometryNodeViewer")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "GeometryNodeWarning", "warning_type")
|
self.node_operator_with_searchable_enum(context, layout, "GeometryNodeWarning", "warning_type")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_POINT(Menu):
|
class NODE_MT_gn_point_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_POINT"
|
|
||||||
bl_label = "Point"
|
bl_label = "Point"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInVolume")
|
self.node_operator(layout, "GeometryNodeDistributePointsInVolume")
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInGrid")
|
self.node_operator(layout, "GeometryNodeDistributePointsInGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsOnFaces")
|
self.node_operator(layout, "GeometryNodeDistributePointsOnFaces")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePoints")
|
self.node_operator(layout, "GeometryNodePoints")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
|
self.node_operator(layout, "GeometryNodePointsToCurves")
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFGrid")
|
self.node_operator(layout, "GeometryNodePointsToSDFGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
|
self.node_operator(layout, "GeometryNodePointsToVertices")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
|
self.node_operator(layout, "GeometryNodePointsToVolume")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
|
self.node_operator(layout, "GeometryNodeSetPointRadius")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_simulation(Menu):
|
class NODE_MT_gn_simulation_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_simulation"
|
|
||||||
bl_label = "Simulation"
|
bl_label = "Simulation"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_simulation_zone(layout, label="Simulation")
|
self.simulation_zone(layout, label="Simulation")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_TEXT(Menu):
|
class NODE_MT_gn_utilities_text_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_TEXT"
|
|
||||||
bl_label = "Text"
|
bl_label = "Text"
|
||||||
|
menu_path = "Utilities/Text"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeFormatString")
|
self.node_operator(layout, "FunctionNodeFormatString")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeStringJoin")
|
self.node_operator(layout, "GeometryNodeStringJoin")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeMatchString")
|
self.node_operator(layout, "FunctionNodeMatchString")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeReplaceString")
|
self.node_operator(layout, "FunctionNodeReplaceString")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeSliceString")
|
self.node_operator(layout, "FunctionNodeSliceString")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeFindInString")
|
self.node_operator(layout, "FunctionNodeFindInString")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeStringLength")
|
self.node_operator(layout, "FunctionNodeStringLength")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeStringToCurves")
|
self.node_operator(layout, "GeometryNodeStringToCurves")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeStringToValue")
|
self.node_operator(layout, "FunctionNodeStringToValue")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeValueToString")
|
self.node_operator(layout, "FunctionNodeValueToString")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInputSpecialCharacters")
|
self.node_operator(layout, "FunctionNodeInputSpecialCharacters")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Text")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_TEXTURE(Menu):
|
class NODE_MT_gn_texture_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_TEXTURE"
|
|
||||||
bl_label = "Texture"
|
bl_label = "Texture"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
self.node_operator(layout, "ShaderNodeTexBrick")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
self.node_operator(layout, "ShaderNodeTexChecker")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGabor")
|
self.node_operator(layout, "ShaderNodeTexGabor")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
self.node_operator(layout, "ShaderNodeTexGradient")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeImageTexture")
|
self.node_operator(layout, "GeometryNodeImageTexture")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
self.node_operator(layout, "ShaderNodeTexMagic")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
self.node_operator(layout, "ShaderNodeTexNoise")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
self.node_operator(layout, "ShaderNodeTexVoronoi")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
self.node_operator(layout, "ShaderNodeTexWave")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
self.node_operator(layout, "ShaderNodeTexWhiteNoise")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UTILITIES(Menu):
|
class NODE_MT_gn_utilities_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UTILITIES"
|
|
||||||
bl_label = "Utilities"
|
bl_label = "Utilities"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_COLOR")
|
self.draw_menu(layout, path="Utilities/Color")
|
||||||
layout.menu("NODE_MT_category_GEO_TEXT")
|
self.draw_menu(layout, path="Utilities/Text")
|
||||||
layout.menu("NODE_MT_category_GEO_VECTOR")
|
self.draw_menu(layout, path="Utilities/Vector")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_utilities_bundle")
|
self.draw_menu(layout, path="Utilities/Bundle")
|
||||||
layout.menu("NODE_MT_category_utilities_closure")
|
self.draw_menu(layout, path="Utilities/Closure")
|
||||||
layout.menu("NODE_MT_category_GEO_UTILITIES_FIELD")
|
self.draw_menu(layout, path="Utilities/Field")
|
||||||
|
self.draw_menu(layout, path="Utilities/Math")
|
||||||
if context.preferences.experimental.use_geometry_nodes_lists:
|
if context.preferences.experimental.use_geometry_nodes_lists:
|
||||||
layout.menu("NODE_MT_category_utilities_list")
|
self.draw_menu(layout, path="Utilities/List")
|
||||||
layout.menu("NODE_MT_category_GEO_UTILITIES_MATH")
|
self.draw_menu(layout, path="Utilities/Matrix")
|
||||||
layout.menu("NODE_MT_category_utilities_matrix")
|
self.draw_menu(layout, path="Utilities/Rotation")
|
||||||
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
|
self.draw_menu(layout, path="Utilities/Deprecated")
|
||||||
layout.menu("NODE_MT_category_GEO_UTILITIES_DEPRECATED")
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_foreach_geometry_element_zone(layout, label="For Each Element")
|
self.for_each_element_zone(layout, label="For Each Element")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeIndexSwitch")
|
self.node_operator(layout, "GeometryNodeIndexSwitch")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeMenuSwitch")
|
self.node_operator(layout, "GeometryNodeMenuSwitch")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
|
self.node_operator(layout, "FunctionNodeRandomValue")
|
||||||
node_add_menu.add_repeat_zone(layout, label="Repeat")
|
self.repeat_zone(layout, label="Repeat")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSwitch")
|
self.node_operator(layout, "GeometryNodeSwitch")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UTILITIES_DEPRECATED(Menu):
|
class NODE_MT_gn_utilities_deprecated_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_DEPRECATED"
|
|
||||||
bl_label = "Deprecated"
|
bl_label = "Deprecated"
|
||||||
|
menu_path = "Utilities/Deprecated"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeAlignEulerToVector")
|
self.node_operator(layout, "FunctionNodeAlignEulerToVector")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
|
self.node_operator(layout, "FunctionNodeRotateEuler")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Deprecated")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UTILITIES_FIELD(Menu):
|
class NODE_MT_gn_utilities_field_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_FIELD"
|
|
||||||
bl_label = "Field"
|
bl_label = "Field"
|
||||||
|
menu_path = "Utilities/Field"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeAccumulateField")
|
self.node_operator(layout, "GeometryNodeAccumulateField")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldAtIndex")
|
self.node_operator(layout, "GeometryNodeFieldAtIndex")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldOnDomain")
|
self.node_operator(layout, "GeometryNodeFieldOnDomain")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldAverage")
|
self.node_operator(layout, "GeometryNodeFieldAverage")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldMinAndMax")
|
self.node_operator(layout, "GeometryNodeFieldMinAndMax")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldVariance")
|
self.node_operator(layout, "GeometryNodeFieldVariance")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Field")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu):
|
class NODE_MT_gn_utilities_rotation_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_ROTATION"
|
|
||||||
bl_label = "Rotation"
|
bl_label = "Rotation"
|
||||||
|
menu_path = "Utilities/Rotation"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeAlignRotationToVector")
|
self.node_operator(layout, "FunctionNodeAlignRotationToVector")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeAxesToRotation")
|
self.node_operator(layout, "FunctionNodeAxesToRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeAxisAngleToRotation")
|
self.node_operator(layout, "FunctionNodeAxisAngleToRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeEulerToRotation")
|
self.node_operator(layout, "FunctionNodeEulerToRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInvertRotation")
|
self.node_operator(layout, "FunctionNodeInvertRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateRotation")
|
self.node_operator(layout, "FunctionNodeRotateRotation")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateVector")
|
self.node_operator(layout, "FunctionNodeRotateVector")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToAxisAngle")
|
self.node_operator(layout, "FunctionNodeRotationToAxisAngle")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToEuler")
|
self.node_operator(layout, "FunctionNodeRotationToEuler")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToQuaternion")
|
self.node_operator(layout, "FunctionNodeRotationToQuaternion")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeQuaternionToRotation")
|
self.node_operator(layout, "FunctionNodeQuaternionToRotation")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Rotation")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_utilities_matrix(Menu):
|
class NODE_MT_gn_utilities_matrix_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_utilities_matrix"
|
|
||||||
bl_label = "Matrix"
|
bl_label = "Matrix"
|
||||||
|
menu_path = "Utilities/Matrix"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineMatrix")
|
self.node_operator(layout, "FunctionNodeCombineMatrix")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineTransform")
|
self.node_operator(layout, "FunctionNodeCombineTransform")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixDeterminant", label="Determinant")
|
self.node_operator(layout, "FunctionNodeMatrixDeterminant", label="Determinant")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeInvertMatrix")
|
self.node_operator(layout, "FunctionNodeInvertMatrix")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMultiply")
|
self.node_operator(layout, "FunctionNodeMatrixMultiply")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeProjectPoint")
|
self.node_operator(layout, "FunctionNodeProjectPoint")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateMatrix")
|
self.node_operator(layout, "FunctionNodeSeparateMatrix")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateTransform")
|
self.node_operator(layout, "FunctionNodeSeparateTransform")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
|
self.node_operator(layout, "FunctionNodeTransformDirection")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeTransformPoint")
|
self.node_operator(layout, "FunctionNodeTransformPoint")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeTransposeMatrix")
|
self.node_operator(layout, "FunctionNodeTransposeMatrix")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Matrix")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_utilities_bundle(Menu):
|
class NODE_MT_category_utilities_bundle_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_utilities_bundle"
|
|
||||||
bl_label = "Bundle"
|
bl_label = "Bundle"
|
||||||
|
menu_path = "Utilities/Bundle"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "NodeCombineBundle")
|
self.node_operator(layout, "NodeCombineBundle")
|
||||||
node_add_menu.add_node_type(layout, "NodeSeparateBundle")
|
self.node_operator(layout, "NodeSeparateBundle")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Bundle")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_utilities_closure(Menu):
|
class NODE_MT_category_utilities_closure_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_utilities_closure"
|
|
||||||
bl_label = "Closure"
|
bl_label = "Closure"
|
||||||
|
menu_path = "Utilities/Closure"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_closure_zone(layout, label="Closure")
|
self.closure_zone(layout, label="Closure")
|
||||||
node_add_menu.add_node_type(layout, "NodeEvaluateClosure")
|
self.node_operator(layout, "NodeEvaluateClosure")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Closure")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_utilities_list(Menu):
|
class NODE_MT_gn_utilities_list_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_utilities_list"
|
|
||||||
bl_label = "List"
|
bl_label = "List"
|
||||||
|
menu_path = "Utilities/List"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeList")
|
self.node_operator(layout, "GeometryNodeList")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeListGetItem")
|
self.node_operator(layout, "GeometryNodeListGetItem")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeListLength")
|
self.node_operator(layout, "GeometryNodeListLength")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/List")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UTILITIES_MATH(Menu):
|
class NODE_MT_gn_utilities_math_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UTILITIES_MATH"
|
|
||||||
bl_label = "Math"
|
bl_label = "Math"
|
||||||
|
menu_path = "Utilities/Math"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type_with_searchable_enum(
|
self.node_operator_with_searchable_enum(
|
||||||
context, layout, "FunctionNodeBitMath", "operation", search_weight=-1.0,
|
context, layout, "FunctionNodeBitMath", "operation", search_weight=-1.0,
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "FunctionNodeBooleanMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "FunctionNodeBooleanMath", "operation")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "FunctionNodeIntegerMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "FunctionNodeIntegerMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
self.node_operator(layout, "ShaderNodeClamp")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeCompare")
|
self.node_operator(layout, "FunctionNodeCompare")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
self.node_operator(layout, "ShaderNodeFloatCurve")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeFloatToInt")
|
self.node_operator(layout, "FunctionNodeFloatToInt")
|
||||||
node_add_menu.add_node_type(layout, "FunctionNodeHashValue")
|
self.node_operator(layout, "FunctionNodeHashValue")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
self.node_operator(layout, "ShaderNodeMapRange")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
self.node_operator(layout, "ShaderNodeMix")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Math")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_UV(Menu):
|
class NODE_MT_gn_mesh_uv_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_UV"
|
|
||||||
bl_label = "UV"
|
bl_label = "UV"
|
||||||
|
menu_path = "Mesh/UV"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeUVPackIslands")
|
self.node_operator(layout, "GeometryNodeUVPackIslands")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeUVUnwrap")
|
self.node_operator(layout, "GeometryNodeUVUnwrap")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Mesh/UV")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_VECTOR(Menu):
|
class NODE_MT_gn_utilities_vector_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_VECTOR"
|
|
||||||
bl_label = "Vector"
|
bl_label = "Vector"
|
||||||
|
menu_path = "Utilities/Vector"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRadialTiling")
|
self.node_operator(layout, "ShaderNodeRadialTiling")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
self.node_operator(layout, "ShaderNodeVectorCurve")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
self.node_operator(layout, "ShaderNodeVectorRotate")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
self.node_operator(layout, "ShaderNodeCombineXYZ")
|
||||||
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label="Mix Vector")
|
props = self.node_operator(layout, "ShaderNodeMix", label="Mix Vector")
|
||||||
ops = props.settings.add()
|
ops = props.settings.add()
|
||||||
ops.name = "data_type"
|
ops.name = "data_type"
|
||||||
ops.value = "'VECTOR'"
|
ops.value = "'VECTOR'"
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
self.node_operator(layout, "ShaderNodeSeparateXYZ")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Vector")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_VOLUME(Menu):
|
class NODE_MT_gn_volume_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_VOLUME"
|
|
||||||
bl_label = "Volume"
|
bl_label = "Volume"
|
||||||
bl_translation_context = i18n_contexts.id_id
|
bl_translation_context = i18n_contexts.id_id
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_READ")
|
self.draw_menu(layout, path="Volume/Read")
|
||||||
layout.menu("NODE_MT_geometry_node_volume_sample")
|
self.draw_menu(layout, path="Volume/Sample")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_WRITE")
|
self.draw_menu(layout, path="Volume/Write")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS")
|
self.draw_menu(layout, path="Volume/Operations")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES")
|
self.draw_menu(layout, path="Volume/Primitives")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_VOLUME_READ(Menu):
|
class NODE_MT_gn_volume_read_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_READ"
|
|
||||||
bl_label = "Read"
|
bl_label = "Read"
|
||||||
|
menu_path = "Volume/Read"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGetNamedGrid")
|
self.node_operator(layout, "GeometryNodeGetNamedGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGridInfo")
|
self.node_operator(layout, "GeometryNodeGridInfo")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Read")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_VOLUME_WRITE(Menu):
|
class NODE_MT_gn_volume_write_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_WRITE"
|
|
||||||
bl_label = "Write"
|
bl_label = "Write"
|
||||||
|
menu_path = "Volume/Write"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedGrid")
|
self.node_operator(layout, "GeometryNodeStoreNamedGrid")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Write")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_volume_sample(Menu):
|
class NODE_MT_gn_volume_sample_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_volume_sample"
|
|
||||||
bl_label = "Sample"
|
bl_label = "Sample"
|
||||||
|
menu_path = "Volume/Sample"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleGrid")
|
self.node_operator(layout, "GeometryNodeSampleGrid")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleGridIndex")
|
self.node_operator(layout, "GeometryNodeSampleGridIndex")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Sample")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS(Menu):
|
class NODE_MT_gn_volume_operations_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS"
|
|
||||||
bl_label = "Operations"
|
bl_label = "Operations"
|
||||||
|
menu_path = "Volume/Operations"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
self.node_operator(layout, "GeometryNodeVolumeToMesh")
|
||||||
if context.preferences.experimental.use_new_volume_nodes:
|
if context.preferences.experimental.use_new_volume_nodes:
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeGridToMesh")
|
self.node_operator(layout, "GeometryNodeGridToMesh")
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeSDFGridBoolean")
|
self.node_operator(layout, "GeometryNodeSDFGridBoolean")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Operations")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES(Menu):
|
class NODE_MT_gn_volume_primitives_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES"
|
|
||||||
bl_label = "Primitives"
|
bl_label = "Primitives"
|
||||||
|
menu_path = "Volume/Primitives"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
|
self.node_operator(layout, "GeometryNodeVolumeCube")
|
||||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Primitives")
|
|
||||||
|
self.draw_assets_for_catalog(layout, self.menu_path)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_GEO_GROUP(Menu):
|
class NODE_MT_gn_all_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_GEO_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_geometry_node_add_all(Menu):
|
|
||||||
bl_idname = "NODE_MT_geometry_node_add_all"
|
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
menu_path = "Root"
|
||||||
|
|
||||||
|
# NOTE: Menus are looked up via their label, this is so that both the Add
|
||||||
|
# & Swap menus can share the same layout while each using their
|
||||||
|
# corresponding menus
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_ATTRIBUTE")
|
self.draw_menu(layout, "Attribute")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT")
|
self.draw_menu(layout, "Input")
|
||||||
layout.menu("NODE_MT_category_GEO_OUTPUT")
|
self.draw_menu(layout, "Output")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY")
|
self.draw_menu(layout, "Geometry")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE")
|
self.draw_menu(layout, "Curve")
|
||||||
layout.menu("NODE_MT_geometry_node_grease_pencil")
|
self.draw_menu(layout, "Grease Pencil")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_INSTANCE")
|
self.draw_menu(layout, "Instances")
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MESH")
|
self.draw_menu(layout, "Mesh")
|
||||||
layout.menu("NODE_MT_category_GEO_POINT")
|
self.draw_menu(layout, "Point")
|
||||||
layout.menu("NODE_MT_category_GEO_VOLUME")
|
self.draw_menu(layout, "Volume")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_simulation")
|
self.draw_menu(layout, "Simulation")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_geometry_node_GEO_MATERIAL")
|
self.draw_menu(layout, "Material")
|
||||||
layout.menu("NODE_MT_category_GEO_TEXTURE")
|
self.draw_menu(layout, "Texture")
|
||||||
layout.menu("NODE_MT_category_GEO_UTILITIES")
|
self.draw_menu(layout, "Utilities")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_GEO_GROUP")
|
self.draw_menu(layout, "Group")
|
||||||
layout.menu("NODE_MT_category_layout")
|
self.draw_menu(layout, "Layout")
|
||||||
node_add_menu.draw_root_assets(layout)
|
|
||||||
|
self.draw_root_assets(layout)
|
||||||
|
|
||||||
|
|
||||||
|
add_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_geometry_node_GEO_ATTRIBUTE": NODE_MT_gn_attribute_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INPUT": NODE_MT_gn_input_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INPUT_CONSTANT": NODE_MT_gn_input_constant_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INPUT_GIZMO": NODE_MT_gn_input_gizmo_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INPUT_GROUP": NODE_MT_gn_input_group_base,
|
||||||
|
"NODE_MT_category_import": NODE_MT_gn_input_import_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INPUT_SCENE": NODE_MT_gn_input_scene_base,
|
||||||
|
"NODE_MT_category_GEO_OUTPUT": NODE_MT_gn_output_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_CURVE": NODE_MT_gn_curve_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_CURVE_READ": NODE_MT_gn_curve_read_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_CURVE_SAMPLE": NODE_MT_gn_curve_sample_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_CURVE_WRITE": NODE_MT_gn_curve_write_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_CURVE_OPERATIONS": NODE_MT_gn_curve_operations_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE": NODE_MT_gn_curve_primitives_base,
|
||||||
|
"NODE_MT_geometry_node_curve_topology": NODE_MT_gn_curve_topology_base,
|
||||||
|
"NODE_MT_geometry_node_grease_pencil": NODE_MT_gn_grease_pencil_base,
|
||||||
|
"NODE_MT_geometry_node_grease_pencil_read": NODE_MT_gn_grease_pencil_read_base,
|
||||||
|
"NODE_MT_geometry_node_grease_pencil_write": NODE_MT_gn_grease_pencil_write_base,
|
||||||
|
"NODE_MT_geometry_node_grease_pencil_operations": NODE_MT_gn_grease_pencil_operations_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_GEOMETRY": NODE_MT_gn_geometry_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_GEOMETRY_READ": NODE_MT_gn_geometry_read_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_GEOMETRY_WRITE": NODE_MT_gn_geometry_write_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS": NODE_MT_gn_geometry_operations_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE": NODE_MT_gn_geometry_sample_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_INSTANCE": NODE_MT_gn_instance_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MESH": NODE_MT_gn_mesh_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MESH_READ": NODE_MT_gn_mesh_read_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MESH_SAMPLE": NODE_MT_gn_mesh_sample_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MESH_WRITE": NODE_MT_gn_mesh_write_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MESH_OPERATIONS": NODE_MT_gn_mesh_operations_base,
|
||||||
|
"NODE_MT_category_PRIMITIVES_MESH": NODE_MT_gn_mesh_uv_base,
|
||||||
|
"NODE_MT_geometry_node_mesh_topology": NODE_MT_gn_mesh_topology_base,
|
||||||
|
"NODE_MT_category_GEO_UV": NODE_MT_gn_mesh_primitives_base,
|
||||||
|
"NODE_MT_category_GEO_POINT": NODE_MT_gn_point_base,
|
||||||
|
"NODE_MT_category_simulation": NODE_MT_gn_simulation_base,
|
||||||
|
"NODE_MT_category_GEO_VOLUME": NODE_MT_gn_volume_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_VOLUME_READ": NODE_MT_gn_volume_read_base,
|
||||||
|
"NODE_MT_geometry_node_volume_sample": NODE_MT_gn_volume_sample_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_VOLUME_WRITE": NODE_MT_gn_volume_write_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS": NODE_MT_gn_volume_operations_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES": NODE_MT_gn_volume_primitives_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_MATERIAL": NODE_MT_gn_material_base,
|
||||||
|
"NODE_MT_category_GEO_TEXTURE": NODE_MT_gn_texture_base,
|
||||||
|
"NODE_MT_category_GEO_UTILITIES": NODE_MT_gn_utilities_base,
|
||||||
|
"NODE_MT_geometry_node_GEO_COLOR": NODE_MT_gn_utilities_color_base,
|
||||||
|
"NODE_MT_category_GEO_TEXT": NODE_MT_gn_utilities_text_base,
|
||||||
|
"NODE_MT_category_GEO_VECTOR": NODE_MT_gn_utilities_vector_base,
|
||||||
|
"NODE_MT_category_utilities_bundle": NODE_MT_category_utilities_bundle_base,
|
||||||
|
"NODE_MT_category_utilities_closure": NODE_MT_category_utilities_closure_base,
|
||||||
|
"NODE_MT_category_GEO_UTILITIES_FIELD": NODE_MT_gn_utilities_field_base,
|
||||||
|
"NODE_MT_category_GEO_UTILITIES_MATH": NODE_MT_gn_utilities_math_base,
|
||||||
|
"NODE_MT_category_GEO_UTILITIES_ROTATION": NODE_MT_gn_utilities_rotation_base,
|
||||||
|
"NODE_MT_category_utilities_list": NODE_MT_gn_utilities_list_base,
|
||||||
|
"NODE_MT_category_utilities_matrix": NODE_MT_gn_utilities_matrix_base,
|
||||||
|
"NODE_MT_category_GEO_UTILITIES_DEPRECATED": NODE_MT_gn_utilities_deprecated_base,
|
||||||
|
"NODE_MT_geometry_node_add_all": NODE_MT_gn_all_base,
|
||||||
|
}
|
||||||
|
add_menus = node_add_menu.generate_menus(
|
||||||
|
add_menus,
|
||||||
|
template=node_add_menu.AddNodeMenu,
|
||||||
|
base_dict=node_add_menu.add_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
swap_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_gn_attribute_swap": NODE_MT_gn_attribute_base,
|
||||||
|
"NODE_MT_gn_input_swap": NODE_MT_gn_input_base,
|
||||||
|
"NODE_MT_gn_input_constant_swap": NODE_MT_gn_input_constant_base,
|
||||||
|
"NODE_MT_gn_input_gizmo_swap": NODE_MT_gn_input_gizmo_base,
|
||||||
|
"NODE_MT_gn_input_group_swap": NODE_MT_gn_input_group_base,
|
||||||
|
"NODE_MT_gn_input_import_swap": NODE_MT_gn_input_import_base,
|
||||||
|
"NODE_MT_gn_input_scene_swap": NODE_MT_gn_input_scene_base,
|
||||||
|
"NODE_MT_gn_output_swap": NODE_MT_gn_output_base,
|
||||||
|
"NODE_MT_gn_curve_swap": NODE_MT_gn_curve_base,
|
||||||
|
"NODE_MT_gn_curve_read_swap": NODE_MT_gn_curve_read_base,
|
||||||
|
"NODE_MT_gn_curve_sample_swap": NODE_MT_gn_curve_sample_base,
|
||||||
|
"NODE_MT_gn_curve_write_swap": NODE_MT_gn_curve_write_base,
|
||||||
|
"NODE_MT_gn_curve_operations_swap": NODE_MT_gn_curve_operations_base,
|
||||||
|
"NODE_MT_gn_curve_primitives_swap": NODE_MT_gn_curve_primitives_base,
|
||||||
|
"NODE_MT_gn_curve_topology_swap": NODE_MT_gn_curve_topology_base,
|
||||||
|
"NODE_MT_gn_grease_pencil_swap": NODE_MT_gn_grease_pencil_base,
|
||||||
|
"NODE_MT_gn_grease_pencil_read_swap": NODE_MT_gn_grease_pencil_read_base,
|
||||||
|
"NODE_MT_gn_grease_pencil_write_swap": NODE_MT_gn_grease_pencil_write_base,
|
||||||
|
"NODE_MT_gn_grease_pencil_operations_swap": NODE_MT_gn_grease_pencil_operations_base,
|
||||||
|
"NODE_MT_gn_geometry_swap": NODE_MT_gn_geometry_base,
|
||||||
|
"NODE_MT_gn_geometry_read_swap": NODE_MT_gn_geometry_read_base,
|
||||||
|
"NODE_MT_gn_geometry_write_swap": NODE_MT_gn_geometry_write_base,
|
||||||
|
"NODE_MT_gn_geometry_operations_swap": NODE_MT_gn_geometry_operations_base,
|
||||||
|
"NODE_MT_gn_geometry_sample_swap": NODE_MT_gn_geometry_sample_base,
|
||||||
|
"NODE_MT_gn_instance_swap": NODE_MT_gn_instance_base,
|
||||||
|
"NODE_MT_gn_mesh_swap": NODE_MT_gn_mesh_base,
|
||||||
|
"NODE_MT_gn_mesh_read_swap": NODE_MT_gn_mesh_read_base,
|
||||||
|
"NODE_MT_gn_mesh_sample_swap": NODE_MT_gn_mesh_sample_base,
|
||||||
|
"NODE_MT_gn_mesh_write_swap": NODE_MT_gn_mesh_write_base,
|
||||||
|
"NODE_MT_gn_mesh_operations_swap": NODE_MT_gn_mesh_operations_base,
|
||||||
|
"NODE_MT_gn_mesh_uv_swap": NODE_MT_gn_mesh_uv_base,
|
||||||
|
"NODE_MT_gn_mesh_topology_swap": NODE_MT_gn_mesh_topology_base,
|
||||||
|
"NODE_MT_gn_mesh_primitives_swap": NODE_MT_gn_mesh_primitives_base,
|
||||||
|
"NODE_MT_gn_point_swap": NODE_MT_gn_point_base,
|
||||||
|
"NODE_MT_gn_simulation_swap": NODE_MT_gn_simulation_base,
|
||||||
|
"NODE_MT_gn_volume_swap": NODE_MT_gn_volume_base,
|
||||||
|
"NODE_MT_gn_volume_read_swap": NODE_MT_gn_volume_read_base,
|
||||||
|
"NODE_MT_gn_volume_sample_swap": NODE_MT_gn_volume_sample_base,
|
||||||
|
"NODE_MT_gn_volume_write_swap": NODE_MT_gn_volume_write_base,
|
||||||
|
"NODE_MT_gn_volume_operations_swap": NODE_MT_gn_volume_operations_base,
|
||||||
|
"NODE_MT_gn_volume_primitives_swap": NODE_MT_gn_volume_primitives_base,
|
||||||
|
"NODE_MT_gn_material_swap": NODE_MT_gn_material_base,
|
||||||
|
"NODE_MT_gn_texture_swap": NODE_MT_gn_texture_base,
|
||||||
|
"NODE_MT_gn_utilities_swap": NODE_MT_gn_utilities_base,
|
||||||
|
"NODE_MT_gn_utilities_color_swap": NODE_MT_gn_utilities_color_base,
|
||||||
|
"NODE_MT_gn_utilities_text_swap": NODE_MT_gn_utilities_text_base,
|
||||||
|
"NODE_MT_gn_utilities_vector_swap": NODE_MT_gn_utilities_vector_base,
|
||||||
|
"NODE_MT_gn_utilities_bundle_swap": NODE_MT_category_utilities_bundle_base,
|
||||||
|
"NODE_MT_gn_utilities_closure_swap": NODE_MT_category_utilities_closure_base,
|
||||||
|
"NODE_MT_gn_utilities_field_swap": NODE_MT_gn_utilities_field_base,
|
||||||
|
"NODE_MT_gn_utilities_math_swap": NODE_MT_gn_utilities_math_base,
|
||||||
|
"NODE_MT_gn_utilities_rotation_swap": NODE_MT_gn_utilities_rotation_base,
|
||||||
|
"NODE_MT_gn_utilities_list_swap": NODE_MT_gn_utilities_list_base,
|
||||||
|
"NODE_MT_gn_utilities_matrix_swap": NODE_MT_gn_utilities_matrix_base,
|
||||||
|
"NODE_MT_gn_utilities_deprecated_swap": NODE_MT_gn_utilities_deprecated_base,
|
||||||
|
"NODE_MT_geometry_node_swap_all": NODE_MT_gn_all_base,
|
||||||
|
}
|
||||||
|
swap_menus = node_add_menu.generate_menus(
|
||||||
|
swap_menus,
|
||||||
|
template=node_add_menu.SwapNodeMenu,
|
||||||
|
base_dict=node_add_menu.swap_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
NODE_MT_geometry_node_add_all,
|
*add_menus,
|
||||||
NODE_MT_geometry_node_GEO_ATTRIBUTE,
|
*swap_menus,
|
||||||
NODE_MT_geometry_node_GEO_INPUT,
|
|
||||||
NODE_MT_geometry_node_GEO_INPUT_CONSTANT,
|
|
||||||
NODE_MT_geometry_node_GEO_INPUT_GROUP,
|
|
||||||
NODE_MT_geometry_node_GEO_INPUT_SCENE,
|
|
||||||
NODE_MT_category_GEO_OUTPUT,
|
|
||||||
NODE_MT_geometry_node_GEO_CURVE,
|
|
||||||
NODE_MT_geometry_node_GEO_CURVE_READ,
|
|
||||||
NODE_MT_geometry_node_GEO_CURVE_SAMPLE,
|
|
||||||
NODE_MT_geometry_node_GEO_CURVE_WRITE,
|
|
||||||
NODE_MT_geometry_node_GEO_CURVE_OPERATIONS,
|
|
||||||
NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE,
|
|
||||||
NODE_MT_geometry_node_curve_topology,
|
|
||||||
NODE_MT_geometry_node_grease_pencil,
|
|
||||||
NODE_MT_geometry_node_grease_pencil_read,
|
|
||||||
NODE_MT_geometry_node_grease_pencil_write,
|
|
||||||
NODE_MT_geometry_node_grease_pencil_operations,
|
|
||||||
NODE_MT_geometry_node_GEO_GEOMETRY,
|
|
||||||
NODE_MT_geometry_node_GEO_GEOMETRY_READ,
|
|
||||||
NODE_MT_geometry_node_GEO_GEOMETRY_WRITE,
|
|
||||||
NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS,
|
|
||||||
NODE_MT_geometry_node_GEO_GEOMETRY_SAMPLE,
|
|
||||||
NODE_MT_geometry_node_GEO_INSTANCE,
|
|
||||||
NODE_MT_geometry_node_GEO_MESH,
|
|
||||||
NODE_MT_geometry_node_GEO_MESH_READ,
|
|
||||||
NODE_MT_geometry_node_GEO_MESH_SAMPLE,
|
|
||||||
NODE_MT_geometry_node_GEO_MESH_WRITE,
|
|
||||||
NODE_MT_geometry_node_GEO_MESH_OPERATIONS,
|
|
||||||
NODE_MT_category_GEO_UV,
|
|
||||||
NODE_MT_category_PRIMITIVES_MESH,
|
|
||||||
NODE_MT_category_import,
|
|
||||||
NODE_MT_geometry_node_mesh_topology,
|
|
||||||
NODE_MT_category_GEO_POINT,
|
|
||||||
NODE_MT_category_simulation,
|
|
||||||
NODE_MT_category_GEO_VOLUME,
|
|
||||||
NODE_MT_geometry_node_GEO_VOLUME_READ,
|
|
||||||
NODE_MT_geometry_node_volume_sample,
|
|
||||||
NODE_MT_geometry_node_GEO_VOLUME_WRITE,
|
|
||||||
NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS,
|
|
||||||
NODE_MT_geometry_node_GEO_VOLUME_PRIMITIVES,
|
|
||||||
NODE_MT_geometry_node_GEO_MATERIAL,
|
|
||||||
NODE_MT_category_GEO_TEXTURE,
|
|
||||||
NODE_MT_category_GEO_UTILITIES,
|
|
||||||
NODE_MT_geometry_node_GEO_COLOR,
|
|
||||||
NODE_MT_category_GEO_TEXT,
|
|
||||||
NODE_MT_category_GEO_VECTOR,
|
|
||||||
NODE_MT_category_GEO_UTILITIES_FIELD,
|
|
||||||
NODE_MT_category_GEO_UTILITIES_MATH,
|
|
||||||
NODE_MT_category_GEO_UTILITIES_ROTATION,
|
|
||||||
NODE_MT_geometry_node_GEO_INPUT_GIZMO,
|
|
||||||
NODE_MT_category_utilities_list,
|
|
||||||
NODE_MT_category_utilities_matrix,
|
|
||||||
NODE_MT_category_utilities_bundle,
|
|
||||||
NODE_MT_category_utilities_closure,
|
|
||||||
NODE_MT_category_GEO_UTILITIES_DEPRECATED,
|
|
||||||
NODE_MT_category_GEO_GROUP,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": # only for live edit.
|
if __name__ == "__main__": # only for live edit.
|
||||||
from bpy.utils import register_class
|
from bpy.utils import register_class
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
|
|||||||
@@ -48,27 +48,26 @@ def object_eevee_shader_nodes_poll(context):
|
|||||||
eevee_shader_nodes_poll(context))
|
eevee_shader_nodes_poll(context))
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_input(Menu):
|
class NODE_MT_shader_node_input_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_input"
|
|
||||||
bl_label = "Input"
|
bl_label = "Input"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeAmbientOcclusion")
|
self.node_operator(layout, "ShaderNodeAmbientOcclusion")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeAttribute")
|
self.node_operator(layout, "ShaderNodeAttribute")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBevel")
|
self.node_operator(layout, "ShaderNodeBevel")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeCameraData",
|
context, layout, "ShaderNodeCameraData",
|
||||||
["View Vector", "View Z Depth", "View Distance"],
|
["View Vector", "View Z Depth", "View Distance"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVertexColor")
|
self.node_operator(layout, "ShaderNodeVertexColor")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeHairInfo",
|
context, layout, "ShaderNodeHairInfo",
|
||||||
["Is Strand", "Intercept", "Length", "Thickness", "Tangent Normal", "Random"],
|
["Is Strand", "Intercept", "Length", "Thickness", "Tangent Normal", "Random"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeFresnel")
|
self.node_operator(layout, "ShaderNodeFresnel")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context,
|
context,
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeNewGeometry",
|
"ShaderNodeNewGeometry",
|
||||||
@@ -84,8 +83,8 @@ class NODE_MT_category_shader_input(Menu):
|
|||||||
"Random Per Island",
|
"Random Per Island",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeLayerWeight")
|
self.node_operator(layout, "ShaderNodeLayerWeight")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context,
|
context,
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeLightPath",
|
"ShaderNodeLightPath",
|
||||||
@@ -107,358 +106,374 @@ class NODE_MT_category_shader_input(Menu):
|
|||||||
"Portal Depth"
|
"Portal Depth"
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeObjectInfo",
|
context, layout, "ShaderNodeObjectInfo",
|
||||||
["Location", "Color", "Alpha", "Object Index", "Material Index", "Random"],
|
["Location", "Color", "Alpha", "Object Index", "Material Index", "Random"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeParticleInfo",
|
context, layout, "ShaderNodeParticleInfo",
|
||||||
["Index", "Random", "Age", "Lifetime", "Location", "Size", "Velocity", "Angular Velocity"],
|
["Index", "Random", "Age", "Lifetime", "Location", "Size", "Velocity", "Angular Velocity"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodePointInfo",
|
context, layout, "ShaderNodePointInfo",
|
||||||
["Position", "Radius", "Random"],
|
["Position", "Radius", "Random"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRGB")
|
self.node_operator(layout, "ShaderNodeRGB")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTangent")
|
self.node_operator(layout, "ShaderNodeTangent")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeTexCoord",
|
context, layout, "ShaderNodeTexCoord",
|
||||||
["Normal", "UV", "Object", "Camera", "Window", "Reflection"],
|
["Normal", "UV", "Object", "Camera", "Window", "Reflection"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll(context))
|
self.node_operator(layout, "ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll(context))
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeUVMap")
|
self.node_operator(layout, "ShaderNodeUVMap")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
self.node_operator(layout, "ShaderNodeValue")
|
||||||
node_add_menu.add_node_type_with_outputs(
|
self.node_operator_with_outputs(
|
||||||
context, layout, "ShaderNodeVolumeInfo",
|
context, layout, "ShaderNodeVolumeInfo",
|
||||||
["Color", "Density", "Flame", "Temperature"],
|
["Color", "Density", "Flame", "Temperature"],
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeWireframe")
|
self.node_operator(layout, "ShaderNodeWireframe")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_output(Menu):
|
class NODE_MT_shader_node_output_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_output"
|
|
||||||
bl_label = "Output"
|
bl_label = "Output"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeOutputAOV",
|
"ShaderNodeOutputAOV",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeOutputLight",
|
"ShaderNodeOutputLight",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeOutputLineStyle",
|
"ShaderNodeOutputLineStyle",
|
||||||
poll=line_style_shader_nodes_poll(context),
|
poll=line_style_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeOutputMaterial",
|
"ShaderNodeOutputMaterial",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeOutputWorld",
|
"ShaderNodeOutputWorld",
|
||||||
poll=world_shader_nodes_poll(context),
|
poll=world_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_shader(Menu):
|
class NODE_MT_shader_node_shader_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_shader"
|
|
||||||
bl_label = "Shader"
|
bl_label = "Shader"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeAddShader",
|
"ShaderNodeAddShader",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBackground",
|
"ShaderNodeBackground",
|
||||||
poll=world_shader_nodes_poll(context),
|
poll=world_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfDiffuse",
|
"ShaderNodeBsdfDiffuse",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeEmission",
|
"ShaderNodeEmission",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfGlass",
|
"ShaderNodeBsdfGlass",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfGlossy",
|
"ShaderNodeBsdfGlossy",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfHair",
|
"ShaderNodeBsdfHair",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeHoldout",
|
"ShaderNodeHoldout",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfMetallic",
|
"ShaderNodeBsdfMetallic",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeMixShader",
|
"ShaderNodeMixShader",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfPrincipled",
|
"ShaderNodeBsdfPrincipled",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfHairPrincipled",
|
"ShaderNodeBsdfHairPrincipled",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeVolumePrincipled"
|
"ShaderNodeVolumePrincipled"
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfRayPortal",
|
"ShaderNodeBsdfRayPortal",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfRefraction",
|
"ShaderNodeBsdfRefraction",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfSheen",
|
"ShaderNodeBsdfSheen",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeEeveeSpecular",
|
"ShaderNodeEeveeSpecular",
|
||||||
poll=object_eevee_shader_nodes_poll(context),
|
poll=object_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeSubsurfaceScattering",
|
"ShaderNodeSubsurfaceScattering",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfToon",
|
"ShaderNodeBsdfToon",
|
||||||
poll=object_not_eevee_shader_nodes_poll(context),
|
poll=object_not_eevee_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfTranslucent",
|
"ShaderNodeBsdfTranslucent",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeBsdfTransparent",
|
"ShaderNodeBsdfTransparent",
|
||||||
poll=object_shader_nodes_poll(context),
|
poll=object_shader_nodes_poll(context),
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeVolumeAbsorption",
|
"ShaderNodeVolumeAbsorption",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeVolumeScatter",
|
"ShaderNodeVolumeScatter",
|
||||||
)
|
)
|
||||||
node_add_menu.add_node_type(
|
self.node_operator(
|
||||||
layout,
|
layout,
|
||||||
"ShaderNodeVolumeCoefficients",
|
"ShaderNodeVolumeCoefficients",
|
||||||
)
|
)
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_color(Menu):
|
class NODE_MT_shader_node_color_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_color"
|
|
||||||
bl_label = "Color"
|
bl_label = "Color"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBrightContrast")
|
self.node_operator(layout, "ShaderNodeBrightContrast")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeGamma")
|
self.node_operator(layout, "ShaderNodeGamma")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeHueSaturation")
|
self.node_operator(layout, "ShaderNodeHueSaturation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeInvert")
|
self.node_operator(layout, "ShaderNodeInvert")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeLightFalloff")
|
self.node_operator(layout, "ShaderNodeLightFalloff")
|
||||||
node_add_menu.add_color_mix_node(context, layout)
|
self.color_mix_node(context, layout)
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
|
self.node_operator(layout, "ShaderNodeRGBCurve")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_converter(Menu):
|
class NODE_MT_shader_node_converter_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_converter"
|
|
||||||
bl_label = "Converter"
|
bl_label = "Converter"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBlackbody")
|
self.node_operator(layout, "ShaderNodeBlackbody")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
self.node_operator(layout, "ShaderNodeClamp")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
self.node_operator(layout, "ShaderNodeValToRGB")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineColor")
|
self.node_operator(layout, "ShaderNodeCombineColor")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
self.node_operator(layout, "ShaderNodeCombineXYZ")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
self.node_operator(layout, "ShaderNodeFloatCurve")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
self.node_operator(layout, "ShaderNodeMapRange")
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
self.node_operator(layout, "ShaderNodeMix")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBToBW")
|
self.node_operator(layout, "ShaderNodeRGBToBW")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateColor")
|
self.node_operator(layout, "ShaderNodeSeparateColor")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
self.node_operator(layout, "ShaderNodeSeparateXYZ")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll(context))
|
self.node_operator(layout, "ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll(context))
|
||||||
node_add_menu.add_node_type_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
self.node_operator_with_searchable_enum(context, layout, "ShaderNodeVectorMath", "operation")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeWavelength")
|
self.node_operator(layout, "ShaderNodeWavelength")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_texture(Menu):
|
class NODE_MT_shader_node_texture_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_texture"
|
|
||||||
bl_label = "Texture"
|
bl_label = "Texture"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
self.node_operator(layout, "ShaderNodeTexBrick")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
self.node_operator(layout, "ShaderNodeTexChecker")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexEnvironment")
|
self.node_operator(layout, "ShaderNodeTexEnvironment")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGabor")
|
self.node_operator(layout, "ShaderNodeTexGabor")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
self.node_operator(layout, "ShaderNodeTexGradient")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexIES")
|
self.node_operator(layout, "ShaderNodeTexIES")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexImage")
|
self.node_operator(layout, "ShaderNodeTexImage")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
self.node_operator(layout, "ShaderNodeTexMagic")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
self.node_operator(layout, "ShaderNodeTexNoise")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexSky")
|
self.node_operator(layout, "ShaderNodeTexSky")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
self.node_operator(layout, "ShaderNodeTexVoronoi")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
self.node_operator(layout, "ShaderNodeTexWave")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
self.node_operator(layout, "ShaderNodeTexWhiteNoise")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_vector(Menu):
|
class NODE_MT_shader_node_vector_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_vector"
|
|
||||||
bl_label = "Vector"
|
bl_label = "Vector"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeBump")
|
self.node_operator(layout, "ShaderNodeBump")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeDisplacement")
|
self.node_operator(layout, "ShaderNodeDisplacement")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeMapping")
|
self.node_operator(layout, "ShaderNodeMapping")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeNormal")
|
self.node_operator(layout, "ShaderNodeNormal")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeNormalMap")
|
self.node_operator(layout, "ShaderNodeNormalMap")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeRadialTiling")
|
self.node_operator(layout, "ShaderNodeRadialTiling")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
self.node_operator(layout, "ShaderNodeVectorCurve")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorDisplacement")
|
self.node_operator(layout, "ShaderNodeVectorDisplacement")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
self.node_operator(layout, "ShaderNodeVectorRotate")
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorTransform")
|
self.node_operator(layout, "ShaderNodeVectorTransform")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_script(Menu):
|
class NODE_MT_shader_node_script_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_script"
|
|
||||||
bl_label = "Script"
|
bl_label = "Script"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_node_type(layout, "ShaderNodeScript")
|
self.node_operator(layout, "ShaderNodeScript")
|
||||||
|
|
||||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
self.draw_assets_for_catalog(layout, self.bl_label)
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_shader_group(Menu):
|
class NODE_MT_shader_node_utilities_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_shader_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_category_shader_utilities(Menu):
|
|
||||||
bl_idname = "NODE_MT_category_shader_utilities"
|
|
||||||
bl_label = "Utilities"
|
bl_label = "Utilities"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
node_add_menu.add_repeat_zone(layout, label="Repeat")
|
self.repeat_zone(layout, label="Repeat")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_closure_zone(layout, label="Closure")
|
self.closure_zone(layout, label="Closure")
|
||||||
node_add_menu.add_node_type(layout, "NodeEvaluateClosure")
|
self.node_operator(layout, "NodeEvaluateClosure")
|
||||||
node_add_menu.add_node_type(layout, "NodeCombineBundle")
|
self.node_operator(layout, "NodeCombineBundle")
|
||||||
node_add_menu.add_node_type(layout, "NodeSeparateBundle")
|
self.node_operator(layout, "NodeSeparateBundle")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_shader_node_add_all(Menu):
|
class NODE_MT_shader_node_all_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_shader_node_add_all"
|
bl_label = ""
|
||||||
bl_label = "Add"
|
menu_path = "Root"
|
||||||
bl_translation_context = i18n_contexts.operator_default
|
bl_translation_context = i18n_contexts.operator_default
|
||||||
|
|
||||||
def draw(self, _context):
|
# NOTE: Menus are looked up via their label, this is so that both the Add
|
||||||
|
# & Swap menus can share the same layout while each using their
|
||||||
|
# corresponding menus
|
||||||
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_shader_input")
|
self.draw_menu(layout, "Input")
|
||||||
layout.menu("NODE_MT_category_shader_output")
|
self.draw_menu(layout, "Output")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_shader_color")
|
self.draw_menu(layout, "Color")
|
||||||
layout.menu("NODE_MT_category_shader_converter")
|
self.draw_menu(layout, "Converter")
|
||||||
layout.menu("NODE_MT_category_shader_shader")
|
self.draw_menu(layout, "Shader")
|
||||||
layout.menu("NODE_MT_category_shader_texture")
|
self.draw_menu(layout, "Texture")
|
||||||
layout.menu("NODE_MT_category_shader_vector")
|
self.draw_menu(layout, "Vector")
|
||||||
layout.menu("NODE_MT_category_shader_utilities")
|
self.draw_menu(layout, "Utilities")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_shader_script")
|
self.draw_menu(layout, "Script")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_shader_group")
|
self.draw_menu(layout, "Group")
|
||||||
layout.menu("NODE_MT_category_layout")
|
self.draw_menu(layout, "Layout")
|
||||||
|
|
||||||
node_add_menu.draw_root_assets(layout)
|
self.draw_root_assets(layout)
|
||||||
|
|
||||||
|
|
||||||
|
add_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_category_shader_input": NODE_MT_shader_node_input_base,
|
||||||
|
"NODE_MT_category_shader_output": NODE_MT_shader_node_output_base,
|
||||||
|
"NODE_MT_category_shader_color": NODE_MT_shader_node_color_base,
|
||||||
|
"NODE_MT_category_shader_converter": NODE_MT_shader_node_converter_base,
|
||||||
|
"NODE_MT_category_shader_shader": NODE_MT_shader_node_shader_base,
|
||||||
|
"NODE_MT_category_shader_texture": NODE_MT_shader_node_texture_base,
|
||||||
|
"NODE_MT_category_shader_vector": NODE_MT_shader_node_vector_base,
|
||||||
|
"NODE_MT_category_shader_script": NODE_MT_shader_node_script_base,
|
||||||
|
"NODE_MT_category_shader_utilities": NODE_MT_shader_node_utilities_base,
|
||||||
|
"NODE_MT_shader_node_add_all": NODE_MT_shader_node_all_base,
|
||||||
|
}
|
||||||
|
add_menus = node_add_menu.generate_menus(
|
||||||
|
add_menus,
|
||||||
|
template=node_add_menu.AddNodeMenu,
|
||||||
|
base_dict=node_add_menu.add_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
swap_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_shader_node_input_swap": NODE_MT_shader_node_input_base,
|
||||||
|
"NODE_MT_shader_node_output_swap": NODE_MT_shader_node_output_base,
|
||||||
|
"NODE_MT_shader_node_color_swap": NODE_MT_shader_node_color_base,
|
||||||
|
"NODE_MT_shader_node_converter_swap": NODE_MT_shader_node_converter_base,
|
||||||
|
"NODE_MT_shader_node_shader_swap": NODE_MT_shader_node_shader_base,
|
||||||
|
"NODE_MT_shader_node_texture_swap": NODE_MT_shader_node_texture_base,
|
||||||
|
"NODE_MT_shader_node_vector_swap": NODE_MT_shader_node_vector_base,
|
||||||
|
"NODE_MT_shader_node_script_swap": NODE_MT_shader_node_script_base,
|
||||||
|
"NODE_MT_shader_node_utilities_swap": NODE_MT_shader_node_utilities_base,
|
||||||
|
"NODE_MT_shader_node_swap_all": NODE_MT_shader_node_all_base,
|
||||||
|
}
|
||||||
|
swap_menus = node_add_menu.generate_menus(
|
||||||
|
swap_menus,
|
||||||
|
template=node_add_menu.SwapNodeMenu,
|
||||||
|
base_dict=node_add_menu.swap_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
NODE_MT_shader_node_add_all,
|
*add_menus,
|
||||||
NODE_MT_category_shader_input,
|
*swap_menus,
|
||||||
NODE_MT_category_shader_output,
|
|
||||||
NODE_MT_category_shader_color,
|
|
||||||
NODE_MT_category_shader_converter,
|
|
||||||
NODE_MT_category_shader_shader,
|
|
||||||
NODE_MT_category_shader_texture,
|
|
||||||
NODE_MT_category_shader_vector,
|
|
||||||
NODE_MT_category_shader_script,
|
|
||||||
NODE_MT_category_shader_group,
|
|
||||||
NODE_MT_category_shader_utilities,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,136 +9,154 @@ from bpy.app.translations import (
|
|||||||
from bl_ui import node_add_menu
|
from bl_ui import node_add_menu
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_input(Menu):
|
class NODE_MT_texture_node_input_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_input"
|
|
||||||
bl_label = "Input"
|
bl_label = "Input"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeCoordinates")
|
self.node_operator(layout, "TextureNodeCoordinates")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeCurveTime")
|
self.node_operator(layout, "TextureNodeCurveTime")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeImage")
|
self.node_operator(layout, "TextureNodeImage")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexture")
|
self.node_operator(layout, "TextureNodeTexture")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_output(Menu):
|
class NODE_MT_texture_node_output_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_output"
|
|
||||||
bl_label = "Output"
|
bl_label = "Output"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeOutput")
|
self.node_operator(layout, "TextureNodeOutput")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeViewer")
|
self.node_operator(layout, "TextureNodeViewer")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_color(Menu):
|
class NODE_MT_texture_node_color_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_color"
|
|
||||||
bl_label = "Color"
|
bl_label = "Color"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeHueSaturation")
|
self.node_operator(layout, "TextureNodeHueSaturation")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeInvert")
|
self.node_operator(layout, "TextureNodeInvert")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeMixRGB")
|
self.node_operator(layout, "TextureNodeMixRGB")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeCurveRGB")
|
self.node_operator(layout, "TextureNodeCurveRGB")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeCombineColor")
|
self.node_operator(layout, "TextureNodeCombineColor")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeSeparateColor")
|
self.node_operator(layout, "TextureNodeSeparateColor")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_converter(Menu):
|
class NODE_MT_texture_node_converter_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_converter"
|
|
||||||
bl_label = "Converter"
|
bl_label = "Converter"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeValToRGB")
|
self.node_operator(layout, "TextureNodeValToRGB")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeDistance")
|
self.node_operator(layout, "TextureNodeDistance")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeMath")
|
self.node_operator(layout, "TextureNodeMath")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeRGBToBW")
|
self.node_operator(layout, "TextureNodeRGBToBW")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeValToNor")
|
self.node_operator(layout, "TextureNodeValToNor")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_distort(Menu):
|
class NODE_MT_texture_node_distort_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_distort"
|
|
||||||
bl_label = "Distort"
|
bl_label = "Distort"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeAt")
|
self.node_operator(layout, "TextureNodeAt")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeRotate")
|
self.node_operator(layout, "TextureNodeRotate")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeScale")
|
self.node_operator(layout, "TextureNodeScale")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTranslate")
|
self.node_operator(layout, "TextureNodeTranslate")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_pattern(Menu):
|
class NODE_MT_texture_node_pattern_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_pattern"
|
|
||||||
bl_label = "Pattern"
|
bl_label = "Pattern"
|
||||||
bl_translation_context = i18n_contexts.id_texture
|
bl_translation_context = i18n_contexts.id_texture
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeBricks")
|
self.node_operator(layout, "TextureNodeBricks")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeChecker")
|
self.node_operator(layout, "TextureNodeChecker")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_texture(Menu):
|
class NODE_MT_texture_node_texture_base(Menu):
|
||||||
bl_idname = "NODE_MT_category_texture_texture"
|
|
||||||
bl_label = "Texture"
|
bl_label = "Texture"
|
||||||
|
|
||||||
def draw(self, _context):
|
def draw(self, _context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexBlend")
|
self.node_operator(layout, "TextureNodeTexBlend")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexClouds")
|
self.node_operator(layout, "TextureNodeTexClouds")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexDistNoise")
|
self.node_operator(layout, "TextureNodeTexDistNoise")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexMagic")
|
self.node_operator(layout, "TextureNodeTexMagic")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexMarble")
|
self.node_operator(layout, "TextureNodeTexMarble")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexMusgrave")
|
self.node_operator(layout, "TextureNodeTexMusgrave")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexNoise")
|
self.node_operator(layout, "TextureNodeTexNoise")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexStucci")
|
self.node_operator(layout, "TextureNodeTexStucci")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexVoronoi")
|
self.node_operator(layout, "TextureNodeTexVoronoi")
|
||||||
node_add_menu.add_node_type(layout, "TextureNodeTexWood")
|
self.node_operator(layout, "TextureNodeTexWood")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_category_texture_group(Menu):
|
class NODE_MT_texture_node_all_base(node_add_menu.NodeMenu):
|
||||||
bl_idname = "NODE_MT_category_texture_group"
|
bl_label = ""
|
||||||
bl_label = "Group"
|
menu_path = "Root"
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
node_add_menu.draw_node_group_add_menu(context, layout)
|
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_texture_node_add_all(Menu):
|
|
||||||
bl_idname = "NODE_MT_texture_node_add_all"
|
|
||||||
bl_label = "Add"
|
|
||||||
bl_translation_context = i18n_contexts.operator_default
|
bl_translation_context = i18n_contexts.operator_default
|
||||||
|
|
||||||
def draw(self, _context):
|
# NOTE: Menus are looked up via their label, this is so that both the Add
|
||||||
|
# & Swap menus can share the same layout while each using their
|
||||||
|
# corresponding menus
|
||||||
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.menu("NODE_MT_category_texture_input")
|
self.draw_menu(layout, "Input")
|
||||||
layout.menu("NODE_MT_category_texture_output")
|
self.draw_menu(layout, "Output")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_texture_color")
|
self.draw_menu(layout, "Color")
|
||||||
layout.menu("NODE_MT_category_texture_converter")
|
self.draw_menu(layout, "Converter")
|
||||||
layout.menu("NODE_MT_category_texture_distort")
|
self.draw_menu(layout, "Distort")
|
||||||
layout.menu("NODE_MT_category_texture_pattern")
|
self.draw_menu(layout, "Pattern")
|
||||||
layout.menu("NODE_MT_category_texture_texture")
|
self.draw_menu(layout, "Texture")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.menu("NODE_MT_category_texture_group")
|
self.draw_menu(layout, "Group")
|
||||||
layout.menu("NODE_MT_category_layout")
|
self.draw_menu(layout, "Layout")
|
||||||
|
|
||||||
|
self.draw_root_assets(layout)
|
||||||
|
|
||||||
|
|
||||||
|
add_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_category_texture_input": NODE_MT_texture_node_input_base,
|
||||||
|
"NODE_MT_category_texture_output": NODE_MT_texture_node_output_base,
|
||||||
|
"NODE_MT_category_texture_color": NODE_MT_texture_node_color_base,
|
||||||
|
"NODE_MT_category_texture_converter": NODE_MT_texture_node_converter_base,
|
||||||
|
"NODE_MT_category_texture_distort": NODE_MT_texture_node_distort_base,
|
||||||
|
"NODE_MT_category_texture_pattern": NODE_MT_texture_node_pattern_base,
|
||||||
|
"NODE_MT_category_texture_texture": NODE_MT_texture_node_texture_base,
|
||||||
|
"NODE_MT_texture_node_add_all": NODE_MT_texture_node_all_base,
|
||||||
|
}
|
||||||
|
add_menus = node_add_menu.generate_menus(
|
||||||
|
add_menus,
|
||||||
|
template=node_add_menu.AddNodeMenu,
|
||||||
|
base_dict=node_add_menu.add_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
swap_menus = {
|
||||||
|
# menu bl_idname: baseclass
|
||||||
|
"NODE_MT_texture_node_input_swap": NODE_MT_texture_node_input_base,
|
||||||
|
"NODE_MT_texture_node_output_swap": NODE_MT_texture_node_output_base,
|
||||||
|
"NODE_MT_texture_node_color_swap": NODE_MT_texture_node_color_base,
|
||||||
|
"NODE_MT_texture_node_converter_swap": NODE_MT_texture_node_converter_base,
|
||||||
|
"NODE_MT_texture_node_distort_swap": NODE_MT_texture_node_distort_base,
|
||||||
|
"NODE_MT_texture_node_pattern_swap": NODE_MT_texture_node_pattern_base,
|
||||||
|
"NODE_MT_texture_node_texture_swap": NODE_MT_texture_node_texture_base,
|
||||||
|
"NODE_MT_texture_node_swap_all": NODE_MT_texture_node_all_base,
|
||||||
|
}
|
||||||
|
swap_menus = node_add_menu.generate_menus(
|
||||||
|
swap_menus,
|
||||||
|
template=node_add_menu.SwapNodeMenu,
|
||||||
|
base_dict=node_add_menu.swap_base_pathing_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
NODE_MT_texture_node_add_all,
|
*add_menus,
|
||||||
NODE_MT_category_texture_input,
|
*swap_menus,
|
||||||
NODE_MT_category_texture_output,
|
|
||||||
NODE_MT_category_texture_color,
|
|
||||||
NODE_MT_category_texture_converter,
|
|
||||||
NODE_MT_category_texture_distort,
|
|
||||||
NODE_MT_category_texture_pattern,
|
|
||||||
NODE_MT_category_texture_texture,
|
|
||||||
NODE_MT_category_texture_group,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from bpy.app.translations import (
|
|||||||
pgettext_iface as iface_,
|
pgettext_iface as iface_,
|
||||||
contexts as i18n_contexts,
|
contexts as i18n_contexts,
|
||||||
)
|
)
|
||||||
from bl_ui import anim
|
from bl_ui import anim, node_add_menu
|
||||||
from bl_ui.utils import PresetPanel
|
from bl_ui.utils import PresetPanel
|
||||||
from bl_ui.properties_grease_pencil_common import (
|
from bl_ui.properties_grease_pencil_common import (
|
||||||
AnnotationDataPanel,
|
AnnotationDataPanel,
|
||||||
@@ -263,10 +263,11 @@ class NODE_MT_editor_menus(Menu):
|
|||||||
layout.menu("NODE_MT_view")
|
layout.menu("NODE_MT_view")
|
||||||
layout.menu("NODE_MT_select")
|
layout.menu("NODE_MT_select")
|
||||||
layout.menu("NODE_MT_add")
|
layout.menu("NODE_MT_add")
|
||||||
|
layout.menu("NODE_MT_swap")
|
||||||
layout.menu("NODE_MT_node")
|
layout.menu("NODE_MT_node")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_add(Menu):
|
class NODE_MT_add(node_add_menu.AddNodeMenu):
|
||||||
bl_space_type = 'NODE_EDITOR'
|
bl_space_type = 'NODE_EDITOR'
|
||||||
bl_label = "Add"
|
bl_label = "Add"
|
||||||
bl_translation_context = i18n_contexts.operator_default
|
bl_translation_context = i18n_contexts.operator_default
|
||||||
@@ -298,6 +299,33 @@ class NODE_MT_add(Menu):
|
|||||||
nodeitems_utils.draw_node_categories_menu(self, context)
|
nodeitems_utils.draw_node_categories_menu(self, context)
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_MT_swap(node_add_menu.SwapNodeMenu):
|
||||||
|
bl_space_type = 'NODE_EDITOR'
|
||||||
|
bl_label = "Swap"
|
||||||
|
bl_translation_context = i18n_contexts.operator_default
|
||||||
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
if layout.operator_context == 'EXEC_REGION_WIN':
|
||||||
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||||
|
layout.operator("WM_OT_search_single_menu", text="Search...", icon='VIEWZOOM').menu_idname = "NODE_MT_swap"
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||||
|
|
||||||
|
snode = context.space_data
|
||||||
|
if snode.tree_type == 'GeometryNodeTree':
|
||||||
|
layout.menu_contents("NODE_MT_geometry_node_swap_all")
|
||||||
|
elif snode.tree_type == 'CompositorNodeTree':
|
||||||
|
layout.menu_contents("NODE_MT_compositor_node_swap_all")
|
||||||
|
elif snode.tree_type == 'ShaderNodeTree':
|
||||||
|
layout.menu_contents("NODE_MT_shader_node_swap_all")
|
||||||
|
elif snode.tree_type == 'TextureNodeTree':
|
||||||
|
layout.menu_contents("NODE_MT_texture_node_swap_all")
|
||||||
|
|
||||||
|
|
||||||
class NODE_MT_view(Menu):
|
class NODE_MT_view(Menu):
|
||||||
bl_label = "View"
|
bl_label = "View"
|
||||||
|
|
||||||
@@ -1216,13 +1244,14 @@ classes = (
|
|||||||
NODE_HT_header,
|
NODE_HT_header,
|
||||||
NODE_MT_editor_menus,
|
NODE_MT_editor_menus,
|
||||||
NODE_MT_add,
|
NODE_MT_add,
|
||||||
NODE_MT_view,
|
NODE_MT_swap,
|
||||||
NODE_MT_select,
|
NODE_MT_select,
|
||||||
NODE_MT_node,
|
NODE_MT_node,
|
||||||
NODE_MT_node_color_context_menu,
|
NODE_MT_node_color_context_menu,
|
||||||
NODE_MT_context_menu_show_hide_menu,
|
NODE_MT_context_menu_show_hide_menu,
|
||||||
NODE_MT_context_menu_select_menu,
|
NODE_MT_context_menu_select_menu,
|
||||||
NODE_MT_context_menu,
|
NODE_MT_context_menu,
|
||||||
|
NODE_MT_view,
|
||||||
NODE_MT_view_pie,
|
NODE_MT_view_pie,
|
||||||
NODE_PT_material_slots,
|
NODE_PT_material_slots,
|
||||||
NODE_PT_geometry_node_tool_object_types,
|
NODE_PT_geometry_node_tool_object_types,
|
||||||
|
|||||||
@@ -132,14 +132,14 @@ class MyCustomNode(MyCustomTreeNode, Node):
|
|||||||
return "I am a custom node"
|
return "I am a custom node"
|
||||||
|
|
||||||
|
|
||||||
# Add custom nodes to the Add menu.
|
# Add custom nodes to the Add & Swap menu.
|
||||||
def draw_add_menu(self, context):
|
def draw_add_menu(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if context.space_data.tree_type != MyCustomTree.bl_idname:
|
if context.space_data.tree_type != MyCustomTree.bl_idname:
|
||||||
# Avoid adding nodes to built-in node tree
|
# Avoid adding nodes to built-in node tree
|
||||||
return
|
return
|
||||||
# Add nodes to the layout. Can use submenus, separators, etc. as in any other menu.
|
# Add nodes to the layout. Can use submenus, separators, etc. as in any other menu.
|
||||||
node_add_menu.add_node_type(layout, "CustomNodeType")
|
self.node_operator(layout, "CustomNodeType")
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
@@ -156,10 +156,12 @@ def register():
|
|||||||
register_class(cls)
|
register_class(cls)
|
||||||
|
|
||||||
bpy.types.NODE_MT_add.append(draw_add_menu)
|
bpy.types.NODE_MT_add.append(draw_add_menu)
|
||||||
|
bpy.types.NODE_MT_swap.append(draw_add_menu)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.types.NODE_MT_add.remove(draw_add_menu)
|
bpy.types.NODE_MT_add.remove(draw_add_menu)
|
||||||
|
bpy.types.NODE_MT_swap.remove(draw_add_menu)
|
||||||
|
|
||||||
from bpy.utils import unregister_class
|
from bpy.utils import unregister_class
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
|
|||||||
@@ -152,4 +152,15 @@ void draw_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
|
|||||||
col->menu(menu_name, IFACE_(item.get_name()), ICON_NONE);
|
col->menu(menu_name, IFACE_(item.get_name()), ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_node_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
|
||||||
|
const StringRefNull operator_id,
|
||||||
|
const StringRefNull menu_name,
|
||||||
|
uiLayout &layout)
|
||||||
|
{
|
||||||
|
uiLayout *col = &layout.column(false);
|
||||||
|
col->context_string_set("asset_catalog_path", item.catalog_path().c_str());
|
||||||
|
col->context_string_set("operator_id", operator_id);
|
||||||
|
col->menu(menu_name, IFACE_(item.get_name()), ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::ed::asset
|
} // namespace blender::ed::asset
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ void draw_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
|
|||||||
StringRefNull menu_name,
|
StringRefNull menu_name,
|
||||||
uiLayout &layout);
|
uiLayout &layout);
|
||||||
|
|
||||||
|
void draw_node_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
|
||||||
|
StringRefNull operator_id,
|
||||||
|
StringRefNull menu_name,
|
||||||
|
uiLayout &layout);
|
||||||
|
|
||||||
void operator_asset_reference_props_set(const asset_system::AssetRepresentation &asset,
|
void operator_asset_reference_props_set(const asset_system::AssetRepresentation &asset,
|
||||||
PointerRNA &ptr);
|
PointerRNA &ptr);
|
||||||
bool operator_asset_reference_props_is_set(PointerRNA &ptr);
|
bool operator_asset_reference_props_is_set(PointerRNA &ptr);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "ED_node_c.hh"
|
#include "ED_node_c.hh"
|
||||||
|
|
||||||
|
#include "UI_interface_layout.hh"
|
||||||
|
|
||||||
struct SpaceNode;
|
struct SpaceNode;
|
||||||
struct ARegion;
|
struct ARegion;
|
||||||
struct Main;
|
struct Main;
|
||||||
@@ -136,7 +138,8 @@ bool node_editor_is_for_geometry_nodes_modifier(const SpaceNode &snode,
|
|||||||
|
|
||||||
void ui_template_node_asset_menu_items(uiLayout &layout,
|
void ui_template_node_asset_menu_items(uiLayout &layout,
|
||||||
const bContext &C,
|
const bContext &C,
|
||||||
StringRef catalog_path);
|
StringRef catalog_path,
|
||||||
|
const NodeAssetMenuOperatorType operator_type);
|
||||||
|
|
||||||
/** See #SpaceNode_Runtime::node_can_sync_states. */
|
/** See #SpaceNode_Runtime::node_can_sync_states. */
|
||||||
Map<int, bool> &node_can_sync_cache_get(SpaceNode &snode);
|
Map<int, bool> &node_can_sync_cache_get(SpaceNode &snode);
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ enum class LayoutSeparatorType : int8_t {
|
|||||||
Line,
|
Line,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class NodeAssetMenuOperatorType : int8_t {
|
||||||
|
Add,
|
||||||
|
Swap,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: `uiLayout` properties should be considered private outside `interface_layout.cc`,
|
* NOTE: `uiLayout` properties should be considered private outside `interface_layout.cc`,
|
||||||
* incoming refactors would remove public access and add public read/write function methods.
|
* incoming refactors would remove public access and add public read/write function methods.
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ static Set<StringRef> get_builtin_menus(const int tree_type)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
static void node_catalog_assets_draw(const bContext *C, Menu *menu)
|
||||||
{
|
{
|
||||||
SpaceNode &snode = *CTX_wm_space_node(C);
|
SpaceNode &snode = *CTX_wm_space_node(C);
|
||||||
const bNodeTree *edit_tree = snode.edittree;
|
const bNodeTree *edit_tree = snode.edittree;
|
||||||
@@ -172,6 +172,12 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
|||||||
if (!menu_path) {
|
if (!menu_path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::optional<blender::StringRefNull> operator_id = CTX_data_string_get(C, "operator_id");
|
||||||
|
if (!operator_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(
|
const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(
|
||||||
menu_path->c_str());
|
menu_path->c_str());
|
||||||
const asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(
|
const asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(
|
||||||
@@ -190,7 +196,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
|||||||
layout->separator();
|
layout->separator();
|
||||||
add_separator = false;
|
add_separator = false;
|
||||||
}
|
}
|
||||||
PointerRNA op_ptr = layout->op("NODE_OT_add_group_asset",
|
PointerRNA op_ptr = layout->op(*operator_id,
|
||||||
IFACE_(asset->get_name()),
|
IFACE_(asset->get_name()),
|
||||||
ICON_NONE,
|
ICON_NONE,
|
||||||
wm::OpCallContext::InvokeRegionWin,
|
wm::OpCallContext::InvokeRegionWin,
|
||||||
@@ -208,17 +214,23 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
|||||||
layout->separator();
|
layout->separator();
|
||||||
add_separator = false;
|
add_separator = false;
|
||||||
}
|
}
|
||||||
asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
|
asset::draw_node_menu_for_catalog(item, *operator_id, "NODE_MT_node_catalog_assets", *layout);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void node_add_unassigned_assets_draw(const bContext *C, Menu *menu)
|
static void node_unassigned_assets_draw(const bContext *C, Menu *menu)
|
||||||
{
|
{
|
||||||
SpaceNode &snode = *CTX_wm_space_node(C);
|
SpaceNode &snode = *CTX_wm_space_node(C);
|
||||||
const bNodeTree *edit_tree = snode.edittree;
|
const bNodeTree *edit_tree = snode.edittree;
|
||||||
if (!edit_tree) {
|
if (!edit_tree) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::optional<blender::StringRefNull> operator_id = CTX_data_string_get(C, "operator_id");
|
||||||
|
if (!operator_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!snode.runtime->assets_for_menu) {
|
if (!snode.runtime->assets_for_menu) {
|
||||||
snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
|
snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
|
||||||
build_catalog_tree(*C, *edit_tree));
|
build_catalog_tree(*C, *edit_tree));
|
||||||
@@ -226,7 +238,7 @@ static void node_add_unassigned_assets_draw(const bContext *C, Menu *menu)
|
|||||||
}
|
}
|
||||||
asset::AssetItemTree &tree = *snode.runtime->assets_for_menu;
|
asset::AssetItemTree &tree = *snode.runtime->assets_for_menu;
|
||||||
for (const asset_system::AssetRepresentation *asset : tree.unassigned_assets) {
|
for (const asset_system::AssetRepresentation *asset : tree.unassigned_assets) {
|
||||||
PointerRNA op_ptr = menu->layout->op("NODE_OT_add_group_asset",
|
PointerRNA op_ptr = menu->layout->op(*operator_id,
|
||||||
IFACE_(asset->get_name()),
|
IFACE_(asset->get_name()),
|
||||||
ICON_NONE,
|
ICON_NONE,
|
||||||
wm::OpCallContext::InvokeRegionWin,
|
wm::OpCallContext::InvokeRegionWin,
|
||||||
@@ -235,7 +247,7 @@ static void node_add_unassigned_assets_draw(const bContext *C, Menu *menu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_root_catalogs_draw(const bContext *C, Menu *menu)
|
static void root_catalogs_draw(const bContext *C, Menu *menu, const StringRefNull operator_id)
|
||||||
{
|
{
|
||||||
SpaceNode &snode = *CTX_wm_space_node(C);
|
SpaceNode &snode = *CTX_wm_space_node(C);
|
||||||
uiLayout *layout = menu->layout;
|
uiLayout *layout = menu->layout;
|
||||||
@@ -264,33 +276,49 @@ static void add_root_catalogs_draw(const bContext *C, Menu *menu)
|
|||||||
|
|
||||||
tree.catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
|
tree.catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
|
||||||
if (!all_builtin_menus.contains_as(item.catalog_path().str())) {
|
if (!all_builtin_menus.contains_as(item.catalog_path().str())) {
|
||||||
asset::draw_menu_for_catalog(item, "NODE_MT_node_add_catalog_assets", *layout);
|
asset::draw_node_menu_for_catalog(item, operator_id, "NODE_MT_node_catalog_assets", *layout);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!tree.unassigned_assets.is_empty()) {
|
if (!tree.unassigned_assets.is_empty()) {
|
||||||
layout->separator();
|
layout->separator();
|
||||||
layout->menu("NODE_MT_node_add_unassigned_assets", IFACE_("Unassigned"), ICON_FILE_HIDDEN);
|
layout->menu("NODE_MT_node_unassigned_assets", IFACE_("Unassigned"), ICON_FILE_HIDDEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuType add_catalog_assets_menu_type()
|
static void add_root_catalogs_draw(const bContext *C, Menu *menu)
|
||||||
|
{
|
||||||
|
const StringRefNull operator_id = "NODE_OT_add_group_asset";
|
||||||
|
|
||||||
|
menu->layout->context_string_set("operator_id", operator_id);
|
||||||
|
root_catalogs_draw(C, menu, operator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swap_root_catalogs_draw(const bContext *C, Menu *menu)
|
||||||
|
{
|
||||||
|
const StringRefNull operator_id = "NODE_OT_swap_group_asset";
|
||||||
|
|
||||||
|
menu->layout->context_string_set("operator_id", operator_id);
|
||||||
|
root_catalogs_draw(C, menu, operator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuType catalog_assets_menu_type()
|
||||||
{
|
{
|
||||||
MenuType type{};
|
MenuType type{};
|
||||||
STRNCPY_UTF8(type.idname, "NODE_MT_node_add_catalog_assets");
|
STRNCPY_UTF8(type.idname, "NODE_MT_node_catalog_assets");
|
||||||
type.poll = node_add_menu_poll;
|
type.poll = node_add_menu_poll;
|
||||||
type.draw = node_add_catalog_assets_draw;
|
type.draw = node_catalog_assets_draw;
|
||||||
type.listener = asset::list::asset_reading_region_listen_fn;
|
type.listener = asset::list::asset_reading_region_listen_fn;
|
||||||
type.flag = MenuTypeFlag::ContextDependent;
|
type.flag = MenuTypeFlag::ContextDependent;
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuType add_unassigned_assets_menu_type()
|
MenuType unassigned_assets_menu_type()
|
||||||
{
|
{
|
||||||
MenuType type{};
|
MenuType type{};
|
||||||
STRNCPY_UTF8(type.idname, "NODE_MT_node_add_unassigned_assets");
|
STRNCPY_UTF8(type.idname, "NODE_MT_node_unassigned_assets");
|
||||||
type.poll = node_add_menu_poll;
|
type.poll = node_add_menu_poll;
|
||||||
type.draw = node_add_unassigned_assets_draw;
|
type.draw = node_unassigned_assets_draw;
|
||||||
type.listener = asset::list::asset_reading_region_listen_fn;
|
type.listener = asset::list::asset_reading_region_listen_fn;
|
||||||
type.flag = MenuTypeFlag::ContextDependent;
|
type.flag = MenuTypeFlag::ContextDependent;
|
||||||
type.description = N_(
|
type.description = N_(
|
||||||
@@ -309,9 +337,20 @@ MenuType add_root_catalogs_menu_type()
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MenuType swap_root_catalogs_menu_type()
|
||||||
|
{
|
||||||
|
MenuType type{};
|
||||||
|
STRNCPY_UTF8(type.idname, "NODE_MT_node_swap_root_catalogs");
|
||||||
|
type.poll = node_add_menu_poll;
|
||||||
|
type.draw = swap_root_catalogs_draw;
|
||||||
|
type.listener = asset::list::asset_reading_region_listen_fn;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
void ui_template_node_asset_menu_items(uiLayout &layout,
|
void ui_template_node_asset_menu_items(uiLayout &layout,
|
||||||
const bContext &C,
|
const bContext &C,
|
||||||
const StringRef catalog_path)
|
const StringRef catalog_path,
|
||||||
|
const NodeAssetMenuOperatorType operator_type)
|
||||||
{
|
{
|
||||||
SpaceNode &snode = *CTX_wm_space_node(&C);
|
SpaceNode &snode = *CTX_wm_space_node(&C);
|
||||||
if (snode.runtime->assets_for_menu == nullptr) {
|
if (snode.runtime->assets_for_menu == nullptr) {
|
||||||
@@ -322,9 +361,21 @@ void ui_template_node_asset_menu_items(uiLayout &layout,
|
|||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringRef operator_id;
|
||||||
|
|
||||||
|
switch (operator_type) {
|
||||||
|
case NodeAssetMenuOperatorType::Swap:
|
||||||
|
operator_id = "NODE_OT_swap_group_asset";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
operator_id = "NODE_OT_add_group_asset";
|
||||||
|
}
|
||||||
|
|
||||||
uiLayout *col = &layout.column(false);
|
uiLayout *col = &layout.column(false);
|
||||||
col->context_string_set("asset_catalog_path", item->catalog_path().str());
|
col->context_string_set("asset_catalog_path", item->catalog_path().str());
|
||||||
col->menu_contents("NODE_MT_node_add_catalog_assets");
|
col->context_string_set("operator_id", operator_id);
|
||||||
|
col->menu_contents("NODE_MT_node_catalog_assets");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::ed::space_node
|
} // namespace blender::ed::space_node
|
||||||
|
|||||||
@@ -361,6 +361,27 @@ static bool node_add_group_poll(bContext *C)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool node_swap_group_poll(bContext *C)
|
||||||
|
{
|
||||||
|
if (!ED_operator_node_editable(C)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const SpaceNode *snode = CTX_wm_space_node(C);
|
||||||
|
if (snode->edittree->type == NTREE_CUSTOM) {
|
||||||
|
CTX_wm_operator_poll_msg_set(
|
||||||
|
C, "Adding node groups isn't supported for custom (Python defined) node trees");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Vector<PointerRNA> selected_nodes;
|
||||||
|
selected_nodes = CTX_data_collection_get(C, "selected_nodes");
|
||||||
|
|
||||||
|
if (selected_nodes.size() <= 0) {
|
||||||
|
CTX_wm_operator_poll_msg_set(C, "No nodes selected.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static wmOperatorStatus node_add_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
static wmOperatorStatus node_add_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
{
|
{
|
||||||
ARegion *region = CTX_wm_region(C);
|
ARegion *region = CTX_wm_region(C);
|
||||||
@@ -490,6 +511,78 @@ static wmOperatorStatus node_add_group_asset_invoke(bContext *C,
|
|||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wmOperatorStatus node_swap_group_asset_invoke(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const wmEvent *event)
|
||||||
|
{
|
||||||
|
ARegion ®ion = *CTX_wm_region(C);
|
||||||
|
Main &bmain = *CTX_data_main(C);
|
||||||
|
SpaceNode &snode = *CTX_wm_space_node(C);
|
||||||
|
bNodeTree &ntree = *snode.edittree;
|
||||||
|
|
||||||
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
asset::operator_asset_reference_props_get_asset_from_all_library(*C, *op->ptr, op->reports);
|
||||||
|
if (!asset) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
|
||||||
|
asset::asset_local_id_ensure_imported(bmain, *asset));
|
||||||
|
|
||||||
|
/* Convert mouse coordinates to v2d space. */
|
||||||
|
UI_view2d_region_to_view(®ion.v2d,
|
||||||
|
event->mval[0],
|
||||||
|
event->mval[1],
|
||||||
|
&snode.runtime->cursor[0],
|
||||||
|
&snode.runtime->cursor[1]);
|
||||||
|
|
||||||
|
snode.runtime->cursor /= UI_SCALE_FAC;
|
||||||
|
|
||||||
|
const StringRef node_idname = node_group_idname(C);
|
||||||
|
if (node_idname[0] == '\0') {
|
||||||
|
BKE_report(op->reports, RPT_WARNING, "Could not determine type of group node");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
wmOperatorType *ot = WM_operatortype_find("NODE_OT_swap_node", true);
|
||||||
|
BLI_assert(ot);
|
||||||
|
PointerRNA ptr;
|
||||||
|
PointerRNA itemptr;
|
||||||
|
WM_operator_properties_create_ptr(&ptr, ot);
|
||||||
|
RNA_string_set(&ptr, "type", node_idname.data());
|
||||||
|
|
||||||
|
/* Assign node group via operator.settings. This needs to be done here so that NODE_OT_swap_node
|
||||||
|
* can preserve matching links */
|
||||||
|
/* Assigning it in the for-loop along with the other node group properties causes the links to
|
||||||
|
* not be preserved*/
|
||||||
|
RNA_collection_add(&ptr, "settings", &itemptr);
|
||||||
|
RNA_string_set(&itemptr, "name", "node_tree");
|
||||||
|
|
||||||
|
std::string setting_value = "bpy.data.node_groups[\"" +
|
||||||
|
std::string(BKE_id_name(node_group->id)) + "\"]";
|
||||||
|
RNA_string_set(&itemptr, "value", setting_value.c_str());
|
||||||
|
|
||||||
|
WM_operator_name_call_ptr(C, ot, wm::OpCallContext::InvokeDefault, &ptr, nullptr);
|
||||||
|
WM_operator_properties_free(&ptr);
|
||||||
|
|
||||||
|
for (bNode *group_node : get_selected_nodes(ntree)) {
|
||||||
|
STRNCPY_UTF8(group_node->name, BKE_id_name(node_group->id));
|
||||||
|
bke::node_unique_name(*snode.edittree, *group_node);
|
||||||
|
|
||||||
|
/* By default, don't show the data-block selector since it's not usually necessary for assets.
|
||||||
|
*/
|
||||||
|
group_node->flag &= ~NODE_OPTIONS;
|
||||||
|
group_node->width = node_group->default_group_node_width;
|
||||||
|
|
||||||
|
id_us_plus(group_node->id);
|
||||||
|
BKE_ntree_update_tag_node_property(&ntree, group_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_main_ensure_invariants(bmain);
|
||||||
|
WM_event_add_notifier(C, NC_NODE | NA_ADDED, nullptr);
|
||||||
|
DEG_relations_tag_update(&bmain);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string node_add_group_asset_get_description(bContext *C,
|
static std::string node_add_group_asset_get_description(bContext *C,
|
||||||
wmOperatorType * /*ot*/,
|
wmOperatorType * /*ot*/,
|
||||||
PointerRNA *ptr)
|
PointerRNA *ptr)
|
||||||
@@ -521,6 +614,21 @@ void NODE_OT_add_group_asset(wmOperatorType *ot)
|
|||||||
asset::operator_asset_reference_props_register(*ot->srna);
|
asset::operator_asset_reference_props_register(*ot->srna);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NODE_OT_swap_group_asset(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Swap Node Group Asset";
|
||||||
|
ot->description = "Swap selected nodes with the specified node group asset";
|
||||||
|
ot->idname = "NODE_OT_swap_group_asset";
|
||||||
|
|
||||||
|
ot->invoke = node_swap_group_asset_invoke;
|
||||||
|
ot->poll = node_swap_group_poll;
|
||||||
|
ot->get_description = node_add_group_asset_get_description;
|
||||||
|
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||||
|
|
||||||
|
asset::operator_asset_reference_props_register(*ot->srna);
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ void NODE_OT_add_mask(wmOperatorType *ot);
|
|||||||
void NODE_OT_add_material(wmOperatorType *ot);
|
void NODE_OT_add_material(wmOperatorType *ot);
|
||||||
void NODE_OT_add_color(wmOperatorType *ot);
|
void NODE_OT_add_color(wmOperatorType *ot);
|
||||||
void NODE_OT_add_import_node(wmOperatorType *ot);
|
void NODE_OT_add_import_node(wmOperatorType *ot);
|
||||||
|
void NODE_OT_swap_group_asset(wmOperatorType *ot);
|
||||||
void NODE_OT_new_node_tree(wmOperatorType *ot);
|
void NODE_OT_new_node_tree(wmOperatorType *ot);
|
||||||
void NODE_OT_new_compositing_node_group(wmOperatorType *ot);
|
void NODE_OT_new_compositing_node_group(wmOperatorType *ot);
|
||||||
void NODE_OT_add_group_input_node(wmOperatorType *ot);
|
void NODE_OT_add_group_input_node(wmOperatorType *ot);
|
||||||
@@ -444,10 +445,12 @@ void invoke_node_link_drag_add_menu(bContext &C,
|
|||||||
|
|
||||||
/* `add_menu_assets.cc` */
|
/* `add_menu_assets.cc` */
|
||||||
|
|
||||||
MenuType add_catalog_assets_menu_type();
|
MenuType catalog_assets_menu_type();
|
||||||
MenuType add_unassigned_assets_menu_type();
|
MenuType unassigned_assets_menu_type();
|
||||||
MenuType add_root_catalogs_menu_type();
|
MenuType add_root_catalogs_menu_type();
|
||||||
|
|
||||||
|
MenuType swap_root_catalogs_menu_type();
|
||||||
|
|
||||||
/* `node_sync_sockets.cc` */
|
/* `node_sync_sockets.cc` */
|
||||||
|
|
||||||
void NODE_OT_sockets_sync(wmOperatorType *ot);
|
void NODE_OT_sockets_sync(wmOperatorType *ot);
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ void node_operatortypes()
|
|||||||
WM_operatortype_append(NODE_OT_add_import_node);
|
WM_operatortype_append(NODE_OT_add_import_node);
|
||||||
WM_operatortype_append(NODE_OT_add_group_input_node);
|
WM_operatortype_append(NODE_OT_add_group_input_node);
|
||||||
|
|
||||||
|
WM_operatortype_append(NODE_OT_swap_group_asset);
|
||||||
|
|
||||||
WM_operatortype_append(NODE_OT_new_node_tree);
|
WM_operatortype_append(NODE_OT_new_node_tree);
|
||||||
WM_operatortype_append(NODE_OT_new_compositing_node_group);
|
WM_operatortype_append(NODE_OT_new_compositing_node_group);
|
||||||
|
|
||||||
|
|||||||
@@ -1884,9 +1884,10 @@ void ED_spacetype_node()
|
|||||||
art->draw = node_toolbar_region_draw;
|
art->draw = node_toolbar_region_draw;
|
||||||
BLI_addhead(&st->regiontypes, art);
|
BLI_addhead(&st->regiontypes, art);
|
||||||
|
|
||||||
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, add_catalog_assets_menu_type()));
|
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, catalog_assets_menu_type()));
|
||||||
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, add_unassigned_assets_menu_type()));
|
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, unassigned_assets_menu_type()));
|
||||||
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, add_root_catalogs_menu_type()));
|
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, add_root_catalogs_menu_type()));
|
||||||
|
WM_menutype_add(MEM_dupallocN<MenuType>(__func__, swap_root_catalogs_menu_type()));
|
||||||
|
|
||||||
BKE_spacetype_register(std::move(st));
|
BKE_spacetype_register(std::move(st));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -898,10 +898,12 @@ void rna_uiLayoutPanel(uiLayout *layout,
|
|||||||
|
|
||||||
static void rna_uiLayout_template_node_asset_menu_items(uiLayout *layout,
|
static void rna_uiLayout_template_node_asset_menu_items(uiLayout *layout,
|
||||||
bContext *C,
|
bContext *C,
|
||||||
const char *catalog_path)
|
const char *catalog_path,
|
||||||
|
const int operator_type)
|
||||||
{
|
{
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
ed::space_node::ui_template_node_asset_menu_items(*layout, *C, StringRef(catalog_path));
|
ed::space_node::ui_template_node_asset_menu_items(
|
||||||
|
*layout, *C, StringRef(catalog_path), NodeAssetMenuOperatorType(operator_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_uiLayout_template_node_operator_asset_menu_items(uiLayout *layout,
|
static void rna_uiLayout_template_node_operator_asset_menu_items(uiLayout *layout,
|
||||||
@@ -1201,6 +1203,20 @@ void RNA_api_ui_layout(StructRNA *srna)
|
|||||||
{0, nullptr, 0, nullptr, nullptr},
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem rna_enum_template_node_operator_type[] = {
|
||||||
|
{int(NodeAssetMenuOperatorType::Add),
|
||||||
|
"ADD",
|
||||||
|
0,
|
||||||
|
"Add Node",
|
||||||
|
"Add a node to the active tree."},
|
||||||
|
{int(NodeAssetMenuOperatorType::Swap),
|
||||||
|
"SWAP",
|
||||||
|
0,
|
||||||
|
"Swap Node",
|
||||||
|
"Replace the selected nodes with the specified type."},
|
||||||
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
static const float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
static const float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
/* simple layout specifiers */
|
/* simple layout specifiers */
|
||||||
@@ -2123,6 +2139,12 @@ void RNA_api_ui_layout(StructRNA *srna)
|
|||||||
srna, "template_node_asset_menu_items", "rna_uiLayout_template_node_asset_menu_items");
|
srna, "template_node_asset_menu_items", "rna_uiLayout_template_node_asset_menu_items");
|
||||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||||
parm = RNA_def_string(func, "catalog_path", nullptr, 0, "", "");
|
parm = RNA_def_string(func, "catalog_path", nullptr, 0, "", "");
|
||||||
|
parm = RNA_def_enum(func,
|
||||||
|
"operator",
|
||||||
|
rna_enum_template_node_operator_type,
|
||||||
|
int(NodeAssetMenuOperatorType::Add),
|
||||||
|
"Operator",
|
||||||
|
"The operator the asset menu will use");
|
||||||
|
|
||||||
func = RNA_def_function(srna,
|
func = RNA_def_function(srna,
|
||||||
"template_modifier_asset_menu_items",
|
"template_modifier_asset_menu_items",
|
||||||
|
|||||||
Reference in New Issue
Block a user