3
$\begingroup$

I'm trying to achieve this:

I select all objects with the same type of modifier (Armature) and want to "click" Apply on all of them. I searched different scripts on here and badly put together this one:

import bpy
sel = bpy.context.selected_objects

for ob in sel:
    for i, mod in enumerate(ob.modifiers):
        if mod.type == 'ARMATURE':
            bpy.context.scene.objects.active = ob
                for x in range(0, i):
                    bpy.ops.object.modifier_apply(modifier=mod.name)

It will work for some of the selected objects then Blender will say "Python Script fail". It's obvious I don't know what I'm doing, but why is it failing after working at first? Thanks

EDIT: I found something that does exactly what I was trying to do. A user from Blender Artists named VincentG created an addon called "Massive Editor" from here. I selected all objects, typed Armature in the custom field and all objects that had that specific modifier applied. The script may be old, but it worked great. Thanks Vincent!

For the sake of learning though, I'd still want to know what went wrong...

UPDATE: While searching around I found this answer here and tried it out to see if it would work for me:

import bpy

sel = bpy.context.selected_objects
act = bpy.context.active_object

for obj in sel:
    if obj != act:
        bpy.context.scene.objects.active = obj #sets the obj accessible to bpy.ops
        bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Mirror")

bpy.context.scene.objects.active = act

It almost does what I would like but every time it would only apply to all selected objects except the active one.

$\endgroup$
8
  • $\begingroup$ As I understand this, you may have more than the modifier that you want to apply, and I'm not sure how to do that (hence a comment, rather than an answer). However, if you can live with having all modifiers applied, you could do Ctrl C followed by M with all the objects selected in object mode. Strictly speaking, this is used to convert meta balls, curves or text to meshes, but it also applies all modifiers, and it works just fine even when the selected objects are already meshes. $\endgroup$
    – user27640
    Commented Mar 31, 2017 at 15:48
  • $\begingroup$ Thanks for the comment, but I have seen that option but unfortunately it cannot do :( $\endgroup$
    – Oblender
    Commented Mar 31, 2017 at 16:14
  • $\begingroup$ What error are you getting? If you are on Windows you can go to Window> Toggle System Console to view the Python error. Otherwise you can look here: docs.blender.org/manual/en/dev/advanced/command_line/… $\endgroup$ Commented Mar 31, 2017 at 17:29
  • $\begingroup$ What probably happens here is that you are looping over a list (obj.modifiers) but inside the list you delete (.modifier_apply) elements of the list. But as indicated @RayMairlot, you should have a look at the console. If that use "for i, mod in enumerate(ob.modifiers[:])" $\endgroup$
    – lemon
    Commented Apr 1, 2017 at 5:02
  • $\begingroup$ I tried two ways, one with Armature modifiers at the bottom of the stack for all selected objects, and one with Armature modifiers at the top of the stack for all selected objects. The first method gave me this error: Info: Applied modifier was not first,...(This was said 4 times) ...line 9 (Which was bpy.ops.object.modifier_apply(modifier=mod.name)) ...UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte Error: Python script fail, look in the console for now... The second method just does nothing and console seems to just pause. $\endgroup$
    – Oblender
    Commented Apr 1, 2017 at 7:46

1 Answer 1

3
$\begingroup$

Blender 2.79

This should work:

import bpy

for ob in bpy.context.selected_objects:
    bpy.context.scene.objects.active = ob
    for mod in [m for m in ob.modifiers if m.type == 'ARMATURE']:
        bpy.ops.object.modifier_apply( modifier = mod.name )

You may have some warnings though (like via the UI).

Blender 2.8

Use view_layer instead of scene:

import bpy

for ob in bpy.context.selected_objects:
    bpy.context.view_layer.objects.active = ob
    for mod in [m for m in ob.modifiers if m.type == 'ARMATURE']:
        bpy.ops.object.modifier_apply( modifier = mod.name )
$\endgroup$
6
  • $\begingroup$ bpy.ops.object.modifier_apply works on the active object (bpy.context.scene.objects.active = ob) $\endgroup$
    – lemon
    Commented Apr 1, 2017 at 14:11
  • $\begingroup$ Now this worked perfectly! Thank you so much! I tried something similar to this but did not have ` [m for m in ob.modifiers if m.type == 'ARMATURE']`. $\endgroup$
    – Oblender
    Commented Apr 1, 2017 at 14:11
  • $\begingroup$ This allows to keep only objects which are armatures $\endgroup$
    – lemon
    Commented Apr 1, 2017 at 14:12
  • $\begingroup$ Sorry I was trying to edit my other comment that got added without me finishing and I forgot what I typed lol. $\endgroup$
    – Oblender
    Commented Apr 1, 2017 at 14:17
  • 1
    $\begingroup$ @ReubenX, after sale services ; ) .... done $\endgroup$
    – lemon
    Commented Aug 20, 2019 at 8:34

You must log in to answer this question.

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