Fixing a render script to make it save all view layers instead of just one

Hello, I’m currently trying to fix a script/addon that was made in ~2.7 that’s just been updated to work with 2.8 and above. In it, the script is saving the image of the active view layer to a specific folder based on what action and view layer is being rendered.

The problem is when multiple view layers are enabled, it only saves the active view layer, and it doesn’t save the other enabled view layers even though they are also being rendered.

I know there are some ways of going about this:

rewrite the script to work with File Output nodes and work inside the compositor instead

not ideal, I have next to no idea regarding scripting, and I’ve tried reading about the documentation regarding class and types and whatnot and I couldn’t follow

edit the script so that it also saves the other layers, also making it so that the other layers are saved in their respective folder

not sure if this is even possible without the File Output node

save the enabled view layers as some sort of list then disable all of them then only activate one at a time upon rendering, that way, time won’t be wasted rendering other layers that aren’t getting saved anyway

might be the easiest solution though might not be as optimized


Anyway, here’s the script. If anyone could point me in the right direction or suggest another way of approaching the problem, that would be great. Thanks :blush:

import bpy
from math import radians, floor, ceil, sqrt
from os.path import join
import sys
from PIL import Image

class RenderAllActions(bpy.types.Operator):
	bl_idname = "scene.render_allactions"
	bl_label = "Vingar Renderer"
	bl_options = {'REGISTER', 'UNDO'}
	
	def execute(self, context):
		scn = context.scene
		S = bpy.context.scene

		renderFolderInitial = scn.save_path

		startFrame = 0
		endFrame  = 0 # frames
		numAngles = scn.camera_angles
		rotAngle  = 360 / numAngles
		all_render_layers = S.view_layers
		render_layers = []
		
		for layer in all_render_layers:
			if layer.use == True:
				render_layers.append(layer)
		
		selection_names = bpy.context.selected_objects
		
		all_actions = bpy.data.actions
		render_actions = []
		
		for action in all_actions:
			if action.use_fake_user == True:
				render_actions.append(action)
				
		for action in render_actions:
			bpy.context.view_layer.objects.active = bpy.data.objects[scn.rig_name]
			
			rig = bpy.data.objects[scn.rig_name]
			
			bpy.context.view_layer.objects.active = bpy.data.objects[scn.rig_name]
			
			rig.animation_data.action = bpy.data.actions.get(action.name)
			
			from bpy import context as C, data as D  # just useful aliases same as in console
			scene_objects = [o for o in D.objects if C.scene in o.users_scene]
			render_platform = next(o for o in scene_objects if o.name.startswith('RenderPlatform'))
			camParent = render_platform
			
			if not scn.renderLastFrame:
				endFrame = int(action.frame_range[1])
			else:
				endFrame = int(action.frame_range[1])-1

			renderFolderAction = "{}/{}/".format(renderFolderInitial, action.name)

			for layer in render_layers:
				layer.use = True
					
				for i in range(numAngles):
					angle = i * rotAngle
					camParent.rotation_euler.z = radians( angle )
					renderFolder = "{0}{1}/{2}".format(renderFolderAction, layer.name, i+1)

					fileNames = []

					for f in range(startFrame,endFrame + 1):
						S.frame_set( f )

						frmNum   = str( f-startFrame ).zfill(3) 
						fileName = "{f}".format(f = frmNum)
						fileName += S.render.file_extension
						S.render.filepath = join( renderFolder, fileName )
						fileNames.append(bpy.path.abspath(S.render.filepath))

						bpy.ops.render.render(write_still = True)

					print("Combining rendered images...")

					images = [Image.open(x) for x in fileNames]
					widths, heights = zip(*(i.size for i in images))

					# we can assume all images have the same width and height
					maxWidth, maxHeight = getSquareSize(len(images)) 
					maxWidth *= widths[0]
					maxHeight *= heights[0]

					maxWidth = int(maxWidth)
					maxHeight = int(maxHeight)

					new_im = Image.new('RGBA', (maxWidth, maxHeight), (255, 0, 0, 0))

					x = 0
					y = 0
					for im in images:
						new_im.paste(im, (x, y))
						x += im.size[0]
						if x >= maxWidth:
							x = 0
							y += im.size[1]

					renderFolder = renderFolder.rsplit('/', 1)[0]
					outFile = renderFolder + "/" + str(i + 1) + "-"
					if scn.model_desc != "":
						outFile += scn.model_desc + "-"
					outFile += layer.name + "-" + action.name + S.render.file_extension
					outFile = bpy.path.abspath(outFile)
					print("Combined rendered images to: " + outFile)
					new_im.save(outFile)

				layer.use = False
		
		camParent.rotation_euler.z = 0

		return {'FINISHED'}

def getSquareSize(n):
	root = sqrt(n)

	if root.is_integer():
		return (root, root)

	minval = floor(root)
	maxval = ceil(root)

	if minval * maxval >= n:
		return (maxval, minval)
	else:
		return (maxval, maxval)