Geometry Nodes: Extend add modifier menu with node group assets
Implements part of #111538. Change the modifier add button to create a menu with submenus. Extend the submenus dynamically with geometry node group assets. This makes it much simpler to share and use custom modifiers. Node groups get a new "Is Modifier" property, which is controllable in a popover in the node editor header when the group is an asset. The built in modifier can be rearranged in different categories in a next step. For now the existing organization is used, except for the geometry nodes modifier, which is called "Empty Modifier" and put in the root menu. The changes in !110855 and !110828 will be important to improve interaction speed with the new UI. Those are planned for 4.0 as well. Pull Request: https://projects.blender.org/blender/blender/pulls/111717
This commit is contained in:
@@ -230,6 +230,7 @@ class NewGeometryNodesModifier(Operator):
|
||||
return {'CANCELLED'}
|
||||
|
||||
group = geometry_node_group_empty_new()
|
||||
group.is_modifier = True
|
||||
modifier.node_group = group
|
||||
|
||||
return {'FINISHED'}
|
||||
@@ -257,6 +258,7 @@ class NewGeometryNodeTreeAssign(Operator):
|
||||
if not modifier:
|
||||
return {'CANCELLED'}
|
||||
group = geometry_node_group_empty_new()
|
||||
group.is_modifier = True
|
||||
modifier.node_group = group
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from bpy.types import Panel
|
||||
from bpy.types import Panel, Menu
|
||||
|
||||
|
||||
class ModifierButtonsPanel:
|
||||
@@ -22,10 +22,151 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator_menu_enum("object.modifier_add", "type")
|
||||
layout.operator("wm.call_menu", text="Add Modifier", icon='ADD').name="OBJECT_MT_modifier_add"
|
||||
layout.template_modifiers()
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add(Menu):
|
||||
bl_label = "Add Modifier"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
geometry_nodes_supported = ob_type in {'MESH', 'CURVE', 'CURVES', 'FONT', 'SURFACE', 'VOLUME', 'POINTCLOUD'}
|
||||
if geometry_nodes_supported:
|
||||
layout.operator("object.modifier_add", text="Empty Modifier").type='NODES'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_edit")
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_generate")
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'VOLUME'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_deform")
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_physics")
|
||||
|
||||
if geometry_nodes_supported:
|
||||
layout.menu_contents("OBJECT_MT_modifier_add_root_catalogs")
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add_edit(Menu):
|
||||
bl_label = "Edit"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Data Transfer", icon='MOD_DATA_TRANSFER').type='DATA_TRANSFER'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Mesh Cache", icon='MOD_MESHDEFORM').type='MESH_CACHE'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Mesh Sequence Cache", icon='MOD_MESHDEFORM').type='MESH_SEQUENCE_CACHE'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Normal Edit", icon='MOD_NORMALEDIT').type='NORMAL_EDIT'
|
||||
layout.operator("object.modifier_add", text="Weighted Normal", icon='MOD_NORMALEDIT').type='WEIGHTED_NORMAL'
|
||||
layout.operator("object.modifier_add", text="UV Project", icon='MOD_UVPROJECT').type='UV_PROJECT'
|
||||
layout.operator("object.modifier_add", text="UV Warp", icon='MOD_UVPROJECT').type='UV_WARP'
|
||||
layout.operator("object.modifier_add", text="Vertex Weight Edit", icon='MOD_VERTEX_WEIGHT').type='VERTEX_WEIGHT_EDIT'
|
||||
layout.operator("object.modifier_add", text="Vertex Weight Mix", icon='MOD_VERTEX_WEIGHT').type='VERTEX_WEIGHT_MIX'
|
||||
layout.operator("object.modifier_add", text="Vertex Weight Proximity", icon='MOD_VERTEX_WEIGHT').type='VERTEX_WEIGHT_PROXIMITY'
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add_generate(Menu):
|
||||
bl_label = "Generate"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Array", icon='MOD_ARRAY').type='ARRAY'
|
||||
layout.operator("object.modifier_add", text="Bevel", icon='MOD_BEVEL').type='BEVEL'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Boolean", icon='MOD_BOOLEAN').type='BOOLEAN'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Build", icon='MOD_BUILD').type='BUILD'
|
||||
layout.operator("object.modifier_add", text="Decimate", icon='MOD_DECIM').type='DECIMATE'
|
||||
layout.operator("object.modifier_add", text="Edge Split", icon='MOD_EDGESPLIT').type='EDGE_SPLIT'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Mask", icon='MOD_MASK').type='MASK'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Mirror", icon='MOD_MIRROR').type='MIRROR'
|
||||
if ob_type == 'VOLUME':
|
||||
layout.operator("object.modifier_add", text="Mesh to Volume", icon='VOLUME_DATA').type='MESH_TO_VOLUME'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Multiresolution", icon='MOD_MULTIRES').type='MULTIRES'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Remesh", icon='MOD_REMESH').type='REMESH'
|
||||
layout.operator("object.modifier_add", text="Screw", icon='MOD_SCREW').type='SCREW'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Skin", icon='MOD_SKIN').type='SKIN'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Solidify", icon='MOD_SOLIDIFY').type='SOLIDIFY'
|
||||
layout.operator("object.modifier_add", text="Subdivision Surface", icon='MOD_SUBSURF').type='SUBSURF'
|
||||
layout.operator("object.modifier_add", text="Triangulate", icon='MOD_TRIANGULATE').type='TRIANGULATE'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Volume to Mesh", icon='VOLUME_DATA').type='VOLUME_TO_MESH'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Weld", icon='AUTOMERGE_OFF').type='WELD'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Wireframe", icon='MOD_WIREFRAME').type='WIREFRAME'
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add_deform(Menu):
|
||||
bl_label = "Deform"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Armature", icon='MOD_ARMATURE').type='ARMATURE'
|
||||
layout.operator("object.modifier_add", text="Cast", icon='MOD_CAST').type='CAST'
|
||||
layout.operator("object.modifier_add", text="Curve", icon='MOD_CURVE').type='CURVE'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Displace", icon='MOD_DISPLACE').type='DISPLACE'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Hook", icon='HOOK').type='HOOK'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Laplacian Deform", icon='MOD_MESHDEFORM').type='LAPLACIANDEFORM'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Lattice", icon='MOD_LATTICE').type='LATTICE'
|
||||
layout.operator("object.modifier_add", text="Mesh Deform", icon='MOD_MESHDEFORM').type='MESH_DEFORM'
|
||||
layout.operator("object.modifier_add", text="Shrinkwrap", icon='MOD_SHRINKWRAP').type='SHRINKWRAP'
|
||||
layout.operator("object.modifier_add", text="Simple Deform", icon='MOD_SIMPLEDEFORM').type='SIMPLE_DEFORM'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
layout.operator("object.modifier_add", text="Smooth", icon='MOD_SMOOTH').type='SMOOTH'
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Smooth Corrective", icon='MOD_SMOOTH').type='CORRECTIVE_SMOOTH'
|
||||
layout.operator("object.modifier_add", text="Smooth Laplacian", icon='MOD_SMOOTH').type='LAPLACIANSMOOTH'
|
||||
layout.operator("object.modifier_add", text="Surface Deform", icon='MOD_MESHDEFORM').type='SURFACE_DEFORM'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Warp", icon='MOD_WARP').type='WARP'
|
||||
layout.operator("object.modifier_add", text="Wave", icon='MOD_WAVE').type='WAVE'
|
||||
if ob_type == 'VOLUME':
|
||||
layout.operator("object.modifier_add", text="Volume Displace", icon='VOLUME_DATA').type='VOLUME_DISPLACE'
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add_physics(Menu):
|
||||
bl_label = "Physics"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
if ob_type == 'MESH':
|
||||
layout.operator("object.modifier_add", text="Cloth", icon='MOD_CLOTH').type='CLOTH'
|
||||
layout.operator("object.modifier_add", text="Collision", icon='MOD_PHYSICS').type='COLLISION'
|
||||
layout.operator("object.modifier_add", text="Dynamic Paint", icon='MOD_DYNAMICPAINT').type='DYNAMIC_PAINT'
|
||||
layout.operator("object.modifier_add", text="Explode", icon='MOD_EXPLODE').type='EXPLODE'
|
||||
layout.operator("object.modifier_add", text="Fluid", icon='MOD_FLUIDSIM').type='FLUID'
|
||||
layout.operator("object.modifier_add", text="Ocean", icon='MOD_OCEAN').type='OCEAN'
|
||||
layout.operator("object.modifier_add", text="Particle Instance", icon='MOD_PARTICLE_INSTANCE').type='PARTICLE_INSTANCE'
|
||||
layout.operator("object.modifier_add", text="Particle System", icon='MOD_PARTICLES').type='PARTICLE_SYSTEM'
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
layout.operator("object.modifier_add", text="Soft Body", icon='MOD_SOFT').type='SOFT_BODY'
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
bl_label = "Modifiers"
|
||||
|
||||
@@ -42,6 +183,11 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
classes = (
|
||||
DATA_PT_modifiers,
|
||||
OBJECT_MT_modifier_add,
|
||||
OBJECT_MT_modifier_add_edit,
|
||||
OBJECT_MT_modifier_add_generate,
|
||||
OBJECT_MT_modifier_add_deform,
|
||||
OBJECT_MT_modifier_add_physics,
|
||||
DATA_PT_gpencil_modifiers,
|
||||
)
|
||||
|
||||
|
||||
@@ -160,6 +160,8 @@ class NODE_HT_header(Header):
|
||||
row.template_ID(active_modifier, "node_group", new="node.new_geometry_node_group_assign")
|
||||
else:
|
||||
row.template_ID(snode, "node_tree", new="node.new_geometry_nodes_modifier")
|
||||
if snode.node_tree and snode.node_tree.asset_data:
|
||||
layout.popover(panel="NODE_PT_geometry_node_asset_traits")
|
||||
else:
|
||||
layout.template_ID(snode, "node_tree", new="node.new_geometry_node_group_tool")
|
||||
if snode.node_tree and snode.node_tree.asset_data:
|
||||
@@ -448,18 +450,21 @@ class NODE_PT_geometry_node_asset_traits(Panel):
|
||||
snode = context.space_data
|
||||
group = snode.node_tree
|
||||
|
||||
col = layout.column(heading="Type")
|
||||
col.prop(group, "is_tool")
|
||||
col = layout.column(heading="Mode")
|
||||
col.active = group.is_tool
|
||||
col.prop(group, "is_mode_edit")
|
||||
col.prop(group, "is_mode_sculpt")
|
||||
col = layout.column(heading="Geometry")
|
||||
col.active = group.is_tool
|
||||
col.prop(group, "is_type_mesh")
|
||||
col.prop(group, "is_type_curve")
|
||||
if context.preferences.experimental.use_new_point_cloud_type:
|
||||
col.prop(group, "is_type_point_cloud")
|
||||
if snode.geometry_nodes_type == 'MODIFIER':
|
||||
layout.prop(group, "is_modifier")
|
||||
else:
|
||||
col = layout.column(heading="Type")
|
||||
col.prop(group, "is_tool")
|
||||
col = layout.column(heading="Mode")
|
||||
col.active = group.is_tool
|
||||
col.prop(group, "is_mode_edit")
|
||||
col.prop(group, "is_mode_sculpt")
|
||||
col = layout.column(heading="Geometry")
|
||||
col.active = group.is_tool
|
||||
col.prop(group, "is_type_mesh")
|
||||
col.prop(group, "is_type_curve")
|
||||
if context.preferences.experimental.use_new_point_cloud_type:
|
||||
col.prop(group, "is_type_point_cloud")
|
||||
|
||||
|
||||
class NODE_PT_node_color_presets(PresetPanel, Panel):
|
||||
|
||||
Reference in New Issue
Block a user