Exemple #1
0
def getWriteParams(i_app, i_afparams, i_wnode):
    o_params = dict()

    pnames = ['filename']
    for pname in pnames:
        par = i_wnode.getParam(pname)
        if par:
            o_params[pname] = par.getValue()

    if len(o_params) == 0:
        NatronGui.natron.warningDialog(
            'Error',
            'No "filename" parameter found on "%s"' % i_wnode.getLabel())
        return None

    o_params['afanasy'] = False
    o_params['nodelabel'] = i_wnode.getLabel()
    o_params['nodename'] = i_wnode.getScriptName()

    files = o_params['filename']
    files = afcommon.patternFromStdC(files)
    files = afcommon.patternFromDigits(files)
    files = replaceProjectPaths(i_app, files)
    o_params['files'] = [files]

    return o_params
Exemple #2
0
def getWriteParams( i_app, i_afparams, i_wnode):
	o_params = dict()

	pnames = ['filename']
	for pname in pnames:
		par = i_wnode.getParam(pname)
		if par:
			o_params[pname] = par.getValue()

	if len(o_params) == 0:
		NatronGui.natron.warningDialog('Error','No "filename" parameter found on "%s"' % i_wnode.getLabel())
		return None

	o_params['afanasy'] = False
	o_params['nodelabel'] = i_wnode.getLabel()
	o_params['nodename'] = i_wnode.getScriptName()

	files = o_params['filename']
	files = afcommon.patternFromStdC(files)
	files = afcommon.patternFromDigits(files)
	files = replaceProjectPaths( i_app, files)
	o_params['files'] = [files]

	return o_params
