c6e5e62f45
Port of the Time Offset modifier from GPv2. Pull Request: https://projects.blender.org/blender/blender/pulls/118371
294 lines
12 KiB
Python
294 lines
12 KiB
Python
# SPDX-FileCopyrightText: 2009-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import bpy
|
|
from bpy.types import Panel, Menu, Operator
|
|
|
|
|
|
class ModifierButtonsPanel:
|
|
bl_space_type = 'PROPERTIES'
|
|
bl_region_type = 'WINDOW'
|
|
bl_context = "modifier"
|
|
bl_options = {'HIDE_HEADER'}
|
|
|
|
|
|
class ModifierAddMenu:
|
|
MODIFIER_TYPES_TO_LABELS = {
|
|
enum_it.identifier: enum_it.name
|
|
for enum_it in bpy.types.Modifier.bl_rna.properties["type"].enum_items_static
|
|
}
|
|
MODIFIER_TYPES_TO_ICONS = {
|
|
enum_it.identifier: enum_it.icon
|
|
for enum_it in bpy.types.Modifier.bl_rna.properties["type"].enum_items_static
|
|
}
|
|
MODIFIER_TYPES_I18N_CONTEXT = bpy.types.Modifier.bl_rna.properties["type"].translation_context
|
|
|
|
@classmethod
|
|
def operator_modifier_add(cls, layout, mod_type):
|
|
layout.operator(
|
|
"object.modifier_add",
|
|
text=cls.MODIFIER_TYPES_TO_LABELS[mod_type],
|
|
# Although these are operators, the label actually comes from an (enum) property,
|
|
# so the property's translation context must be used here.
|
|
text_ctxt=cls.MODIFIER_TYPES_I18N_CONTEXT,
|
|
icon=cls.MODIFIER_TYPES_TO_ICONS[mod_type],
|
|
).type = mod_type
|
|
|
|
|
|
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|
bl_label = "Modifiers"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
ob = context.object
|
|
return ob and ob.type != 'GPENCIL'
|
|
|
|
def draw(self, _context):
|
|
layout = self.layout
|
|
layout.operator("wm.call_menu", text="Add Modifier", icon='ADD').name = "OBJECT_MT_modifier_add"
|
|
layout.template_modifiers()
|
|
|
|
|
|
class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
|
|
bl_label = "Add Modifier"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
geometry_nodes_supported = ob_type in {'MESH', 'CURVE', 'CURVES',
|
|
'FONT', 'VOLUME', 'POINTCLOUD', 'GREASEPENCIL'}
|
|
|
|
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 = "OBJECT_MT_modifier_add"
|
|
layout.separator()
|
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
|
|
|
if geometry_nodes_supported:
|
|
self.operator_modifier_add(layout, 'NODES')
|
|
layout.separator()
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'GREASEPENCIL'}:
|
|
layout.menu("OBJECT_MT_modifier_add_edit")
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME', 'GREASEPENCIL'}:
|
|
layout.menu("OBJECT_MT_modifier_add_generate")
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'VOLUME', 'GREASEPENCIL'}:
|
|
layout.menu("OBJECT_MT_modifier_add_deform")
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
layout.menu("OBJECT_MT_modifier_add_physics")
|
|
if ob_type in {'GREASEPENCIL'}:
|
|
layout.menu("OBJECT_MT_modifier_add_color")
|
|
|
|
if geometry_nodes_supported:
|
|
layout.menu_contents("OBJECT_MT_modifier_add_root_catalogs")
|
|
|
|
|
|
class OBJECT_MT_modifier_add_edit(ModifierAddMenu, Menu):
|
|
bl_label = "Edit"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'DATA_TRANSFER')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'MESH_CACHE')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'MESH_SEQUENCE_CACHE')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'NORMAL_EDIT')
|
|
self.operator_modifier_add(layout, 'WEIGHTED_NORMAL')
|
|
self.operator_modifier_add(layout, 'UV_PROJECT')
|
|
self.operator_modifier_add(layout, 'UV_WARP')
|
|
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_EDIT')
|
|
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
|
|
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
|
|
if ob_type == 'GREASEPENCIL':
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_TIME')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_PROXIMITY')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_ANGLE')
|
|
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
|
|
bl_label = "Generate"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'ARRAY')
|
|
self.operator_modifier_add(layout, 'BEVEL')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'BOOLEAN')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'BUILD')
|
|
self.operator_modifier_add(layout, 'DECIMATE')
|
|
self.operator_modifier_add(layout, 'EDGE_SPLIT')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'MASK')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'MIRROR')
|
|
if ob_type == 'VOLUME':
|
|
self.operator_modifier_add(layout, 'MESH_TO_VOLUME')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'MULTIRES')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'REMESH')
|
|
self.operator_modifier_add(layout, 'SCREW')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'SKIN')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'SOLIDIFY')
|
|
self.operator_modifier_add(layout, 'SUBSURF')
|
|
self.operator_modifier_add(layout, 'TRIANGULATE')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'VOLUME_TO_MESH')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'WELD')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'WIREFRAME')
|
|
if ob_type == 'GREASEPENCIL':
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_ARRAY')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_DASH')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_LENGTH')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_MIRROR')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_MULTIPLY')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_SUBDIV')
|
|
self.operator_modifier_add(layout, 'LINEART')
|
|
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
class OBJECT_MT_modifier_add_deform(ModifierAddMenu, Menu):
|
|
bl_label = "Deform"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'ARMATURE')
|
|
self.operator_modifier_add(layout, 'CAST')
|
|
self.operator_modifier_add(layout, 'CURVE')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'DISPLACE')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'HOOK')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'LAPLACIANDEFORM')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'LATTICE')
|
|
self.operator_modifier_add(layout, 'MESH_DEFORM')
|
|
self.operator_modifier_add(layout, 'SHRINKWRAP')
|
|
self.operator_modifier_add(layout, 'SIMPLE_DEFORM')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
|
self.operator_modifier_add(layout, 'SMOOTH')
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'CORRECTIVE_SMOOTH')
|
|
self.operator_modifier_add(layout, 'LAPLACIANSMOOTH')
|
|
self.operator_modifier_add(layout, 'SURFACE_DEFORM')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'WARP')
|
|
self.operator_modifier_add(layout, 'WAVE')
|
|
if ob_type == 'VOLUME':
|
|
self.operator_modifier_add(layout, 'VOLUME_DISPLACE')
|
|
if ob_type == 'GREASEPENCIL':
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_ARMATURE')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_HOOK')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_LATTICE')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_NOISE')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_OFFSET')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_SMOOTH')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_THICKNESS')
|
|
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
class OBJECT_MT_modifier_add_physics(ModifierAddMenu, Menu):
|
|
bl_label = "Physics"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
if ob_type == 'MESH':
|
|
self.operator_modifier_add(layout, 'CLOTH')
|
|
self.operator_modifier_add(layout, 'COLLISION')
|
|
self.operator_modifier_add(layout, 'DYNAMIC_PAINT')
|
|
self.operator_modifier_add(layout, 'EXPLODE')
|
|
self.operator_modifier_add(layout, 'FLUID')
|
|
self.operator_modifier_add(layout, 'OCEAN')
|
|
self.operator_modifier_add(layout, 'PARTICLE_INSTANCE')
|
|
self.operator_modifier_add(layout, 'PARTICLE_SYSTEM')
|
|
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
|
self.operator_modifier_add(layout, 'SOFT_BODY')
|
|
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
class OBJECT_MT_modifier_add_color(ModifierAddMenu, Menu):
|
|
bl_label = "Color"
|
|
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
ob_type = context.object.type
|
|
if ob_type == 'GREASEPENCIL':
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_COLOR')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_TINT')
|
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_OPACITY')
|
|
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
|
|
|
|
|
class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
|
bl_label = "Modifiers"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
ob = context.object
|
|
return ob and ob.type == 'GPENCIL'
|
|
|
|
def draw(self, _context):
|
|
layout = self.layout
|
|
layout.operator_menu_enum("object.gpencil_modifier_add", "type")
|
|
layout.template_grease_pencil_modifiers()
|
|
|
|
|
|
class AddModifierMenu(Operator):
|
|
bl_idname = "object.add_modifier_menu"
|
|
bl_label = "Add Modifier"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
# NOTE: This operator only exists to add a poll to the add modifier shortcut in the property editor.
|
|
object = context.object
|
|
space = context.space_data
|
|
if object and object.type == 'GPENCIL':
|
|
return False
|
|
return space and space.type == 'PROPERTIES' and space.context == 'MODIFIER'
|
|
|
|
def invoke(self, context, event):
|
|
return bpy.ops.wm.call_menu(name="OBJECT_MT_modifier_add")
|
|
|
|
|
|
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,
|
|
OBJECT_MT_modifier_add_color,
|
|
DATA_PT_gpencil_modifiers,
|
|
AddModifierMenu,
|
|
)
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
from bpy.utils import register_class
|
|
|
|
for cls in classes:
|
|
register_class(cls)
|