Use when working with Blender modifiers via Python -- adding, configuring, or applying modifiers, or accessing Geometry Nodes inputs. Prevents the common mistake of reading mesh data before applying modifiers (getting unmodified geometry) instead of using depsgraph.evaluated_get(). Covers modifier stack, Geometry Nodes input identifiers, common AEC modifiers (Array, Boolean, Solidify), and evaluated mesh access. Keywords: modifier, Array, Boolean, Solidify, Geometry Nodes, depsgraph, evaluated_get, modifier.apply, modifier stack, input identifier, add modifier from code, apply modifier Python, boolean cut.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
blender-syntax-modifiers
description
Use when working with Blender modifiers via Python -- adding, configuring, or applying modifiers, or accessing Geometry Nodes inputs. Prevents the common mistake of reading mesh data before applying modifiers (getting unmodified geometry) instead of using depsgraph.evaluated_get(). Covers modifier stack, Geometry Nodes input identifiers, common AEC modifiers (Array, Boolean, Solidify), and evaluated mesh access. Keywords: modifier, Array, Boolean, Solidify, Geometry Nodes, depsgraph, evaluated_get, modifier.apply, modifier stack, input identifier, add modifier from code, apply modifier Python, boolean cut.
license
MIT
compatibility
Designed for Claude Code. Requires Blender 3.x/4.x/5.x with Python.
metadata
{"author":"OpenAEC-Foundation","version":"1.0"}
blender-syntax-modifiers
Quick Reference
Critical Warnings
NEVER apply modifiers while the object is in Edit Mode — modifier_apply requires Object Mode. Switch with bpy.ops.object.mode_set(mode='OBJECT') first.
NEVER use dict context overrides for modifier_apply in Blender 4.0+ — use context.temp_override() instead. Dict overrides raise .
TypeError
NEVER read obj.data.vertices expecting post-modifier results — use obj.evaluated_get(depsgraph).to_mesh() to access evaluated mesh data.
NEVER forget obj_eval.to_mesh_clear() after obj_eval.to_mesh() — this causes memory leaks. ALWAYS use a try/finally block.
NEVER assume Geometry Nodes modifier input identifiers match socket names — identifiers are auto-generated as Socket_N. ALWAYS look up identifiers via modifier.node_group.interface.items_tree.
NEVER modify the evaluated mesh — it is read-only. Modify the original object, then let the depsgraph re-evaluate.
Modifier Type Decision Tree
Need to add geometry procedurally?
├── Repeat geometry in a pattern → ARRAY
├── Combine/subtract meshes → BOOLEAN
├── Add thickness to surfaces → SOLIDIFY
├── Subdivide for smoothness → SUBSURF
├── Symmetry across an axis → MIRROR
├── Edge beveling → BEVEL
├── Custom node-based logic → NODES (Geometry Nodes)
└── Reduce polygon count → DECIMATE
Need deformation?
├── Skeleton-based → ARMATURE
├── Surface projection → SHRINKWRAP
├── Volume-based deform → MESH_DEFORM
├── Grid-based deform → LATTICE
└── Along a path → CURVE
AEC-Relevant Modifiers
Modifier
AEC Use Case
Type String
Array
Repetitive elements (columns, railings, facade panels)
# Blender 3.x/4.x/5.x: add modifier to an objectimport bpy
obj = bpy.data.objects.get("Wall")
if obj isNone:
raise RuntimeError("Object 'Wall' not found")
# Add modifier: returns the new Modifier object
mod = obj.modifiers.new(name="MyArray", type='ARRAY')
# name: display name (Blender may append .001 if duplicate)# type: modifier type enum string (see table above)# Configure modifier properties
mod.count = 5
mod.relative_offset_displace = (1.0, 0.0, 0.0)
Pattern 2: Remove a Modifier
# Blender 3.x/4.x/5.x: remove modifier by reference or nameimport bpy
obj = bpy.data.objects.get("Wall")
# Remove by reference
mod = obj.modifiers.get("MyArray")
if mod isnotNone:
obj.modifiers.remove(mod)
# Remove all modifiersfor mod in obj.modifiers[:]: # Copy list — modifiers change during removal
obj.modifiers.remove(mod)
Pattern 3: Apply a Modifier (Version-Critical)
Applying a modifier permanently bakes its effect into the mesh. This is an IRREVERSIBLE operation. ALWAYS requires Object Mode.
# Blender 3.2+/4.x/5.x: apply modifier using temp_overrideimport bpy
obj = bpy.data.objects.get("Wall")
# Ensure Object Modeif bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# Apply a single modifierwith bpy.context.temp_override(object=obj, active_object=obj):
bpy.ops.object.modifier_apply(modifier="MyArray")
# Apply ALL modifiers (copy list: stack changes during apply)with bpy.context.temp_override(object=obj, active_object=obj):
for mod in obj.modifiers[:]:
bpy.ops.object.modifier_apply(modifier=mod.name)
# Blender < 3.2 ONLY (legacy: do NOT use for new code)
override = bpy.context.copy()
override['object'] = obj
override['active_object'] = obj
bpy.ops.object.modifier_apply(override, modifier="MyArray")
Pattern 4: Evaluated Mesh via Depsgraph (Preview Without Applying)
Use this to read the post-modifier mesh WITHOUT permanently applying modifiers.
# Blender 3.x/4.x/5.x: read evaluated mesh dataimport bpy
obj = bpy.data.objects.get("Wall")
depsgraph = bpy.context.evaluated_depsgraph_get()
obj_eval = obj.evaluated_get(depsgraph)
mesh_eval = obj_eval.to_mesh()
try:
print(f"Original verts: {len(obj.data.vertices)}")
print(f"Evaluated verts: {len(mesh_eval.vertices)}")
# Read vertex positions in world spacefor v in mesh_eval.vertices:
world_co = obj_eval.matrix_world @ v.co
# process world_co...finally:
obj_eval.to_mesh_clear() # ALWAYS clean up
Pattern 5: Geometry Nodes Modifier: Assign and Configure Inputs
# Blender 4.0+: assign node group and set input valuesimport bpy
obj = bpy.data.objects.get("Building")
mod = obj.modifiers.new(name="GeoNodes", type='NODES')
# Assign an existing node group
node_group = bpy.data.node_groups.get("AEC_WallGenerator")
if node_group isNone:
raise RuntimeError("Node group 'AEC_WallGenerator' not found")
mod.node_group = node_group
# Find input identifiers by name (REQUIRED: identifiers are NOT names)defget_gn_input_identifier(modifier, input_name):
"""Return the Socket_N identifier for a named GN input."""for item in modifier.node_group.interface.items_tree:
if item.item_type == 'SOCKET'and item.in_out == 'INPUT':
if item.name == input_name:
return item.identifier
raise KeyError(f"Input '{input_name}' not found in node group")
# Set input values using identifiers
height_id = get_gn_input_identifier(mod, "Height")
mod[height_id] = 3.5
thickness_id = get_gn_input_identifier(mod, "Thickness")
mod[thickness_id] = 0.2# Force scene update after changing GN inputs
bpy.context.view_layer.update()
# Blender 4.0+: list all GN modifier inputsfor item in mod.node_group.interface.items_tree:
if item.item_type == 'SOCKET'and item.in_out == 'INPUT':
identifier = item.identifier # e.g., "Socket_2"
name = item.name # e.g., "Height"
socket_type = item.socket_type # e.g., "NodeSocketFloat"
current_value = mod.get(identifier)
print(f"{name} ({socket_type}): {identifier} = {current_value}")
Pattern 6: Reorder Modifiers
# Blender 4.0+/5.x: move modifier to specific positionimport bpy
obj = bpy.data.objects.get("Wall")
with bpy.context.temp_override(object=obj):
bpy.ops.object.modifier_move_to_index(modifier="Boolean", index=0)
# Blender 3.x/4.x/5.x: move up/down by one positionwith bpy.context.temp_override(object=obj):
bpy.ops.object.modifier_move_up(modifier="Boolean")
bpy.ops.object.modifier_move_down(modifier="Array")
Common Operations
Array Modifier: Repetitive AEC Elements
# Blender 3.x/4.x/5.x: create array of columnsimport bpy
obj = bpy.data.objects.get("Column")
mod = obj.modifiers.new(name="ColumnArray", type='ARRAY')
# Fixed count
mod.use_relative_offset = True
mod.relative_offset_displace = (2.0, 0.0, 0.0) # Spacing in object-relative units
mod.count = 10# Constant offset (absolute units)
mod.use_constant_offset = True
mod.constant_offset_displace = (3.0, 0.0, 0.0) # 3m spacing in scene units# Fit to length
mod.fit_type = 'FIT_LENGTH'
mod.fit_length = 30.0# Total span in scene units# Fit to curve
mod.fit_type = 'FIT_CURVE'
mod.curve = bpy.data.objects.get("ArrayPath")
# Blender 3.x/4.x/5.x: add thickness to planar geometryimport bpy
obj = bpy.data.objects.get("WallSurface")
mod = obj.modifiers.new(name="WallThickness", type='SOLIDIFY')
mod.thickness = 0.3# Wall thickness in scene units
mod.offset = -1.0# -1 = outward, 0 = centered, 1 = inward
mod.use_even_offset = True# Uniform thickness on angled surfaces
mod.use_quality_normals = True# Better normals on complex geometry
Copy Modifier Settings Between Objects
# Blender 3.x/4.x/5.x: copy all modifiers from source to targetimport bpy
source = bpy.data.objects.get("SourceWall")
target = bpy.data.objects.get("TargetWall")
# Use operator to copy modifierswith bpy.context.temp_override(
object=target,
active_object=source,
selected_objects=[target]
):
bpy.ops.object.make_links_data(type='MODIFIERS')
Check if Modifier Exists Before Operating
# Blender 3.x/4.x/5.x: safe modifier accessimport bpy
obj = bpy.data.objects.get("Wall")
# Check by name
mod = obj.modifiers.get("MyArray")
if mod isnotNone:
print(f"Found modifier: {mod.name}, type: {mod.type}")
# Check by type
has_boolean = any(m.type == 'BOOLEAN'for m in obj.modifiers)
# Iterate with type filterfor mod in obj.modifiers:
if mod.type == 'ARRAY':
print(f"Array: {mod.name}, count: {mod.count}")
Version-Specific Notes
Feature
Blender 3.x
Blender 4.0+
Context override for modifier_apply
Dict override (deprecated 3.2)
context.temp_override() REQUIRED
GN node group sockets API
node_group.inputs.new(...)
node_group.interface.new_socket(...)
GN modifier input identifiers
Input_N (Blender 3.x)
Socket_N (Blender 4.0+)
modifier_move_to_index
Not available
Available
Boolean solver 'EXACT'
Available (3.0+)
Available
bmesh.from_object() depsgraph param
Optional
REQUIRED
BVHTree.FromObject() depsgraph param
Optional
REQUIRED
Reference Links
references/methods.md — Complete API signatures for ObjectModifiers, Modifier base, and specific modifier types