Atualizar um script 2.7 que usa frame_current para funcionar com 2.8+
Há um script que acho muito útil que funciona em 2.7x e não funciona mais em 2.8x, 2.9x. Eu quero atualizá-lo para funcionar com as versões atuais do Blender. O script pega um objeto e faz uma duplicata dele onde estaria em cada quadro, aplicando deformações de malha. Parece que parou de funcionar por causa dessas mudanças na API Python que vieram com o novo sistema de coleções.
O script que funciona em 2.7x foi criado por CodeManX :
import bpy
scene = bpy.context.scene
frame_current = scene.frame_current
r = intervalo (scene.frame_start, scene.frame_end + 1)
l = len (str (len (r)))
obs = []
para f em r:
scene.frame_set (f)
para ob em scene.objects:
if ob.type == 'MESH' e ob.name.startswith ("modelo"):
me = ob.to_mesh (cena, Verdadeiro, '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)
para ob em obs:
scene.objects.link (ob)
scene.update ()
Mandei uma mensagem para o autor do código original na semana passada, mas parece que ele não está tão ativo no Blender SE atualmente, então não estou prendendo a respiração por uma resposta. Além disso, talvez no processo de tentar corrigir isso eu possa aprender mais sobre como a API funciona.
De acordo com as mudanças da API, substituí scene = bpy.context.scenepor layer = bpy.context.view_layere isso resolveu um erro. Mas agora estou tentando resolver este:
AttributeError: 'ViewLayer' object has no attribute 'frame_current'
Esta página do Manual do Blender ainda faz referências scene.frame_current. Esta página do manual está desatualizada? Ou estou entendendo mal e ainda podemos usar sceneem certos casos?
Este é meu script modificado de trabalho em andamento, parcialmente corrigido para 2.8+ :
import bpy
layer = bpy.context.view_layer
frame_current = layer.frame_current
r = intervalo (layer.frame_start, layer.frame_end + 1)
l = len (str (len (r)))
obs = []
para f em r:
layer.frame_set (f)
para ob em layer.objects:
if ob.type == 'MESH' e ob.name.startswith ("modelo"):
me = ob.to_mesh (camada, Verdadeiro, '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)
para ob em obs:
layer.objects.link (ob)
layer.update ()
Qualquer ajuda seria muito apreciada. E se puder ser explicado de uma maneira geral que pode se aplicar a outras pessoas que estão tendo problemas para atualizar um script 2.7, ou especificamente aqueles que estão se perguntando sobre como frame_currentmudou, isso seria ótimo.
Finalmente, uma possível dica de nova sintaxe está nesta resposta, onde o autor riscou frame_current = 1e substituiu por frame_set(1)... infelizmente, minha lógica de tentar frame_get()não funcionou.
Respostas
Script atualizado.
Todas as mudanças aqui foram bem documentadas.
A obtenção da malha atualizada mudou.
Como faço para obter um bloco de dados de malha com modificadores e chaves de forma aplicadas no Blender 2.8?
A atualização da cena foi substituída.
Qual é a substituição de scene.update ()?
A configuração da moldura ainda é feita da mesma forma. ( frame_setnão é membro de ViewLayer.)
Vincular objeto a uma cena mudou.
vincular novo objeto à cena com python em 2.8
Os objetos da camada de visualização não têm método de link.
roteiro revisado.
import bpy
context = bpy.context
scene = context.scene
dg = context.evaluated_depsgraph_get()
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)
#dg = context.evaluated_depsgraph_get()
for ob in scene.objects:
if ob.type == 'MESH' and ob.name.startswith("Cube"):
ev_ob = ob.evaluated_get(dg)
me = ev_ob.data.copy()
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:
context.collection.objects.link(ob)
context.view_layer.update()
Observe que não testei isso completamente, com relação à frequência para avaliar o gráfico, descomente #dg = context.evalua....para ver se o resultado difere quando é avaliado por quadro.