1
$\begingroup$

I'm trying to use bpy.ops.object.convert(target='MESH') in Blender 3.3 to apply all modifiers. Unfortunately, I get the error in the title and I don't get what's wrong. I could use modifier_apply() as an operator but that has other problems for me, s weo I wanted to see if I could fix this problem here.

import bpy

for collection in [c for c in bpy.data.collections if 'M_' in c.name]:
    for obj in [o.copy() for o in collection.objects if o.type == 'MESH']:
        obj.data = obj.data.copy()
        if obj.animation_data:
            obj.animation_data.action = obj.animation_data.action.copy()
        bpy.context.collection.objects.link(obj)
    
    with bpy.context.temp_override(active_object=obj):
        bpy.ops.object.convert(target="MESH")
$\endgroup$

1 Answer 1

1
$\begingroup$

Your first mistake was that bpy.context.active_object is read-only. You have to use bpy.context.view_layer.objects.active instead. Another problem was that bpy.ops.object.convert need the object to be selected, so I deselected all selected objects to not disturb the process. After the conversion, the selection is restored.

import bpy

# save and reset state of selection
selected_objects = bpy.context.selected_objects
active_object = bpy.context.active_object
for obj in selected_objects:
    obj.select_set(False)

# apply modifier by converting to mesh    
for collection in [c for c in bpy.data.collections if 'M_' in c.name]:
    for obj in collection.objects:
        obj.data = obj.data.copy()
        if obj.animation_data:
            obj.animation_data.action = obj.animation_data.action.copy()
        bpy.context.collection.objects.link(obj)
            
        bpy.context.view_layer.objects.active = obj
        selection = obj.select_get()
        obj.select_set(True)
        bpy.ops.object.convert(target="MESH")
        obj.select_set(selection)

# restore saved state of selection
bpy.context.view_layer.objects.active = active_object
for obj in selected_objects:
    obj.select_set(True)
$\endgroup$
5
  • $\begingroup$ Thanks Rivin, I might have a misconception of context.temp_override() then. Because numerous lines of selection code is exactly what I didnt want. Context overrides should take care of what you pointed out. At least I thought so! I understood through other stackexchange questions that those overrides would be the way to go since 3.3 $\endgroup$
    – rbx 775
    Sep 22, 2022 at 11:15
  • $\begingroup$ If I use bpy.ops.object.convert with temp_override, the modifier is applied, but I get a copy of the object. So temp_override is probably not suitable for some operators $\endgroup$ Sep 22, 2022 at 12:58
  • $\begingroup$ Did you use my code snippet from above? Then yes, it should generate a duplicate beforehand. But temp_override() should not generate a duplicate/copy on its own, just tested with the snippet below, and was watching the blend file contents in the outliner to verify: import bpy with bpy.context.temp_override(active_object=bpy.context.active_object): bpy.ops.object.convert(target="MESH") $\endgroup$
    – rbx 775
    Sep 22, 2022 at 13:03
  • $\begingroup$ Oh sorry, I accidentally deleted this one line and didn't see the copy in the outliner $\endgroup$ Sep 22, 2022 at 13:24
  • $\begingroup$ @rbx775 it would have worked with any other operator but AFAIK bpy.ops.object.convert is not overridable, confirmed by the devs. See developer.blender.org/T93188 and blender.stackexchange.com/questions/235009/… $\endgroup$
    – Gorgious
    Sep 22, 2022 at 15:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .