I'm am currently writing a script that changes a node property (cycles value node) for fast switching between different materiallayers. I also want to be able to render multiple materiallayers into a folder automatically. The problem is that while I render the multiple images, either the UI freezes (it's rendering fine but while it does, blender doesn't respond) or when I use
py.ops.render.render('INVOKE_DEFAULT', write_still=True)
only the last image I called gets rendered (in the UI without freezing).
Here is an image thats shows what the script does
and the full code of the renderscript
import bpy
from bpy.props import *
#ml_filepath = 'C:/Users/render/Pictures/test'
def renderLayer(context, layer): #renders
scn = bpy.context.scene
ml_filepath = '//{}/'.format(scn['ml_renderfolder_name']) #generate filepath
name = bpy.context.scene['mln{}'.format(layer)] #get name for the image
bpy.data.node_groups["MLN Layercontroll"].nodes["layer"].outputs[0].default_value = layer #set materiallayer
bpy.context.scene.render.filepath = ml_filepath + scn['ml_renderfolder_name'] + '_ml{}_{}'.format(layer, name) #generate filename
bpy.ops.render.render(write_still=True) #renders layer - ui freeze while rendering
#bpy.ops.render.render('INVOKE_DEFAULT', write_still=True) #only the last layer gets rendered :(
def initSceneProperties(scn): #initiert renderliste
scn['ml_renderlist'] = "1,2,3,4,5"
scn['ml_renderfolder_name'] = "mlRender"
bpy.types.Scene.ml_renderlist = StringProperty(name = "")
bpy.types.Scene.ml_renderfolder_name = StringProperty(name = "")
initSceneProperties(bpy.context.scene)
class MlRenderPanel(bpy.types.Panel): #Panel
bl_label = "ML Render"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
def draw(self, context):
layout = self.layout
scn = bpy.context.scene
layout.label(text="choose materiallayers to render:")
layout.prop(scn, 'ml_renderlist')
layout.label(text="choose foldername:")
layout.prop(scn, 'ml_renderfolder_name')
layout.operator("render.mlrender")
layout.label(text="UI will freeze while rendering")
class MlRenderOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "render.mlrender"
bl_label = "render materiallayers"
def execute(self, context):
scn = bpy.context.scene
list = scn['ml_renderlist'].split(",") #splits renderlist string into list
listInts = map(int, list)
for number in listInts: #calls renderlayer() for every number in the renderlist
renderLayer(context, number)
return {'FINISHED'}
bpy.utils.register_module(__name__)
also here is the code for switching between materiallayers in viewport and renaming them. Probably not necessary for this but I better just post it.
import bpy
from bpy.props import *
layerRange = 5 #Range of layers
# set value in nodegroup "MLN LAYERCONTROLL" to layer property-------------
def execute(self, context):
scn = context.scene
val = scn['materiallayer']
layerName = scn['layerName']
bpy.data.node_groups["MLN Layercontroll"].nodes["layer"].outputs[0].default_value = val
print("set materiallayer to",val)
currentname = scn['mln{}'.format(val)] #rename textfield when switching between layers
scn.layerName = currentname
for i in range(0, layerRange): #rename nodeinputs
print("named nodegroup input",i)
newname = scn['mln{}'.format(i+1)]
bpy.data.node_groups["MLN x5"].inputs[i].name = newname
#raname node inputs + properties
def renameNodeInputs(self, context):
scn = context.scene
textfieldName = scn['layerName']
val = scn['materiallayer']
scn['mln{}'.format(val)] = textfieldName #rename layername property
for i in range(0, layerRange): #alle inputs benennen
print("named nodegroup input",i)
newname = scn['mln{}'.format(i+1)]
bpy.data.node_groups["MLN x5"].inputs[i].name = newname
#initialize scene properties
def initSceneProperties(scn):
scn['materiallayer'] = 1
bpy.types.Scene.materiallayer = IntProperty( #current Materiallayer (number)
name = "materiallayer", update = execute,
description = "choose materiallayer",
min = 1, max = layerRange,)
bpy.types.Scene.layerName = StringProperty(name = "Name",
update = renameNodeInputs) #layername
for i in range(0, layerRange):
scn['mln{}'.format(i+1)] = "materiallayer {}".format(i+1) #create layernamen
print("created mln property")
#
layername = bpy.context.scene.layerName
test = scn['materiallayer']
scn["layerName"] = layername
initSceneProperties(bpy.context.scene)
#Panel in UI region
class ML_Panel(bpy.types.Panel):
bl_label = "Materiallayer"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
scn = context.scene
layout.prop(scn, 'materiallayer', icon='BLENDER')
layout.prop(scn, 'layerName')
#Registration
bpy.utils.register_module(__name__)
sorry when my code is a total mess - I just started learning python and bpy.
tldr: How can I render multiple images from a for loop without freezing the UI while rendering?