#!/usr/bin/env python3 import json import re from utilities.render_worker import * class BlenderRenderWorker(BaseRenderWorker): renderer = 'Blender' render_engine = 'blender' supported_extensions = ['.blend'] install_paths = ['/Applications/Blender.app/Contents/MacOS/Blender'] supported_export_formats = ['TGA', 'RAWTGA', 'JPEG', 'IRIS', 'IRIZ', 'AVIRAW', 'AVIJPEG', 'PNG', 'BMP', 'HDR', 'TIFF', 'OPEN_EXR', 'OPEN_EXR_MULTILAYER', 'MPEG', 'CINEON', 'DPX', 'DDS', 'JP2'] def __init__(self, input_path, output_path, args=None): super(BlenderRenderWorker, self).__init__(input_path=input_path, output_path=output_path, ignore_extensions=False, args=args) # Args self.engine = self.args.get('engine', 'BLENDER_EEVEE').upper() self.export_format = self.args.get('export_format', None) or 'JPEG' self.camera = self.args.get('camera', None) self.render_all_frames = self.args.get('render_all_frames', False) self.frame_to_render = 0 # Stats self.__frame_percent_complete = 0.0 # Scene Info self.scene_info = get_scene_info(input_path) self.total_frames = int(self.scene_info.get('frame_end', 0)) self.current_frame = int(self.scene_info.get('frame_start', 0)) self.resolution = {'x': int(self.scene_info.get('resolution_x', 0)), 'y': int(self.scene_info.get('resolution_y', 0))} @classmethod def version(cls): version = None try: render_path = cls.renderer_path() if render_path: ver_out = subprocess.check_output([render_path, '-v']) version = ver_out.decode('utf-8').splitlines()[0].replace('Blender', '').strip() except Exception as e: logging.error(f'Failed to get {cls.renderer} version: {e}') return version def _generate_subprocess(self): cmd = [self.renderer_path()] if self.args.get('background', True): # optionally run render not in background cmd.append('-b') cmd.append(self.input_path) if self.camera: cmd.extend(['--python-expr', f"import bpy;bpy.context.scene.camera = bpy.data.objects['{self.camera}'];"]) cmd.extend(['-E', self.engine, '-o', self.output_path, '-F', self.export_format]) # all frames or single cmd.extend(['-a'] if self.render_all_frames else ['-f', str(self.frame_to_render)]) return cmd def _parse_stdout(self, line): pattern = re.compile( r'Fra:(?P\d*).*Mem:(?P\S+).*Time:(?P