There's a script I find very useful that works in 2.7x that is no longer working in 2.8x, 2.9x. I want to update it to work with current Blender versions. The script takes an object and makes a duplicate of it where it would be at each frame, applying mesh deformations. It seems it stopped working because of these Python API changes that came with the new Collections system.
The script that works in 2.7x was authored by CodeManX:
import bpy scene = bpy.context.scene frame_current = scene.frame_current r = range(scene.frame_start, scene.frame_end + 1) l = len(str(len(r))) obs = [] for f in r: scene.frame_set(f) for ob in scene.objects: if ob.type == 'MESH' and ob.name.startswith("model"): me = ob.to_mesh(scene, True, 'PREVIEW') new_ob = bpy.data.objects.new("%s_frame%0*i" % (ob.name, l, f), me) new_ob.matrix_world = ob.matrix_world.copy() obs.append(new_ob) scene.frame_set(frame_current) for ob in obs: scene.objects.link(ob) scene.update()
I messaged the author of the original code last week, but it appears he is not so active on Blender SE these days, so I'm not holding my breath for a response. Besides, maybe in the process of trying to fix this I can learn more about how the API works.
According to the API changes, I replaced scene = bpy.context.scene
with layer = bpy.context.view_layer
and that resolved one error. But now I am trying to resolve this one:
AttributeError: 'ViewLayer' object has no attribute 'frame_current'
This page of the Blender Manual still references scene.frame_current
. Is this manual page outdated? Or am I misunderstanding and we can still use scene
in certain cases?
This is my work-in-progress modified script, partially fixed for 2.8+:
import bpy layer = bpy.context.view_layer frame_current = layer.frame_current r = range(layer.frame_start, layer.frame_end + 1) l = len(str(len(r))) obs = [] for f in r: layer.frame_set(f) for ob in layer.objects: if ob.type == 'MESH' and ob.name.startswith("model"): me = ob.to_mesh(layer, True, 'PREVIEW') new_ob = bpy.data.objects.new("%s_frame%0*i" % (ob.name, l, f), me) new_ob.matrix_world = ob.matrix_world.copy() obs.append(new_ob) layer.frame_set(frame_current) for ob in obs: layer.objects.link(ob) layer.update()
Any help would be greatly appreciated. And if it can explained in a general way that may apply to others having problems updating a 2.7 script, or specifically those wondering about how frame_current
has changed, that would be great.
Finally, one possible hint of new syntax is in this answer where the author has crossed out frame_current = 1
and replaced it with frame_set(1)
...unfortunately my logic of trying frame_get()
did not work.