Exemple #3
0
    def launch(self, *args, **kwargs):
        """launch renderer command
        """
        # do nothing if there is no window (called externally)
        if not self.window:
            return

        # warn the user about the ignore settings
        try:
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            ignore_attrs = [
                'ignoreSubdivision', 'ignoreDisplacement', 'ignoreBump',
                'ignoreMotionBlur'
            ]

            attr_values = [(attr, dAO.getAttr(attr)) for attr in ignore_attrs
                           if dAO.getAttr(attr) is True]

            if any(attr_values):
                msg_text = '<br>'.join(
                    map(lambda x: '%s: %s' % (x[0], x[1]), attr_values))

                response = pm.confirmDialog(
                    title='Ignore These Settings?',
                    message=
                    'You have ignored:<br><br>%s<br><br><b>Is that ok?</b>' %
                    msg_text,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return
        except pm.MayaNodeError:
            # no Arnold
            pass

        # check if rendering with persp camera
        try:
            wrong_camera_names = [
                'perspShape',
                'topShape',
                'sideShape',
                'fontShape',
                'persp1Shape',
                'perspShape1',
            ]
            renderable_cameras = [
                node for node in pm.ls(type='camera')
                if node.getAttr('renderable')
            ]
            if any(
                    map(lambda x: x.name() in wrong_camera_names,
                        renderable_cameras)):
                response = pm.confirmDialog(
                    title='Rendering with Persp?',
                    message=
                    'You are rendering with <b>Persp Camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return

            if len(renderable_cameras) > 1:
                response = pm.confirmDialog(
                    title='Rendering more than one Camera?',
                    message=
                    'You are rendering <b>more than one camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return
            elif len(renderable_cameras) == 0:
                pm.confirmDialog(
                    title='No <b>Renderable</b> camera!!!',
                    message='There is no <b>renderable camera<b>!!!',
                    button=['Ok'],
                    defaultButton='Ok',
                    cancelButton='Ok',
                    dismissString='Ok')
                return

        except pm.MayaNodeError:
            # no default render globals node
            pass

        # get values
        start_frame = pm.intField('cgru_afanasy__start_frame', q=1, v=1)
        end_frame = pm.intField('cgru_afanasy__end_frame', q=1, v=1)
        frames_per_task = \
            pm.intField('cgru_afanasy__frames_per_task', q=1, v=1)
        by_frame = pm.intField('cgru_afanasy__by_frame', q=1, v=1)
        hosts_mask = pm.textField('cgru_afanasy__hosts_mask', q=1, text=True)
        hosts_exclude = pm.textField('cgru_afanasy__hosts_exclude',
                                     q=1,
                                     text=True)
        separate_layers = \
            pm.checkBox('cgru_afanasy__separate_layers', q=1, v=1)
        pause = pm.checkBox('cgru_afanasy__paused', q=1, v=1)
        life_time = pm.intField('cgru_afanasy__life_time', q=1, v=1)

        # check values
        if start_frame > end_frame:
            temp = end_frame
            end_frame = start_frame
            start_frame = temp

        frames_per_task = max(1, frames_per_task)
        by_frame = max(1, by_frame)

        # store without quota sign
        hosts_mask = hosts_mask.replace('"', '')
        hosts_exclude = hosts_exclude.replace('"', '')

        # store field values
        pm.optionVar['cgru_afanasy__start_frame_ov'] = start_frame
        pm.optionVar['cgru_afanasy__end_frame_ov'] = end_frame
        pm.optionVar['cgru_afanasy__frames_per_task_ov'] = frames_per_task
        pm.optionVar['cgru_afanasy__by_frame_ov'] = by_frame
        pm.optionVar['cgru_afanasy__hosts_mask_ov'] = hosts_mask
        pm.optionVar['cgru_afanasy__hosts_exclude_ov'] = hosts_exclude
        pm.optionVar['cgru_afanasy__separate_layers_ov'] = separate_layers
        pm.optionVar['cgru_afanasy__life_time_ov'] = life_time

        # get paths
        scene_name = pm.sceneName()
        datetime = '%s%s' % (time.strftime('%y%m%d-%H%M%S-'),
                             str(time.time() - int(time.time()))[2:5])

        filename = '%s.%s.mb' % (scene_name, datetime)

        project_path = pm.workspace(q=1, rootDirectory=1)

        # get output paths, set the RenderPass token to Beauty,
        # this will at least guarantee to get something
        outputs = \
            pm.renderSettings(
                fullPath=1, firstImageName=1, lastImageName=1,
                leaveUnmatchedTokens=1, customTokenString="RenderPass=Beauty"
            )

        job_name = os.path.basename(scene_name)

        logger.debug('%ss %se %sr' % (start_frame, end_frame, by_frame))
        logger.debug('scene        = %s' % scene_name)
        logger.debug('file         = %s' % filename)
        logger.debug('job_name     = %s' % job_name)
        logger.debug('project_path = %s' % project_path)
        logger.debug('outputs      = %s' % outputs)

        if pm.checkBox('cgru_afanasy__close', q=1, v=1):
            pm.deleteUI(self.window)

        drg = pm.PyNode('defaultRenderGlobals')
        render_engine = drg.getAttr('currentRenderer')

        job = af.Job(job_name)

        stored_log_level = None
        if render_engine == 'arnold':
            # set the verbosity level to warning+info
            aro = pm.PyNode('defaultArnoldRenderOptions')
            stored_log_level = aro.getAttr('log_verbosity')
            aro.setAttr('log_verbosity', 1)
            # set output to console
            aro.setAttr("log_to_console", 1)
        elif render_engine == 'redshift':
            # set the verbosity level to detailed+info
            redshift = pm.PyNode('redshiftOptions')
            stored_log_level = redshift.logLevel.get()
            redshift.logLevel.set(2)

        # save file
        pm.saveAs(filename, force=1, type='mayaBinary')

        # rename back to original name
        pm.renameFile(scene_name)

        # create the render command
        mrc = MayaRenderCommandBuilder(name=job_name,
                                       file_full_path=filename,
                                       render_engine=render_engine,
                                       project=project_path,
                                       by_frame=by_frame)

        # submit renders
        blocks = []
        if separate_layers:
            # render each layer separately
            rlm = pm.PyNode('renderLayerManager')
            layers = [
                layer for layer in rlm.connections() if layer.renderable.get()
            ]

            for layer in layers:
                mrc_layer = copy.copy(mrc)
                layer_name = layer.name()
                mrc_layer.name = layer_name
                mrc_layer.render_layer = layer_name

                # create a new block for this layer
                block = af.Block(
                    layer_name,
                    renderer_to_block_type.get(render_engine, 'maya'))

                block.setFiles(
                    afcommon.patternFromDigits(
                        afcommon.patternFromStdC(
                            afcommon.patternFromPaths(outputs[0],
                                                      outputs[1]))).split(';'))
                block.setNumeric(start_frame, end_frame, frames_per_task,
                                 by_frame)
                block.setCommand(mrc_layer.build_command())

                blocks.append(block)
        else:
            # create only one block
            block = af.Block('All Layers',
                             renderer_to_block_type.get(render_engine, 'maya'))

            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(
                        afcommon.patternFromPaths(outputs[0],
                                                  outputs[1]))).split(';'))
            block.setNumeric(start_frame, end_frame, frames_per_task, by_frame)
            block.setCommand(mrc.build_command())

            blocks.append(block)

        job.setFolder('input', os.path.dirname(filename))
        job.setFolder('output', os.path.dirname(outputs[0]))
        job.setHostsMask(hosts_mask)
        job.setHostsMaskExclude(hosts_exclude)
        if life_time > 0:
            job.setTimeLife(life_time * 3600)

        job.setCmdPost('deletefiles "%s"' % os.path.abspath(filename))
        if pause:
            job.offline()

        # add blocks
        job.blocks.extend(blocks)

        status, data = job.send()
        if not status:
            pm.PopupError('Something went wrong!')
        print('data: %s' % data)

        # restore log level
        if render_engine == 'arnold':
            aro = pm.PyNode('defaultArnoldRenderOptions')
            aro.setAttr('log_verbosity', stored_log_level)
            # disable set output to console
            aro.setAttr("log_to_console", 0)
        elif render_engine == 'redshift':
            redshift = pm.PyNode('redshiftOptions')
            redshift.logLevel.set(stored_log_level)
Exemple #4
0
if len(sys.argv) < 2:
    print('\nUsage: To check common functions class launch:')
    print('%s [func] [args...]\n' % os.path.basename(sys.argv[0]))
    sys.exit(1)

if sys.argv[1] == 'pat2':
    if len(sys.argv) < 4:
        print('Usage: %s %s str1 str2' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromPaths(sys.argv[2], sys.argv[3]))
elif sys.argv[1] == 'fillnum':
    if len(sys.argv) < 5:
        print('Usage: %s %s pattern start end' % (sys.argv[0], sys.argv[1]))
    else:
        print(
            afcommon.fillNumbers(sys.argv[2], int(sys.argv[3]),
                                 int(sys.argv[4])))
elif sys.argv[1] == 'patc':
    if len(sys.argv) < 3:
        print('Usage: %s %s str' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromStdC(sys.argv[2], True))
elif sys.argv[1] == 'patd':
    if len(sys.argv) < 3:
        print('Usage: %s %s str' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromDigits(sys.argv[2], True))
else:
    print('Unknown command: "%s"' % sys.argv[1])
Exemple #5
0
    def launch(self, *args, **kwargs):
        """launch renderer command
        """
        # do nothing if there is no window (called externally)
        if not self.window:
            return

        # warn the user about the ignore settings
        try:
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            ignore_attrs = [
                'ignoreSubdivision',
                'ignoreDisplacement',
                'ignoreBump',
                'ignoreMotionBlur'
            ]

            attr_values = [
                (attr, dAO.getAttr(attr))
                for attr in ignore_attrs
                if dAO.getAttr(attr) is True
            ]

            if any(attr_values):
                msg_text = '<br>'.join(
                    map(
                        lambda x: '%s: %s' % (x[0], x[1]),
                        attr_values
                    )
                )

                response = pm.confirmDialog(
                    title='Ignore These Settings?',
                    message='You have ignored:<br><br>%s<br><br><b>Is that ok?</b>' % msg_text,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
        except pm.MayaNodeError:
            # no Arnold
            pass

        # check if rendering with persp camera
        try:
            wrong_camera_names = [
                'perspShape',
                'topShape',
                'sideShape',
                'fontShape',

                'persp1Shape',
                'perspShape1',
            ]
            renderable_cameras = [node for node in pm.ls(type='camera') if node.getAttr('renderable')]
            if any(map(lambda x: x.name() in wrong_camera_names, renderable_cameras)):
                response = pm.confirmDialog(
                    title='Rendering with Persp?',
                    message='You are rendering with <b>Persp Camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return

            if len(renderable_cameras) > 1:
                response = pm.confirmDialog(
                    title='Rendering more than one Camera?',
                    message='You are rendering <b>more than one camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
            elif len(renderable_cameras) == 0:
                pm.confirmDialog(
                    title='No <b>Renderable</b> camera!!!',
                    message='There is no <b>renderable camera<b>!!!',
                    button=['Ok'],
                    defaultButton='Ok',
                    cancelButton='Ok',
                    dismissString='Ok'
                )
                return

        except pm.MayaNodeError:
            # no default render globals node
            pass

        # get values
        start_frame = pm.intField('cgru_afanasy__start_frame', q=1, v=1)
        end_frame = pm.intField('cgru_afanasy__end_frame', q=1, v=1)
        frames_per_task = \
            pm.intField('cgru_afanasy__frames_per_task', q=1, v=1)
        by_frame = pm.intField('cgru_afanasy__by_frame', q=1, v=1)
        hosts_mask = pm.textField('cgru_afanasy__hosts_mask', q=1, text=True)
        hosts_exclude = pm.textField('cgru_afanasy__hosts_exclude', q=1, text=True)
        separate_layers = \
            pm.checkBox('cgru_afanasy__separate_layers', q=1, v=1)
        pause = pm.checkBox('cgru_afanasy__paused', q=1, v=1)
        life_time = pm.intField('cgru_afanasy__life_time', q=1, v=1)

        # check values
        if start_frame > end_frame:
            temp = end_frame
            end_frame = start_frame
            start_frame = temp

        frames_per_task = max(1, frames_per_task)
        by_frame = max(1, by_frame)

        # store without quota sign
        hosts_mask = hosts_mask.replace('"', '')
        hosts_exclude = hosts_exclude.replace('"', '')

        # store field values
        pm.optionVar['cgru_afanasy__start_frame_ov'] = start_frame
        pm.optionVar['cgru_afanasy__end_frame_ov'] = end_frame
        pm.optionVar['cgru_afanasy__frames_per_task_ov'] = frames_per_task
        pm.optionVar['cgru_afanasy__by_frame_ov'] = by_frame
        pm.optionVar['cgru_afanasy__hosts_mask_ov'] = hosts_mask
        pm.optionVar['cgru_afanasy__hosts_exclude_ov'] = hosts_exclude
        pm.optionVar['cgru_afanasy__separate_layers_ov'] = separate_layers
        pm.optionVar['cgru_afanasy__life_time_ov'] = life_time

        # get paths
        scene_name = pm.sceneName()
        datetime = '%s%s' % (
            time.strftime('%y%m%d-%H%M%S-'),
            str(time.time() - int(time.time()))[2:5]
        )

        filename = '%s.%s.mb' % (scene_name, datetime)

        project_path = pm.workspace(q=1, rootDirectory=1)

        # get output paths, set the RenderPass token to Beauty,
        # this will at least guarantee to get something
        outputs = \
            pm.renderSettings(
                fullPath=1, firstImageName=1, lastImageName=1,
                leaveUnmatchedTokens=1, customTokenString="RenderPass=Beauty"
            )

        job_name = os.path.basename(scene_name)

        logger.debug('%ss %se %sr' % (start_frame, end_frame, by_frame))
        logger.debug('scene        = %s' % scene_name)
        logger.debug('file         = %s' % filename)
        logger.debug('job_name     = %s' % job_name)
        logger.debug('project_path = %s' % project_path)
        logger.debug('outputs      = %s' % outputs)

        if pm.checkBox('cgru_afanasy__close', q=1, v=1):
            pm.deleteUI(self.window)

        drg = pm.PyNode('defaultRenderGlobals')
        render_engine = drg.getAttr('currentRenderer')

        job = af.Job(job_name)

        stored_log_level = None
        if render_engine == 'arnold':
            # set the verbosity level to warning+info
            aro = pm.PyNode('defaultArnoldRenderOptions')
            stored_log_level = aro.getAttr('log_verbosity')
            aro.setAttr('log_verbosity', 1)
            # set output to console
            aro.setAttr("log_to_console", 1)
        elif render_engine == 'redshift':
            # set the verbosity level to detailed+info
            redshift = pm.PyNode('redshiftOptions')
            stored_log_level = redshift.logLevel.get()
            redshift.logLevel.set(2)

        # save file
        pm.saveAs(
            filename,
            force=1,
            type='mayaBinary'
        )

        # rename back to original name
        pm.renameFile(scene_name)

        # create the render command
        mrc = MayaRenderCommandBuilder(
            name=job_name, file_full_path=filename,
            render_engine=render_engine, project=project_path,
            by_frame=by_frame
        )

        # submit renders
        blocks = []
        if separate_layers:
            # render each layer separately
            rlm = pm.PyNode('renderLayerManager')
            layers = [layer for layer in rlm.connections()
                      if layer.renderable.get()]

            for layer in layers:
                mrc_layer = copy.copy(mrc)
                layer_name = layer.name()
                mrc_layer.name = layer_name
                mrc_layer.render_layer = layer_name

                # create a new block for this layer
                block = af.Block(
                    layer_name,
                    renderer_to_block_type.get(render_engine, 'maya')
                )

                block.setFiles(
                    afcommon.patternFromDigits(
                        afcommon.patternFromStdC(
                            afcommon.patternFromPaths(outputs[0], outputs[1])
                        )
                    ).split(';')
                )
                block.setNumeric(
                    start_frame, end_frame, frames_per_task, by_frame
                )
                block.setCommand(mrc_layer.build_command())

                blocks.append(block)
        else:
            # create only one block
            block = af.Block(
                'All Layers',
                renderer_to_block_type.get(render_engine, 'maya')
            )

            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(
                        afcommon.patternFromPaths(outputs[0], outputs[1])
                    )
                ).split(';')
            )
            block.setNumeric(
                start_frame, end_frame, frames_per_task, by_frame
            )
            block.setCommand(mrc.build_command())

            blocks.append(block)

        job.setFolder('input', os.path.dirname(filename))
        job.setFolder('output', os.path.dirname(outputs[0]))
        job.setHostsMask(hosts_mask)
        job.setHostsMaskExclude(hosts_exclude)
        if life_time > 0:
            job.setTimeLife(life_time * 3600)

        job.setCmdPost('deletefiles "%s"' % os.path.abspath(filename))
        if pause:
            job.offline()

        # add blocks
        job.blocks.extend(blocks)

        status, data = job.send()
        if not status:
            pm.PopupError('Something went wrong!')
        print('data: %s' % data)

        # restore log level
        if render_engine == 'arnold':
            aro = pm.PyNode('defaultArnoldRenderOptions')
            aro.setAttr('log_verbosity', stored_log_level)
            # disable set output to console
            aro.setAttr("log_to_console", 0)
        elif render_engine == 'redshift':
            redshift = pm.PyNode('redshiftOptions')
            redshift.logLevel.set(stored_log_level)
Exemple #6
0
			block.setSequential( seq)

		if scenetype == 'max':
			block.setCommand(cmd, False, False)
		else:
			block.setCommand(cmd)

		block.setCapacity(capacity)
		block.setVariableCapacity(capmin, capmax)
		if maxruntime != 0:
			block.setTasksMaxRunTime(maxruntime)

		if images != '':
			block.setFiles(
				afcommon.patternFromDigits(
					afcommon.patternFromStdC(images)
				).split(';')
			)

		blocks.append(block)
		i += 1

	if mname != '' and images != '':
		block = af.Block(mname + '-movie', 'movgen')
		blocks.append(block)
		block.setWorkingDirectory(pwd)
		block.setDependMask(blocknames[-1])
		task = af.Task(mname)
		block.tasks.append(task)
		cmd = os.getenv('CGRU_LOCATION')
		cmd = os.path.join(cmd, 'utilities')
Exemple #7
0
Fichier : job.py Projet : CGRU/cgru
        if int(fr[2]) < 0:
            negative_pertask = True

    if not Options.stringtype and not negative_pertask:
        cmd = 'task.py'
        cmd = "\"%s\"" % os.path.join(os.getcwd(), cmd)
        cmd = "%s %s" % (os.getenv('CGRU_PYTHONEXE','python'), cmd)
        cmd += ' --exitstatus %d ' % Options.exitstatus

        if Options.filesout:
            cmd += ' --filesout "%s"' % Options.filesout
            block.skipExistingFiles()
            block.checkRenderedFiles(100)
            files = []
            for afile in Options.filesout.split(';'):
                files.append(afcommon.patternFromStdC(afile))
            block.setFiles(files)

        cmd += '%(str_capacity)s%(str_hosts)s -s @#@ -e @#@ ' \
               '-i %(increment)d -t %(timesec)g -r %(randtime)g --pkp %(pkp)d ' \
               '-v %(verbose)d @####@ @#####@ @#####@ @#####@' % vars()

        block.setCommand(cmd, False)

        if Options.frames != '':
            fr = frames[b].split('/')
            block.setNumeric(int(fr[0]), int(fr[1]), int(fr[2]), int(fr[3]))
        else:
            block.setNumeric(1, numtasks, Options.pertask, increment)

    else:
Exemple #8
0
            block.setSequential(seq)

        if scenetype == 'max':
            block.setCommand(cmd, False, False)
        else:
            block.setCommand(cmd)

        block.setCapacity(capacity)
        block.setVariableCapacity(capmin, capmax)
        if maxruntime != 0:
            block.setTasksMaxRunTime(maxruntime)

        if images != '':
            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(images)
                ).split(';')
            )

        blocks.append(block)

    if mname != '' and images != '':
        block = af.Block(mname + '-movie', 'movgen')
        blocks.append(block)
        block.setWorkingDirectory(pwd)
        block.setDependMask(blocknames[-1])
        task = af.Task(mname)
        block.tasks.append(task)
        cmd = os.getenv('CGRU_LOCATION')
        cmd = os.path.join(cmd, 'utilities')
        cmd = os.path.join(cmd, 'moviemaker')
