We can apply modifiers to an object by sequentially looping through the modifiers list and calling the bpy.ops.object.modifier_apply() operator to apply each of them. However, we can use the fact that the depsgraph already has fully calculated mesh data with modifiers already applied and simply rebuild the object according to this data.
The author of the method is Iyad Ahmed.
An additional bonus of this method is that we can apply modifiers both in the “Object” and in the “Edit” modes.
First, we need to get a pointer to the depsgraph:
1 |
depsgraph = bpy.context.evaluated_depsgraph_get() |
with which we can now get the already fully calculated mesh geometry with all modifiers:
1 |
evaluated_object = bpy.context.object.evaluated_get(depsgraph) |
We will need to remove modifiers from the object later, which will affect the recalculated data, so we need to make a copy of the recalculated mesh geometry:
1 |
mesh = bpy.data.meshes.new_from_object(evaluated_object, depsgraph=depsgraph) |
Now we can remove all modifiers from the object:
1 |
bpy.context.object.modifiers.clear() |
It remains to replace the current mesh geometry with the one that we previously saved.
For the “Object” mode:
1 2 |
if bpy.context.object.mode == 'OBJECT': bpy.context.object.data = mesh |
and for the “Edit” mode:
1 2 3 4 5 |
else: bm = bmesh.from_edit_mesh(bpy.context.object.data) bm.clear() bm.from_mesh(mesh) bmesh.update_edit_mesh(bpy.context.object.data) |
As a result, we get the object with all modifiers applied to it.
Full code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import bpy import bmesh depsgraph = bpy.context.evaluated_depsgraph_get() obj = bpy.context.object evaluated_object = obj.evaluated_get(depsgraph) mesh = bpy.data.meshes.new_from_object(evaluated_object, depsgraph=depsgraph) obj.modifiers.clear() if obj.mode == 'OBJECT': obj.data = mesh else: bm = bmesh.from_edit_mesh(obj.data) bm.clear() bm.from_mesh(mesh) bmesh.update_edit_mesh(obj.data) |
So basically it is the way to apply the modifiers without using
bpy.ops
! Is there downsides to this?Ops in their poll functions commonly control that you do exactly you want. If you work directly with data, you need to control everything yourself. Will it be a big disadvantage when working this way, I don’t think.