I want to render objects from nested collections and save them to a folder created using the collection name.
If the collection has a child collection e.g. Suzanne
then it should create a folder structure similar to the collection hierarchy.
So in this case the folder structure will be Cube/Suzanne/
Now there are two mode
of rendering.
COMBINED
It should render all objects from a particular collection and save them to their corresponding folder.INDIVIDUAL
It should render each object from a particular collection and save it to its corresponding folder.
Example:
import bpy
from bpy.types import Operator
from bpy.props import *
import os
class RENDER_OT_render_frames(Operator):
bl_label = "Render Frames"
bl_idname = "redner.render_frames"
type : EnumProperty(
items = (
('ANIMATION', 'Animation', ''),
('VIEW', 'View', ''),
)
)
mode : EnumProperty(
items = (
('COMBINED', 'Combined', 'Render all object together from a collection'),
('INDIVIDUAL', 'Individual', 'Render individual object from a collection'),
)
)
def create_output_folder(self, path):
if os.path.isdir(path):
return
os.makedirs(path)
def render_combined_objects(self, context, collection: bpy.types.Collection, filepath: str, name: str):
for object in bpy.data.objects:
if object.type not in {"CAMERA", "LIGHT"}:
object.hide_render = True
object.hide_viewport = True
if collection.objects:
if self.type == 'ANIMATION':
for obj in bpy.data.objects:
if obj in list(collection.objects):
obj.hide_render = False
context.scene.render.filepath = filepath + name.strip() + '-'
bpy.ops.render.render("INVOKE_DEFAULT")
elif self.type == 'VIEW':
for obj in bpy.data.objects:
if obj in list(collection.objects):
obj.hide_viewport = False
context.scene.render.filepath = filepath + name.strip() + '-'
bpy.ops.render.opengl()
for col in collection.children:
if not col.hide_viewport:
path = bpy.path.abspath(os.path.join(filepath, col.name.strip(), ''))
self.create_output_folder(path)
self.render_combined_objects(context, collection=col, filepath=path, name=col.name)
def render_individual_object(self, context, collection: bpy.types.Collection, filepath: str):
for object in bpy.data.objects:
if object.type not in {"CAMERA", "LIGHT"}:
object.hide_render = True
object.hide_viewport = True
if collection.objects:
for object in collection.objects:
if self.type == 'ANIMATION':
object.hide_render = False
context.scene.render.filepath = filepath + object.name.strip() + '-'
bpy.ops.render.render("INVOKE_DEFAULT")
object.hide_render = True
elif self.type == 'VIEW':
object.hide_viewport = False
context.scene.render.filepath = filepath + object.name.strip() + '-'
bpy.ops.render.opengl()
object.hide_viewport = True
for col in collection.children:
if not col.hide_viewport:
path = bpy.path.abspath(os.path.join(filepath, col.name.strip(), ''))
self.create_output_folder(path)
self.render_individual_object(context, collection=col, filepath=path)
def execute(self, context):
self.rendering = True
self.collection = bpy.data.collections['Cube']
self.path = bpy.app.tempdir
self._timer = context.window_manager.event_timer_add(0.5, window=context.window)
context.window_manager.modal_handler_add(self)
return {"RUNNING_MODAL"}
def modal(self, context, event):
if event.type == 'TIMER':
if self.rendering:
filepath = os.path.join(self.path, self.collection.name.strip(), '')
self.create_output_folder(filepath)
if self.mode == 'COMBINED':
self.render_combined_objects(context, collection=self.collection, filepath=filepath, name=self.collection.name)
else:
self.render_individual_object(context, collection=self.collection, filepath=filepath)
for object in bpy.data.objects:
if object.type not in {"CAMERA", "LIGHT"}:
object.hide_render = False
object.hide_viewport = False
self.rendering = False
else:
context.window_manager.event_timer_remove(self._timer)
return {"FINISHED"}
return {"PASS_THROUGH"}
def register():
bpy.utils.register_class(RENDER_OT_render_frames)
def unregister():
bpy.utils.unregister_class(RENDER_OT_render_frames)
if __name__ == "__main__":
register()
But when I try to render child collection i.e. Suzanne
it crashes blender.
Please provide a better solution.