Exemple #9
0
    def launch(self, *args, **kwargs):
        """launch renderer command
        """
        # do nothing if there is no window (called externally)
        if not self.window:
            return

        # warn the user about the ignore settings
        try:
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            ignore_attrs = [
                'ignoreSubdivision',
                'ignoreDisplacement',
                'ignoreBump',
                'ignoreMotionBlur'
            ]

            attr_values = [
                (attr, dAO.getAttr(attr))
                for attr in ignore_attrs
                if dAO.getAttr(attr) is True
            ]

            if any(attr_values):
                msg_text = '<br>'.join(
                    map(
                        lambda x: '%s: %s' % (x[0], x[1]),
                        attr_values
                    )
                )

                response = pm.confirmDialog(
                    title='Ignore These Settings?',
                    message='You have ignored:<br><br>%s<br><br><b>Is that ok?</b>' % msg_text,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
        except pm.MayaNodeError:
            # no Arnold
            pass

        # check if rendering with persp camera
        try:
            wrong_camera_names = [
                'perspShape',
                'topShape',
                'sideShape',
                'fontShape',

                'persp1Shape',
                'perspShape1',
            ]
            renderable_cameras = [node for node in pm.ls(type='camera') if node.getAttr('renderable')]
            if any(map(lambda x: x.name() in wrong_camera_names, renderable_cameras)):
                response = pm.confirmDialog(
                    title='Rendering with Persp?',
                    message='You are rendering with <b>Persp Camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return

            if len(renderable_cameras) > 1:
                response = pm.confirmDialog(
                    title='Rendering more than one Camera?',
                    message='You are rendering <b>more than one camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
            elif len(renderable_cameras) == 0:
                pm.confirmDialog(
                    title='No <b>Renderable</b> camera!!!',
                    message='There is no <b>renderable camera<b>!!!',
                    button=['Ok'],
                    defaultButton='Ok',
                    cancelButton='Ok',
                    dismissString='Ok'
                )
                return

        except pm.MayaNodeError:
            # no default render globals node
            pass

        drg = pm.PyNode('defaultRenderGlobals')
        render_engine = drg.getAttr('currentRenderer')
        # RENDERER SPECIFIC CHECKS

        if render_engine == 'redshift':
            # if the renderer is RedShift
            # check if unifiedDisableDivision is 1 which will take too much time
            # to render
            dro = pm.PyNode('redshiftOptions')
            if dro.unifiedDisableDivision.get() == 1:
                response = pm.confirmDialog(
                    title="Enabled **Don't Automatically Reduce Samples of Other Effects**",
                    message='It is not allowed to render with the following option is enabled:<br>'
                            '<br>'
                            "Don't Automatically Reduce Samples of Other Effects: Enabled<br>"
                            "<br>"
                            "Please DISABLE it!",
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

        elif render_engine == 'arnold':
            # check if the samples are too high
            dAO = pm.PyNode('defaultArnoldRenderOptions')


            aa_samples = dAO.AASamples.get()
            diff_samples = dAO.GIDiffuseSamples.get()
            glossy_samples = dAO.GIGlossySamples.get()
            if int(pm.about(v=1)) >= 2017:
                sss_samples = dAO.GISssSamples.get()
            else:
                sss_samples = dAO.sssBssrdfSamples.get()

            total_diff_samples = aa_samples**2 * diff_samples**2
            total_glossy_samples = aa_samples**2 * glossy_samples**2
            total_sss_samples = aa_samples**2 * sss_samples**2

            max_allowed_diff_samples = 225
            max_allowed_glossy_samples = 100
            max_allowed_sss_samples = 450

            if total_diff_samples > max_allowed_diff_samples:
                pm.confirmDialog(
                    title="Too Much Diffuse Samples!!!",
                    message='You are using too much DIFFUSE SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of Diffuse '
                            'Samples!!!' % max_allowed_diff_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            if total_glossy_samples > max_allowed_glossy_samples:
                pm.confirmDialog(
                    title="Too Much Glossy Samples!!!",
                    message='You are using too much GLOSSY SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of Glossy '
                            'Samples!!!' % max_allowed_glossy_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            if total_sss_samples > max_allowed_sss_samples:
                pm.confirmDialog(
                    title="Too Much SSS Samples!!!",
                    message='You are using too much SSS SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of SSS '
                            'Samples!!!' % max_allowed_sss_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # check Light Samples
            # check point lights with zero radius but more than one samples
            all_point_lights = pm.ls(type='pointLight')
            ridiculous_point_lights = []
            for point_light in all_point_lights:
                if point_light.aiRadius.get() < 0.1 and point_light.aiSamples.get() > 1:
                    ridiculous_point_lights.append(point_light)

            if ridiculous_point_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Point Lights!!!",
                    message='You are using too much SAMPLES (>1)<br>'
                            '<br>'
                            'on <b>Point lights with zero radius</b><br>'
                            '<br>'
                            'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # Check area lights with more than 2 samples
            all_area_lights = pm.ls(type=['areaLight', 'aiAreaLight'])
            ridiculous_area_lights = []
            for area_light in all_area_lights:
                if area_light.aiSamples.get() > 2:
                    ridiculous_area_lights.append(area_light)

            if ridiculous_area_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Area Lights!!!",
                    message='You are using too much SAMPLES (>2) on<br>'
                            '<br>'
                            '<b>Area Lights</b><br>'
                            '<br>'
                            'Please reduce the samples to 2',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # Check directional lights with angle == 0 and samples > 1
            all_directional_lights = pm.ls(type='directionalLight')
            ridiculous_directional_lights = []
            for directional_light in all_directional_lights:
                if directional_light.aiAngle.get() == 0 and directional_light.aiSample.get() > 1:
                    ridiculous_directional_lights.append(directional_light)

            if ridiculous_directional_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Directional Lights!!!",
                    message='You are using too much SAMPLES (>1) on <br>'
                            '<br>'
                            '<b>Directional lights with zero angle</b><br>'
                            '<br>'
                            'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

        # get values
        start_frame = pm.intField('cgru_afanasy__start_frame', q=1, v=1)
        end_frame = pm.intField('cgru_afanasy__end_frame', q=1, v=1)
        frames_per_task = \
            pm.intField('cgru_afanasy__frames_per_task', q=1, v=1)
        by_frame = pm.intField('cgru_afanasy__by_frame', q=1, v=1)
        hosts_mask = pm.textField('cgru_afanasy__hosts_mask', q=1, text=True)
        hosts_exclude = pm.textField('cgru_afanasy__hosts_exclude', q=1, text=True)
        separate_layers = \
            pm.checkBox('cgru_afanasy__separate_layers', q=1, v=1)
        pause = pm.checkBox('cgru_afanasy__paused', q=1, v=1)
        life_time = pm.intField('cgru_afanasy__life_time', q=1, v=1)

        # check values
        if start_frame > end_frame:
            temp = end_frame
            end_frame = start_frame
            start_frame = temp

        frames_per_task = max(1, frames_per_task)
        by_frame = max(1, by_frame)

        # store without quota sign
        hosts_mask = hosts_mask.replace('"', '')
        hosts_exclude = hosts_exclude.replace('"', '')

        # store field values
        pm.optionVar['cgru_afanasy__start_frame_ov'] = start_frame
        pm.optionVar['cgru_afanasy__end_frame_ov'] = end_frame
        pm.optionVar['cgru_afanasy__frames_per_task_ov'] = frames_per_task
        pm.optionVar['cgru_afanasy__by_frame_ov'] = by_frame
        pm.optionVar['cgru_afanasy__hosts_mask_ov'] = hosts_mask
        pm.optionVar['cgru_afanasy__hosts_exclude_ov'] = hosts_exclude
        pm.optionVar['cgru_afanasy__separate_layers_ov'] = separate_layers
        pm.optionVar['cgru_afanasy__life_time_ov'] = life_time

        # get paths
        scene_name = pm.sceneName()
        datetime = '%s%s' % (
            time.strftime('%y%m%d-%H%M%S-'),
            str(time.time() - int(time.time()))[2:5]
        )

        filename = '%s.%s.mb' % (scene_name, datetime)

        project_path = pm.workspace(q=1, rootDirectory=1)

        outputs = \
            pm.renderSettings(fullPath=1, firstImageName=1, lastImageName=1)

        # job_name = os.path.basename(scene_name)
        job_name = self.generate_job_name()

        logger.debug('%ss %se %sr' % (start_frame, end_frame, by_frame))
        logger.debug('scene        = %s' % scene_name)
        logger.debug('file         = %s' % filename)
        logger.debug('job_name     = %s' % job_name)
        logger.debug('project_path = %s' % project_path)
        logger.debug('outputs      = %s' % outputs)

        if pm.checkBox('cgru_afanasy__close', q=1, v=1):
            pm.deleteUI(self.window)



        job = af.Job(job_name)

        stored_log_level = None
        if render_engine == 'arnold':
            # set the verbosity level to warning+info
            aro = pm.PyNode('defaultArnoldRenderOptions')
            stored_log_level = aro.getAttr('log_verbosity')
            aro.setAttr('log_verbosity', 1)
            # set output to console
            aro.setAttr("log_to_console", 1)
        elif render_engine == 'redshift':
            # set the verbosity level to detailed+info
            redshift = pm.PyNode('redshiftOptions')
            stored_log_level = redshift.logLevel.get()
            redshift.logLevel.set(2)

        # save file
        pm.saveAs(
            filename,
            force=1,
            type='mayaBinary'
        )

        # rename back to original name
        pm.renameFile(scene_name)

        # create the render command
        mrc = MayaRenderCommandBuilder(
            name=job_name, file_full_path=filename,
            render_engine=render_engine, project=project_path,
            by_frame=by_frame
        )

        # submit renders
        blocks = []
        if separate_layers:
            # render each layer separately
            rlm = pm.PyNode('renderLayerManager')
            layers = [layer for layer in rlm.connections()
                      if layer.renderable.get()]

            for layer in layers:
                mrc_layer = copy.copy(mrc)
                layer_name = layer.name()
                mrc_layer.name = layer_name
                mrc_layer.render_layer = layer_name

                # create a new block for this layer
                block = af.Block(
                    layer_name,
                    renderer_to_block_type.get(render_engine, 'maya')
                )

                block.setFiles(
                    afcommon.patternFromDigits(
                        afcommon.patternFromStdC(
                            afcommon.patternFromPaths(outputs[0], outputs[1])
                        )
                    ).split(';')
                )
                block.setNumeric(
                    start_frame, end_frame, frames_per_task, by_frame
                )
                block.setCommand(mrc_layer.build_command())

                blocks.append(block)
        else:
            # create only one block
            block = af.Block(
                'All Layers',
                renderer_to_block_type.get(render_engine, 'maya')
            )

            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(
                        afcommon.patternFromPaths(outputs[0], outputs[1])
                    )
                ).split(';')
            )
            block.setNumeric(
                start_frame, end_frame, frames_per_task, by_frame
            )
            block.setCommand(mrc.build_command())

            blocks.append(block)

        job.setFolder('input', os.path.dirname(filename))
        job.setFolder('output', os.path.dirname(outputs[0]))
        job.setHostsMask(hosts_mask)
        job.setHostsMaskExclude(hosts_exclude)
        if life_time > 0:
            job.setTimeLife(life_time * 3600)

        job.setCmdPost('deletefiles "%s"' % os.path.abspath(filename))
        if pause:
            job.offline()

        # add blocks
        job.blocks.extend(blocks)

        status, data = job.send()
        if not status:
            pm.PopupError('Something went wrong!')
        print('data: %s' % data)

        # restore log level
        if render_engine == 'arnold':
            aro = pm.PyNode('defaultArnoldRenderOptions')
            aro.setAttr('log_verbosity', stored_log_level)
            # disable set output to console
            aro.setAttr("log_to_console", 0)
        elif render_engine == 'redshift':
            redshift = pm.PyNode('redshiftOptions')
            redshift.logLevel.set(stored_log_level)
Exemple #10
0
    blockparsers.append(blockparser)
i = 0
for cmd in cmds:
    block = af.Block(blocknames[i], blocktype)
    if len(blockparsers):
        block.setParser(blockparsers[i])
    block.setWorkingDirectory(pwd)
    block.setNumeric(s, e, fpt, by)
    if scenetype == 'max': block.setCommand(cmd, False, False)
    else: block.setCommand(cmd)
    block.setCapacity(capacity)
    block.setVariableCapacity(capmin, capmax)
    if maxruntime != 0: block.setTasksMaxRunTime(maxruntime)
    if images != '':
        block.setFiles(
            afcommon.patternFromDigits(afcommon.patternFromStdC(images)))
    blocks.append(block)
    i += 1

# Create a Job:
job = af.Job(name)
job.setPriority(priority)
if maxruntasks != -1: job.setMaxRunningTasks(maxruntasks)
if hostsmask != '': job.setHostsMask(hostsmask)
if hostsexcl != '': job.setHostsMaskExclude(hostsexcl)
if dependmask != '': job.setDependMask(dependmask)
if dependglobal != '': job.setDependMaskGlobal(dependglobal)
if deletescene: job.setCmdPost('deletefiles "%s"' % os.path.abspath(scene))
if startpaused: job.offline()
if platform != '':
    if platform == 'any': job.setNeedOS('')
Exemple #11
0
            block.setSequential(seq)

        if scenetype == 'max':
            block.setCommand(cmd, False, False)
        else:
            block.setCommand(cmd)

        block.setCapacity(capacity)
        block.setVariableCapacity(capmin, capmax)
        if maxruntime != 0:
            block.setTasksMaxRunTime(maxruntime)

        if images != '':
            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(images)).split(';'))

        blocks.append(block)

    if mname != '' and images != '':
        block = af.Block(mname + '-movie', 'movgen')
        blocks.append(block)
        block.setWorkingDirectory(pwd)
        block.setDependMask(blocknames[-1])
        task = af.Task(mname)
        block.tasks.append(task)
        cmd = os.getenv('CGRU_LOCATION')
        cmd = os.path.join(cmd, 'utilities')
        cmd = os.path.join(cmd, 'moviemaker')
        cmd = os.path.join(cmd, 'makemovie.py')
        cmd = 'python "%s"' % cmd
Exemple #12
0
	blocknames.append( blockname)
if len(blockparsers) == 0 and blockparser != '':
	blockparsers.append( blockparser)
i = 0
for cmd in cmds:
	block = af.Block( blocknames[i], blocktype)
	if len( blockparsers):
		block.setParser( blockparsers[i])
	block.setWorkingDirectory( pwd )
	block.setNumeric( s, e, fpt, by)
	if scenetype == 'max': block.setCommand( cmd, False, False )
	else: block.setCommand( cmd )
	block.setCapacity( capacity)
	block.setVariableCapacity( capmin, capmax)
	if maxruntime != 0: block.setTasksMaxRunTime( maxruntime)
	if images != '': block.setFiles( afcommon.patternFromDigits( afcommon.patternFromStdC( images)))
	blocks.append( block)
	i += 1

# Create a Job:
job = af.Job( name)
job.setPriority( priority)
if maxruntasks	!= -1: job.setMaxRunningTasks( maxruntasks)
if hostsmask		!= '': job.setHostsMask( hostsmask)
if hostsexcl		!= '': job.setHostsMaskExclude( hostsexcl)
if dependmask	!= '': job.setDependMask( dependmask)
if dependglobal	!= '': job.setDependMaskGlobal( dependglobal)
if deletescene			: job.setCmdPost('deletefiles "%s"' % os.path.abspath(scene))
if startpaused			: job.offline()
if platform != '':
	if platform == 'any': job.setNeedOS('')
Exemple #13
0
	if options.frames != '':
		fr = frames[b].split('/')
		if int(fr[2]) < 0:
			negative_pertask = True

	if not options.stringtype and not negative_pertask:
		cmd = 'task.py'
		cmd = os.path.join(os.getcwd(), cmd)
		cmd = 'python "%s"' % cmd
		cmd += ' --exitstatus %d ' % options.exitstatus

		if options.fileout:
			cmd += ' --fileout "%s"' % options.fileout
			block.skipExistingFiles()
			block.checkRenderedFiles( 10, 1000000)
			block.setFiles([afcommon.patternFromStdC(options.fileout)])

		cmd += '%(str_capacity)s%(str_hosts)s -s @#@ -e @#@ ' \
			   '-i %(increment)d -t %(timesec)g -r %(randtime)g --pkp %(pkp)d ' \
			   '-v %(verbose)d @####@ @#####@ @#####@ @#####@' % vars()

		block.setCommand(cmd, False)

		if options.frames != '':
			fr = frames[b].split('/')
			block.setNumeric(int(fr[0]), int(fr[1]), int(fr[2]), int(fr[3]))
		else:
			block.setNumeric(1, numtasks, options.pertask, increment)

	else:
		block.setCommand(
Exemple #14
0
import afcommon

if len(sys.argv) < 2:
    print('\nUsage: To check common functions class launch:')
    print('%s [func] [args...]\n' % os.path.basename(sys.argv[0]))
    sys.exit(1)

if sys.argv[1] == 'pat2':
    if len(sys.argv) < 4:
        print('Usage: %s %s str1 str2' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromPaths(sys.argv[2], sys.argv[3]))
elif sys.argv[1] == 'fillnum':
    if len(sys.argv) < 5:
        print('Usage: %s %s pattern start end' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.fillNumbers(sys.argv[2], int(sys.argv[3]), int(sys.argv[4])))
elif sys.argv[1] == 'patc':
    if len(sys.argv) < 3:
        print('Usage: %s %s str' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromStdC(sys.argv[2], True))
elif sys.argv[1] == 'patd':
    if len(sys.argv) < 3:
        print('Usage: %s %s str' % (sys.argv[0], sys.argv[1]))
    else:
        print(afcommon.patternFromDigits(sys.argv[2], True))
else:
    print('Unknown command: "%s"' % sys.argv[1])
Exemple #15
0
        cmd += ' -c ' + services.service.str_capacity

    if Args.mhmin != -1 or Args.mhmax != -1:
        block.setMultiHost(Args.mhmin, Args.mhmax, Args.mhwaitmax, Args.mhsame,
                           Args.mhservice, Args.mhwaitsrv)
        if Args.mhignorelost:
            block.setSlaveLostIgnore()
        cmd += ' ' + services.service.str_hosts

    if Args.filesout:
        cmd += ' --filesout "%s"' % Args.filesout
        block.skipExistingFiles()
        block.checkRenderedFiles(100)
        files = []
        for afile in Args.filesout.split(';'):
            files.append(afcommon.patternFromStdC(afile))
        block.setFiles(files)

    if Args.stdoutfile:
        if not os.path.isfile(Args.stdoutfile):
            print('ERROR: File "%s" does not exist.')
            sys.exit(1)
        cmd += ' --stdoutfile "%s"' % Args.stdoutfile

    if not Args.stringtype and not negative_pertask:
        cmd += ' -s @#@ -e @#@ -i %(increment)d' \
               ' -t %(timesec)g -r %(randtime)g --pkp %(pkp)d' \
               ' -v %(verbose)d @####@ @#####@ @#####@ @#####@' % vars()

        if Args.frames != '':
            fr = frames[b].split('/')
Exemple #16
0
    def launch(self, *args, **kwargs):
        """launch renderer command
        """
        # do nothing if there is no window (called externally)
        if not self.window:
            return

        # warn the user about the ignore settings
        try:
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            ignore_attrs = [
                'ignoreSubdivision', 'ignoreDisplacement', 'ignoreBump',
                'ignoreMotionBlur'
            ]

            attr_values = [(attr, dAO.getAttr(attr)) for attr in ignore_attrs
                           if dAO.getAttr(attr) is True]

            if any(attr_values):
                msg_text = '<br>'.join(
                    map(lambda x: '%s: %s' % (x[0], x[1]), attr_values))

                response = pm.confirmDialog(
                    title='Ignore These Settings?',
                    message=
                    'You have ignored:<br><br>%s<br><br><b>Is that ok?</b>' %
                    msg_text,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return
        except (pm.MayaNodeError, pm.MayaAttributeError):
            # no Arnold
            pass

        # check if rendering with persp camera
        try:
            wrong_camera_names = [
                'perspShape',
                'topShape',
                'sideShape',
                'fontShape',
                'persp1Shape',
                'perspShape1',
            ]
            renderable_cameras = [
                node for node in pm.ls(type='camera')
                if node.getAttr('renderable')
            ]
            if any(
                    map(lambda x: x.name() in wrong_camera_names,
                        renderable_cameras)):
                response = pm.confirmDialog(
                    title='Rendering with Persp?',
                    message=
                    'You are rendering with <b>Persp Camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return

            if len(renderable_cameras) > 1:
                response = pm.confirmDialog(
                    title='Rendering more than one Camera?',
                    message=
                    'You are rendering <b>more than one camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')

                if response == 'No':
                    return
            elif len(renderable_cameras) == 0:
                pm.confirmDialog(
                    title='No <b>Renderable</b> camera!!!',
                    message='There is no <b>renderable camera<b>!!!',
                    button=['Ok'],
                    defaultButton='Ok',
                    cancelButton='Ok',
                    dismissString='Ok')
                return

        except pm.MayaNodeError:
            # no default render globals node
            pass

        drg = pm.PyNode('defaultRenderGlobals')
        render_engine = drg.getAttr('currentRenderer')
        # RENDERER SPECIFIC CHECKS

        if render_engine == 'redshift':
            # if the renderer is RedShift
            # check if unifiedDisableDivision is 1 which will take too much time
            # to render
            dro = pm.PyNode('redshiftOptions')
            if dro.unifiedDisableDivision.get() == 1:
                response = pm.confirmDialog(
                    title=
                    "Enabled **Don't Automatically Reduce Samples of Other Effects**",
                    message=
                    'It is not allowed to render with the following option is enabled:<br>'
                    '<br>'
                    "Don't Automatically Reduce Samples of Other Effects: Enabled<br>"
                    "<br>"
                    "Please DISABLE it!",
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            # Check dome light backgrounds
            domes_to_fix = []
            rs_domes = pm.ls(type='RedshiftDomeLight')
            if rs_domes:
                for rs_dome in rs_domes:
                    if rs_dome.getAttr('background_enable') == 1 \
                       or rs_dome.getAttr('backPlateEnabled') == 1:
                        domes_to_fix.append(rs_dome.name())

            if domes_to_fix:
                message = 'Some DomeLights have <b>BackGround Render ' \
                          'Enabled</b>:' \
                          '<br><br>%s<br><br>' \
                          'Are you Sure?' % '<br>'.join(domes_to_fix)

                response = pm.confirmDialog(
                    title='Dome Lights with Background Enabled?',
                    message=message,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No')
                if response == 'No':
                    return

            # abort on license fail
            dro.abortOnLicenseFail.set(1)

        elif render_engine == 'arnold':
            # check if the samples are too high
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            aa_samples = dAO.AASamples.get()
            diff_samples = dAO.GIDiffuseSamples.get()
            try:
                glossy_samples = dAO.GIGlossySamples.get()
            except AttributeError:
                glossy_samples = dAO.GISpecularSamples.get()
            if int(pm.about(v=1)) >= 2017:
                sss_samples = dAO.GISssSamples.get()
            else:
                sss_samples = dAO.sssBssrdfSamples.get()

            total_diff_samples = aa_samples**2 * diff_samples**2
            total_glossy_samples = aa_samples**2 * glossy_samples**2
            total_sss_samples = aa_samples**2 * sss_samples**2

            max_allowed_diff_samples = 225
            max_allowed_glossy_samples = 100
            max_allowed_sss_samples = 800

            if total_diff_samples > max_allowed_diff_samples:
                pm.confirmDialog(
                    title="Too Much Diffuse Samples!!!",
                    message='You are using too much DIFFUSE SAMPLES (>%s)<br>'
                    '<br>'
                    'Please either reduce AA samples of Diffuse '
                    'Samples!!!' % max_allowed_diff_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            if total_glossy_samples > max_allowed_glossy_samples:
                pm.confirmDialog(
                    title="Too Much Glossy Samples!!!",
                    message='You are using too much GLOSSY SAMPLES (>%s)<br>'
                    '<br>'
                    'Please either reduce AA samples of Glossy '
                    'Samples!!!' % max_allowed_glossy_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            if total_sss_samples > max_allowed_sss_samples:
                pm.confirmDialog(
                    title="Too Much SSS Samples!!!",
                    message='You are using too much SSS SAMPLES (>%s)<br>'
                    '<br>'
                    'Please either reduce AA samples of SSS '
                    'Samples!!!' % max_allowed_sss_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            # check Light Samples
            # check point lights with zero radius but more than one samples
            all_point_lights = pm.ls(type='pointLight')
            ridiculous_point_lights = []
            for point_light in all_point_lights:
                if point_light.aiRadius.get(
                ) < 0.1 and point_light.aiSamples.get() > 1:
                    ridiculous_point_lights.append(point_light)

            if ridiculous_point_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Point Lights!!!",
                    message='You are using too much SAMPLES (>1)<br>'
                    '<br>'
                    'on <b>Point lights with zero radius</b><br>'
                    '<br>'
                    'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            # Check area lights with more than 2 samples
            all_area_lights = pm.ls(type=['areaLight', 'aiAreaLight'])
            ridiculous_area_lights = []
            for area_light in all_area_lights:
                if area_light.aiSamples.get() > 2:
                    ridiculous_area_lights.append(area_light)

            if ridiculous_area_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Area Lights!!!",
                    message='You are using too much SAMPLES (>2) on<br>'
                    '<br>'
                    '<b>Area Lights</b><br>'
                    '<br>'
                    'Please reduce the samples to 2',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

            # Check directional lights with angle == 0 and samples > 1
            all_directional_lights = pm.ls(type='directionalLight')
            ridiculous_directional_lights = []
            dir_sample_attr_name = 'aiSamples'
            # if pm.about(v=1) == "2014":
            #     dir_sample_attr_name = 'aiSamples'

            for directional_light in all_directional_lights:
                if directional_light.aiAngle.get(
                ) == 0 and directional_light.attr(
                        dir_sample_attr_name).get() > 1:
                    ridiculous_directional_lights.append(directional_light)

            if ridiculous_directional_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Directional Lights!!!",
                    message='You are using too much SAMPLES (>1) on <br>'
                    '<br>'
                    '<b>Directional lights with zero angle</b><br>'
                    '<br>'
                    'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK')
                return

        # get values
        start_frame = pm.intField('cgru_afanasy__start_frame', q=1, v=1)
        end_frame = pm.intField('cgru_afanasy__end_frame', q=1, v=1)
        frames_per_task = \
            pm.intField('cgru_afanasy__frames_per_task', q=1, v=1)
        by_frame = pm.intField('cgru_afanasy__by_frame', q=1, v=1)
        depend_mask_global = pm.textField('cgru_afanasy__depend_mask_global',
                                          q=1,
                                          text=True)
        hosts_mask = pm.textField('cgru_afanasy__hosts_mask', q=1, text=True)
        hosts_exclude = pm.textField('cgru_afanasy__hosts_exclude',
                                     q=1,
                                     text=True)
        separate_layers = \
            pm.radioButtonGrp('cgru_afanasy__separate_layers', q=1, sl=1)
        pause = pm.checkBox('cgru_afanasy__paused', q=1, v=1)
        life_time = pm.intField('cgru_afanasy__life_time', q=1, v=1)
        annotation = pm.textField('cgru_afanasy__annotation', q=1, text=True)
        submit_multiple_times = pm.intField(
            'cgru_afanasy__submit_multiple_times', q=1, v=1)
        errors_avoid_host = pm.intField('cgru_afanasy__errors_avoid_host',
                                        q=1,
                                        v=1)
        errors_retries = pm.intField('cgru_afanasy__errors_retries', q=1, v=1)
        errors_task_same_host = pm.intField(
            'cgru_afanasy__errors_task_same_host', q=1, v=1)
        errors_forgive_time = pm.intField('cgru_afanasy__errors_forgive_time',
                                          q=1,
                                          v=1)

        generate_previews = pm.checkBox('cgru_afanasy__generate_previews',
                                        q=1,
                                        v=1)

        # check values
        if start_frame > end_frame:
            temp = end_frame
            end_frame = start_frame
            start_frame = temp

        frames_per_task = max(1, frames_per_task)
        by_frame = max(1, by_frame)

        # store without quota sign
        depend_mask_global = depend_mask_global.replace('"', '')
        hosts_mask = hosts_mask.replace('"', '')
        hosts_exclude = hosts_exclude.replace('"', '')

        # store field values
        pm.optionVar['cgru_afanasy__start_frame_ov'] = start_frame
        pm.optionVar['cgru_afanasy__end_frame_ov'] = end_frame
        pm.optionVar['cgru_afanasy__frames_per_task_ov'] = frames_per_task
        pm.optionVar['cgru_afanasy__by_frame_ov'] = by_frame
        pm.optionVar['cgru_afanasy__depend_mask_global_ov'] = \
            depend_mask_global
        pm.optionVar['cgru_afanasy__hosts_mask_ov'] = hosts_mask
        pm.optionVar['cgru_afanasy__hosts_exclude_ov'] = hosts_exclude
        pm.optionVar['cgru_afanasy__separate_layers_ov'] = separate_layers
        pm.optionVar['cgru_afanasy__life_time_ov'] = life_time
        pm.optionVar['cgru_afanasy__annotation_ov'] = annotation

        pm.optionVar[
            'cgru_afanasy__submit_multiple_times_ov'] = submit_multiple_times
        pm.optionVar['cgru_afanasy__errors_avoid_host_ov'] = errors_avoid_host
        pm.optionVar['cgru_afanasy__errors_retries_ov'] = errors_retries
        pm.optionVar[
            'cgru_afanasy__errors_task_same_host_ov'] = errors_task_same_host
        pm.optionVar[
            'cgru_afanasy__errors_errors_forgive_time_ov'] = errors_forgive_time
        pm.optionVar['cgru_afanasy__paused_ov'] = pause

        pm.optionVar['cgru_afanasy__generate_previews_ov'] = generate_previews

        # get paths
        scene_name = pm.sceneName()
        datetime = '%s%s' % (time.strftime('%y%m%d-%H%M%S-'),
                             str(time.time() - int(time.time()))[2:5])

        filename = '%s.%s.mb' % (scene_name, datetime)

        project_path = pm.workspace(q=1, rootDirectory=1)

        # outputs = \
        #     pm.renderSettings(fullPath=1, firstImageName=1, lastImageName=1)

        # get output paths, set the RenderPass token to Beauty,
        # this will at least guarantee to get something
        outputs = \
            pm.renderSettings(
                fullPath=1, firstImageName=1, lastImageName=1,
                leaveUnmatchedTokens=1, customTokenString="RenderPass=Beauty"
            )

        # job_name = os.path.basename(scene_name)
        job_name = self.generate_job_name()

        logger.debug('%ss %se %sr' % (start_frame, end_frame, by_frame))
        logger.debug('scene                 = %s' % scene_name)
        logger.debug('file                  = %s' % filename)
        logger.debug('job_name              = %s' % job_name)
        logger.debug('project_path          = %s' % project_path)
        logger.debug('outputs               = %s' % outputs)
        logger.debug('annotation            = %s' % annotation)
        logger.debug('separate_layers       = %s' % separate_layers)
        logger.debug('errors_avoid_host     = %s' % errors_avoid_host)
        logger.debug('errors_retries        = %s' % errors_retries)
        logger.debug('errors_task_same_host = %s' % errors_task_same_host)
        logger.debug('errors_forgive_time   = %s' % errors_forgive_time)
        logger.debug('generate_previews     = %s' % generate_previews)

        if pm.checkBox('cgru_afanasy__close', q=1, v=1):
            pm.deleteUI(self.window)

        stored_log_level = None
        if render_engine == 'arnold':
            # set the verbosity level to warning+info
            aro = pm.PyNode('defaultArnoldRenderOptions')
            stored_log_level = aro.getAttr('log_verbosity')
            aro.setAttr('log_verbosity', 2)
            # set output to console
            aro.setAttr("log_to_console", 1)
        elif render_engine == 'redshift':
            # set the verbosity level to detailed+info
            redshift = pm.PyNode('redshiftOptions')
            stored_log_level = redshift.logLevel.get()
            redshift.logLevel.set(2)

        # save file
        pm.saveAs(filename, force=1, type='mayaBinary')

        # rename back to original name
        pm.renameFile(scene_name)

        # create the render command
        mrc = MayaRenderCommandBuilder(name=job_name,
                                       file_full_path=filename,
                                       render_engine=render_engine,
                                       project=project_path,
                                       by_frame=by_frame)

        # submit renders
        jobs = []
        blocks = []

        #
        # separate_layers:
        # 1 -> None  -> submit one job with a single block with all layers
        # 2 -> Block -> submit one job with multiple blocks
        # 3 -> Job   -> submit multiple jobs with a single block per layer
        #
        if separate_layers in [1, 2]:
            job = af.Job(job_name)
            jobs.append(job)

        if separate_layers in [2, 3]:
            # render each layer separately
            rlm = pm.PyNode('renderLayerManager')
            layers = [
                layer for layer in rlm.connections(type=pm.nt.RenderLayer)
                if layer.renderable.get()
            ]

            for layer in layers:
                mrc_layer = copy.copy(mrc)
                layer_name = layer.name()
                mrc_layer.name = layer_name
                mrc_layer.render_layer = layer_name

                # create a new block for this layer
                block = af.Block(
                    layer_name,
                    renderer_to_block_type.get(render_engine, 'maya'))

                # Fix the output path for this layer
                # by replacing the "masterLayer" with the layer name
                # without rs_ at the beginning
                layer_outputs = outputs
                if layer_name != 'defaultRenderLayer':
                    layer_outputs[0] = outputs[0].replace(
                        'masterLayer', layer_name.replace('rs_', ''))
                    layer_outputs[1] = outputs[1].replace(
                        'masterLayer', layer_name.replace('rs_', ''))

                if generate_previews:
                    outputs_split = afcommon.patternFromDigits(
                        afcommon.patternFromStdC(
                            afcommon.patternFromPaths(
                                layer_outputs[0],
                                layer_outputs[1]))).split(';')
                    block.setFiles(outputs_split)

                block.setNumeric(start_frame, end_frame, frames_per_task,
                                 by_frame)
                command = mrc_layer.build_command()

                block.setErrorsAvoidHost(errors_avoid_host)
                block.setErrorsRetries(errors_retries)
                block.setErrorsTaskSameHost(errors_task_same_host)
                block.setErrorsForgiveTime(errors_forgive_time)

                block.setCommand(command)

                if separate_layers == 2:
                    blocks.append(block)
                else:
                    job = af.Job('%s - %s' % (job_name, layer_name))
                    # add blocks
                    job.blocks = [block]
                    jobs.append(job)

        else:
            # create only one block
            block = af.Block('All Layers',
                             renderer_to_block_type.get(render_engine, 'maya'))

            if generate_previews:
                block.setFiles(
                    afcommon.patternFromDigits(
                        afcommon.patternFromStdC(
                            afcommon.patternFromPaths(outputs[0],
                                                      outputs[1]))).split(';'))

            block.setNumeric(start_frame, end_frame, frames_per_task, by_frame)
            command = mrc.build_command()
            block.setCommand(command)

            blocks.append(block)

        for job in jobs:
            job.setAnnotation(annotation)
            job.setFolder('input', os.path.dirname(filename))
            job.setFolder('output', os.path.dirname(outputs[0]))
            job.setDependMaskGlobal(depend_mask_global)
            job.setHostsMask(hosts_mask)
            job.setHostsMaskExclude(hosts_exclude)
            if life_time > 0:
                job.setTimeLife(life_time * 3600)
            else:
                job.setTimeLife(240 * 3600)

            job.setCmdPost('deletefiles -s "%s"' % os.path.abspath(filename))
            if pause:
                job.offline()

            # add blocks
            if separate_layers in [1, 2]:
                job.blocks.extend(blocks)

            for i in range(submit_multiple_times):
                orig_job_name = job.data['name']
                job.setName('%s - %03i' % (orig_job_name, i + 1))
                status, data = job.send()

                # restore job name
                job.setName(orig_job_name)
                if not status:
                    pm.PopupError('Something went wrong!')

        # restore log level
        if render_engine == 'arnold':
            aro = pm.PyNode('defaultArnoldRenderOptions')
            aro.setAttr('log_verbosity', stored_log_level)
            # disable set output to console
            aro.setAttr("log_to_console", 0)
        elif render_engine == 'redshift':
            redshift = pm.PyNode('redshiftOptions')
            redshift.logLevel.set(stored_log_level)

            # disable abort on license fail
            redshift.abortOnLicenseFail.set(0)
Exemple #17
0
    def launch(self, *args, **kwargs):
        """launch renderer command
        """
        # do nothing if there is no window (called externally)
        if not self.window:
            return

        # warn the user about the ignore settings
        try:
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            ignore_attrs = [
                'ignoreSubdivision',
                'ignoreDisplacement',
                'ignoreBump',
                'ignoreMotionBlur'
            ]

            attr_values = [
                (attr, dAO.getAttr(attr))
                for attr in ignore_attrs
                if dAO.getAttr(attr) is True
            ]

            if any(attr_values):
                msg_text = '<br>'.join(
                    map(
                        lambda x: '%s: %s' % (x[0], x[1]),
                        attr_values
                    )
                )

                response = pm.confirmDialog(
                    title='Ignore These Settings?',
                    message='You have ignored:<br><br>%s<br><br><b>Is that ok?</b>' % msg_text,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
        except pm.MayaNodeError:
            # no Arnold
            pass

        # check if rendering with persp camera
        try:
            wrong_camera_names = [
                'perspShape',
                'topShape',
                'sideShape',
                'fontShape',

                'persp1Shape',
                'perspShape1',
            ]
            renderable_cameras = [node for node in pm.ls(type='camera') if node.getAttr('renderable')]
            if any(map(lambda x: x.name() in wrong_camera_names, renderable_cameras)):
                response = pm.confirmDialog(
                    title='Rendering with Persp?',
                    message='You are rendering with <b>Persp Camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return

            if len(renderable_cameras) > 1:
                response = pm.confirmDialog(
                    title='Rendering more than one Camera?',
                    message='You are rendering <b>more than one camera<b><br><br>Is that ok?</b>',
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )

                if response == 'No':
                    return
            elif len(renderable_cameras) == 0:
                pm.confirmDialog(
                    title='No <b>Renderable</b> camera!!!',
                    message='There is no <b>renderable camera<b>!!!',
                    button=['Ok'],
                    defaultButton='Ok',
                    cancelButton='Ok',
                    dismissString='Ok'
                )
                return

        except pm.MayaNodeError:
            # no default render globals node
            pass

        drg = pm.PyNode('defaultRenderGlobals')
        render_engine = drg.getAttr('currentRenderer')
        # RENDERER SPECIFIC CHECKS

        if render_engine == 'redshift':
            # if the renderer is RedShift
            # check if unifiedDisableDivision is 1 which will take too much time
            # to render
            dro = pm.PyNode('redshiftOptions')
            if dro.unifiedDisableDivision.get() == 1:
                response = pm.confirmDialog(
                    title="Enabled **Don't Automatically Reduce Samples of Other Effects**",
                    message='It is not allowed to render with the following option is enabled:<br>'
                            '<br>'
                            "Don't Automatically Reduce Samples of Other Effects: Enabled<br>"
                            "<br>"
                            "Please DISABLE it!",
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # Check dome light backgrounds
            domes_to_fix = []
            rs_domes = pm.ls(type='RedshiftDomeLight')
            if rs_domes:
                for rs_dome in rs_domes:
                    if rs_dome.getAttr('background_enable') == 1 \
                       or rs_dome.getAttr('backPlateEnabled') == 1:
                        domes_to_fix.append(rs_dome.name())

            if domes_to_fix:
                message = 'Some DomeLights have <b>BackGround Render ' \
                          'Enabled</b>:' \
                          '<br><br>%s<br><br>' \
                          'Are you Sure?' % '<br>'.join(domes_to_fix)

                response = pm.confirmDialog(
                    title='Dome Lights with Background Enabled?',
                    message=message,
                    button=['Yes', 'No'],
                    defaultButton='No',
                    cancelButton='No',
                    dismissString='No'
                )
                if response == 'No':
                    return

            # abort on license fail
            dro.abortOnLicenseFail.set(1)

        elif render_engine == 'arnold':
            # check if the samples are too high
            dAO = pm.PyNode('defaultArnoldRenderOptions')

            aa_samples = dAO.AASamples.get()
            diff_samples = dAO.GIDiffuseSamples.get()
            try:
                glossy_samples = dAO.GIGlossySamples.get()
            except AttributeError:
                glossy_samples = dAO.GISpecularSamples.get()
            if int(pm.about(v=1)) >= 2017:
                sss_samples = dAO.GISssSamples.get()
            else:
                sss_samples = dAO.sssBssrdfSamples.get()

            total_diff_samples = aa_samples**2 * diff_samples**2
            total_glossy_samples = aa_samples**2 * glossy_samples**2
            total_sss_samples = aa_samples**2 * sss_samples**2

            max_allowed_diff_samples = 225
            max_allowed_glossy_samples = 100
            max_allowed_sss_samples = 800

            if total_diff_samples > max_allowed_diff_samples:
                pm.confirmDialog(
                    title="Too Much Diffuse Samples!!!",
                    message='You are using too much DIFFUSE SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of Diffuse '
                            'Samples!!!' % max_allowed_diff_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            if total_glossy_samples > max_allowed_glossy_samples:
                pm.confirmDialog(
                    title="Too Much Glossy Samples!!!",
                    message='You are using too much GLOSSY SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of Glossy '
                            'Samples!!!' % max_allowed_glossy_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            if total_sss_samples > max_allowed_sss_samples:
                pm.confirmDialog(
                    title="Too Much SSS Samples!!!",
                    message='You are using too much SSS SAMPLES (>%s)<br>'
                            '<br>'
                            'Please either reduce AA samples of SSS '
                            'Samples!!!' % max_allowed_sss_samples,
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # check Light Samples
            # check point lights with zero radius but more than one samples
            all_point_lights = pm.ls(type='pointLight')
            ridiculous_point_lights = []
            for point_light in all_point_lights:
                if point_light.aiRadius.get() < 0.1 and point_light.aiSamples.get() > 1:
                    ridiculous_point_lights.append(point_light)

            if ridiculous_point_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Point Lights!!!",
                    message='You are using too much SAMPLES (>1)<br>'
                            '<br>'
                            'on <b>Point lights with zero radius</b><br>'
                            '<br>'
                            'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # Check area lights with more than 2 samples
            all_area_lights = pm.ls(type=['areaLight', 'aiAreaLight'])
            ridiculous_area_lights = []
            for area_light in all_area_lights:
                if area_light.aiSamples.get() > 2:
                    ridiculous_area_lights.append(area_light)

            if ridiculous_area_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Area Lights!!!",
                    message='You are using too much SAMPLES (>2) on<br>'
                            '<br>'
                            '<b>Area Lights</b><br>'
                            '<br>'
                            'Please reduce the samples to 2',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

            # Check directional lights with angle == 0 and samples > 1
            all_directional_lights = pm.ls(type='directionalLight')
            ridiculous_directional_lights = []
            dir_sample_attr_name = 'aiSamples'
            # if pm.about(v=1) == "2014":
            #     dir_sample_attr_name = 'aiSamples'

            for directional_light in all_directional_lights:
                if directional_light.aiAngle.get() == 0 and directional_light.attr(dir_sample_attr_name).get() > 1:
                    ridiculous_directional_lights.append(directional_light)

            if ridiculous_directional_lights:
                pm.confirmDialog(
                    title="Unnecessary Samples on Directional Lights!!!",
                    message='You are using too much SAMPLES (>1) on <br>'
                            '<br>'
                            '<b>Directional lights with zero angle</b><br>'
                            '<br>'
                            'Please reduce the samples to 1',
                    button=['OK'],
                    defaultButton='OK',
                    cancelButton='OK',
                    dismissString='OK'
                )
                return

        # get values
        start_frame = pm.intField('cgru_afanasy__start_frame', q=1, v=1)
        end_frame = pm.intField('cgru_afanasy__end_frame', q=1, v=1)
        frames_per_task = \
            pm.intField('cgru_afanasy__frames_per_task', q=1, v=1)
        by_frame = pm.intField('cgru_afanasy__by_frame', q=1, v=1)
        hosts_mask = pm.textField('cgru_afanasy__hosts_mask', q=1, text=True)
        hosts_exclude = pm.textField('cgru_afanasy__hosts_exclude', q=1, text=True)
        separate_layers = \
            pm.radioButtonGrp('cgru_afanasy__separate_layers', q=1, sl=1)
        pause = pm.checkBox('cgru_afanasy__paused', q=1, v=1)
        life_time = pm.intField('cgru_afanasy__life_time', q=1, v=1)
        annotation = pm.textField('cgru_afanasy__annotation', q=1, text=True)
        submit_multiple_times = pm.intField('cgru_afanasy__submit_multiple_times', q=1, v=1)
        errors_avoid_host = pm.intField('cgru_afanasy__errors_avoid_host', q=1, v=1)
        errors_retries = pm.intField('cgru_afanasy__errors_retries', q=1, v=1)
        errors_task_same_host = pm.intField('cgru_afanasy__errors_task_same_host', q=1, v=1)
        errors_forgive_time = pm.intField('cgru_afanasy__errors_forgive_time', q=1, v=1)

        # check values
        if start_frame > end_frame:
            temp = end_frame
            end_frame = start_frame
            start_frame = temp

        frames_per_task = max(1, frames_per_task)
        by_frame = max(1, by_frame)

        # store without quota sign
        hosts_mask = hosts_mask.replace('"', '')
        hosts_exclude = hosts_exclude.replace('"', '')

        # store field values
        pm.optionVar['cgru_afanasy__start_frame_ov'] = start_frame
        pm.optionVar['cgru_afanasy__end_frame_ov'] = end_frame
        pm.optionVar['cgru_afanasy__frames_per_task_ov'] = frames_per_task
        pm.optionVar['cgru_afanasy__by_frame_ov'] = by_frame
        pm.optionVar['cgru_afanasy__hosts_mask_ov'] = hosts_mask
        pm.optionVar['cgru_afanasy__hosts_exclude_ov'] = hosts_exclude
        pm.optionVar['cgru_afanasy__separate_layers_ov'] = separate_layers
        pm.optionVar['cgru_afanasy__life_time_ov'] = life_time
        pm.optionVar['cgru_afanasy__annotation_ov'] = annotation

        pm.optionVar['cgru_afanasy__submit_multiple_times_ov'] = submit_multiple_times
        pm.optionVar['cgru_afanasy__errors_avoid_host_ov'] = errors_avoid_host
        pm.optionVar['cgru_afanasy__errors_retries_ov'] = errors_retries
        pm.optionVar['cgru_afanasy__errors_task_same_host_ov'] = errors_task_same_host
        pm.optionVar['cgru_afanasy__errors_errors_forgive_time_ov'] = errors_forgive_time

        # get paths
        scene_name = pm.sceneName()
        datetime = '%s%s' % (
            time.strftime('%y%m%d-%H%M%S-'),
            str(time.time() - int(time.time()))[2:5]
        )

        filename = '%s.%s.mb' % (scene_name, datetime)

        project_path = pm.workspace(q=1, rootDirectory=1)

        # outputs = \
        #     pm.renderSettings(fullPath=1, firstImageName=1, lastImageName=1)

        # get output paths, set the RenderPass token to Beauty,
        # this will at least guarantee to get something
        outputs = \
            pm.renderSettings(
                fullPath=1, firstImageName=1, lastImageName=1,
                leaveUnmatchedTokens=1, customTokenString="RenderPass=Beauty"
            )

        # job_name = os.path.basename(scene_name)
        job_name = self.generate_job_name()

        logger.debug('%ss %se %sr' % (start_frame, end_frame, by_frame))
        logger.debug('scene                 = %s' % scene_name)
        logger.debug('file                  = %s' % filename)
        logger.debug('job_name              = %s' % job_name)
        logger.debug('project_path          = %s' % project_path)
        logger.debug('outputs               = %s' % outputs)
        logger.debug('annotation            = %s' % annotation)
        logger.debug('separate_layers       = %s' % separate_layers)
        logger.debug('errors_avoid_host     = %s' % errors_avoid_host)
        logger.debug('errors_retries        = %s' % errors_retries)
        logger.debug('errors_task_same_host = %s' % errors_task_same_host)
        logger.debug('errors_forgive_time   = %s' % errors_forgive_time)

        if pm.checkBox('cgru_afanasy__close', q=1, v=1):
            pm.deleteUI(self.window)

        stored_log_level = None
        if render_engine == 'arnold':
            # set the verbosity level to warning+info
            aro = pm.PyNode('defaultArnoldRenderOptions')
            stored_log_level = aro.getAttr('log_verbosity')
            aro.setAttr('log_verbosity', 2)
            # set output to console
            aro.setAttr("log_to_console", 1)
        elif render_engine == 'redshift':
            # set the verbosity level to detailed+info
            redshift = pm.PyNode('redshiftOptions')
            stored_log_level = redshift.logLevel.get()
            redshift.logLevel.set(2)

        # save file
        pm.saveAs(
            filename,
            force=1,
            type='mayaBinary'
        )

        # rename back to original name
        pm.renameFile(scene_name)

        # create the render command
        mrc = MayaRenderCommandBuilder(
            name=job_name,
            file_full_path=filename,
            render_engine=render_engine,
            project=project_path,
            by_frame=by_frame
        )

        # submit renders
        jobs = []
        blocks = []

        #
        # separate_layers:
        # 1 -> None  -> submit one job with a single block with all layers
        # 2 -> Block -> submit one job with multiple blocks
        # 3 -> Job   -> submit multiple jobs with a single block per layer
        #
        if separate_layers in [1, 2]:
            job = af.Job(job_name)
            jobs.append(job)

        if separate_layers in [2, 3]:
            # render each layer separately
            rlm = pm.PyNode('renderLayerManager')
            layers = [layer for layer in rlm.connections()
                      if layer.renderable.get()]

            for layer in layers:
                mrc_layer = copy.copy(mrc)
                layer_name = layer.name()
                mrc_layer.name = layer_name
                mrc_layer.render_layer = layer_name

                # create a new block for this layer
                block = af.Block(
                    layer_name,
                    renderer_to_block_type.get(render_engine, 'maya')
                )

                # Fix the output path for this layer
                # by replacing the "masterLayer" with the layer name
                # without rs_ at the beginning
                layer_outputs = outputs
                if layer_name != 'defaultRenderLayer':
                    layer_outputs[0] = outputs[0].replace(
                        'masterLayer',
                        layer_name.replace('rs_', '')
                    )
                    layer_outputs[1] = outputs[1].replace(
                        'masterLayer',
                        layer_name.replace('rs_', '')
                    )

                outputs_split = afcommon.patternFromDigits(
                    afcommon.patternFromStdC(
                        afcommon.patternFromPaths(
                            layer_outputs[0],
                            layer_outputs[1]
                        )
                    )
                ).split(';')

                block.setFiles(outputs_split)

                block.setNumeric(
                    start_frame, end_frame, frames_per_task, by_frame
                )
                command = mrc_layer.build_command()

                block.setErrorsAvoidHost(errors_avoid_host)
                block.setErrorsRetries(errors_retries)
                block.setErrorsTaskSameHost(errors_task_same_host)
                block.setErrorsForgiveTime(errors_forgive_time)

                block.setCommand(command)

                if separate_layers == 2:
                    blocks.append(block)
                else:
                    job = af.Job('%s - %s' % (job_name, layer_name))
                    # add blocks
                    job.blocks = [block]
                    jobs.append(job)

        else:
            # create only one block
            block = af.Block(
                'All Layers',
                renderer_to_block_type.get(render_engine, 'maya')
            )

            block.setFiles(
                afcommon.patternFromDigits(
                    afcommon.patternFromStdC(
                        afcommon.patternFromPaths(outputs[0], outputs[1])
                    )
                ).split(';')
            )
            block.setNumeric(
                start_frame, end_frame, frames_per_task, by_frame
            )
            command = mrc.build_command()
            block.setCommand(command)

            blocks.append(block)

        for job in jobs:
            job.setAnnotation(annotation)
            job.setFolder('input', os.path.dirname(filename))
            job.setFolder('output', os.path.dirname(outputs[0]))
            job.setHostsMask(hosts_mask)
            job.setHostsMaskExclude(hosts_exclude)
            if life_time > 0:
                job.setTimeLife(life_time * 3600)
            else:
                job.setTimeLife(240 * 3600)

            job.setCmdPost('deletefiles -s "%s"' % os.path.abspath(filename))
            if pause:
                job.offline()

            # add blocks
            if separate_layers in [1, 2]:
                job.blocks.extend(blocks)

            for i in range(submit_multiple_times):
                orig_job_name = job.data['name']
                job.setName('%s - %03i' % (orig_job_name, i + 1))
                status, data = job.send()

                # restore job name
                job.setName(orig_job_name)
                if not status:
                    pm.PopupError('Something went wrong!')

        # restore log level
        if render_engine == 'arnold':
            aro = pm.PyNode('defaultArnoldRenderOptions')
            aro.setAttr('log_verbosity', stored_log_level)
            # disable set output to console
            aro.setAttr("log_to_console", 0)
        elif render_engine == 'redshift':
            redshift = pm.PyNode('redshiftOptions')
            redshift.logLevel.set(stored_log_level)

            # disable abort on license fail
            redshift.abortOnLicenseFail.set(0)