# Using Python Rifs
# import batch
#
# rifs = ['rif_it', 'rif_format.Rif(640,480)' ] <<-- 2 python rifs
# batch.render(1, 1, rifs)
# Notes:
# If a python rif does NOT have inputs it can be specified by it's module name.
# If a python rif DOES have inputs it must be specified by module_name.Rif(arg1,arg2, ...)
# Inputs MUST be separated by commas.
#___________________________________________________________________________________________
# Using compiled C++ RifPlugins
# import batch
#
# rifs = [ ['FULL_PATH/TO/Mesh2Blobby','0.2'],
# ['./rif_plugins/Format','640, 480'] ] <<-- relative to current Maya project dir
# batch.render(1,1, rifs)
# Notes:
# Only the name of the rif need be specified - either '.so' or '.dll' will be added
# by the BatchWriter class.
#___________________________________________________________________________________________
# Vanilla rendering - no rifs
# import batch
#
# batch.render(1,1) <<-- Generate fresh ribs and render immediately.
# batch.render(1,0) <<-- Or, generate fresh ribs and postpone rendering.
# batch.render(0,1) <<-- Or, use existing ribs and render immediately.
#
# Malcolm Kesson
# July 26 2018
# Edits: Aug 6 2018
import rfm2.render
import maya.mel as mel
import maya.cmds as mc
import os
import re
import sys
import subprocess
from batch_writer import BatchWriter
from batch_rif import BatchRif
unsaved_scene_name = 'unknown'
reg_extract_numeric_ext = re.compile(r'(\w+)[._]+(\d+)[._]+rib')
def render(gen_ribs, do_render, rifs=None):
# Grab the required data
proj_path = mc.workspace(q=True, rootDirectory=True)
scene_name = get_scene_name()
anim = mc.getAttr('defaultRenderGlobals.animation')
begin = mc.getAttr('defaultRenderGlobals.startFrame')
end = mc.getAttr('defaultRenderGlobals.endFrame')
by = int(mc.getAttr('defaultRenderGlobals.byFrameStep'))
layer_name = get_render_layer()
# 2. Adjust the frame range when a single frame is to be rendered
# and motion blur is 'ON'.
if not anim:
begin = mc.currentTime(query=True)
end = mc.currentTime(query=True)
motion = mc.getAttr('rmanGlobals.motionBlur');
if motion == 1 or motion == 2:
end = end + 1
mc.setAttr("defaultRenderGlobals.endFrame", end)
begin = int(begin)
end = int(end)
by = int(by)
# 3. Generate the rib files
if gen_ribs:
rfm2.render.frame('-ribFile')
# 4. Get a listing of all the ribs generated.
vt_dir_name = get_version_take_str()
ribs_dir_path = os.path.join(proj_path,'renderman', 'rib', scene_name, vt_dir_name)
ribs = os.listdir(ribs_dir_path)
# Get the names of the renderable cameras
cams = get_renderable_cameras()
# 5. Store the names of ribs that match the renderable camera(s). This ensures
# the batch render script(s) ignores ribs that were generated by previous renders.
# A typical entry in the database dictionarywould be,
# {'perspShape': ['PATH_TO/perspShape.0001.rib','PATH_TO/perspShape.0002.rib']}
ribs_database = {}
for cam in cams:
re_cam = re.compile(r'%s' % cam)
rib_list = []
next_valid = int(begin)
for rib in ribs:
if not rib.endswith('.rib'):
continue
if re_cam.search(rib, 0):
num_ext = get_numeric_ext(rib)
if not anim:
if num_ext == begin or num_ext == end:
rib_list.append(os.path.join(ribs_dir_path, rib))
if anim:
if num_ext % next_valid == 0:
if(num_ext >= begin and num_ext <= end):
rib_list.append(os.path.join(ribs_dir_path, rib))
next_valid += by
ribs_database[cam] = rib_list
usesCompiledRifPlugins = False
if rifs != None:
if len(rifs) > 0:
if type(rifs[0]) is not list:
BR = BatchRif(proj_path, ribs_database, rifs)
BR.applyRifs('ascii')
else:
usesCompiledRifPlugins = True
BW = BatchWriter(proj_path, scene_name, vt_dir_name, ribs_database, begin)
if usesCompiledRifPlugins:
batch_paths = BW.makeBatchRenderScripts(rifs)
else:
batch_paths = BW.makeBatchRenderScripts()
# Auto executing multiple batchrender scripts is problematic.
# Only proceed...
if len(batch_paths) == 1 and do_render:
rfm2.render.show_it() # <<-- might be a problem on linux!!!!
run_batch_script(batch_paths[0])
#_____________________________________________________________________________
def get_version_take_str():
v = int(mc.getAttr('rmanGlobals.version'))
t = int(mc.getAttr('rmanGlobals.take'))
return 'v%0*d_t%0*d' % (3, v, 2, t)
#
def get_renderable_cameras():
out = []
cams = mc.ls(type='camera')
for cam in cams:
renderable = mc.getAttr('%s.renderable' % cam)
if renderable:
out.append(cam)
return out
#
def get_render_layer():
layer_index = mc.getAttr('renderLayerManager.currentRenderLayer')
all_layers = mc.listConnections('renderLayerManager')
return all_layers[layer_index]
#
def get_scene_name():
name = mc.file(q=True, sceneName=True, shortName=True)
if len(name) == 0:
name = unsaved_scene_name
else:
name = name[:len(name) - 3]
# foo_001 stays foo_001 but foo.001 becomes foo
# This accounts for an "inconsistency" in the way that RfM
# handles scene names
#print('name = %s' % name)
re_patt = re.compile(r'(\w+[_d]*)')
match = re.search(re_patt, name)
if match:
#print('match = %s' % match.group(1))
return match.group(1)
return name
#
def get_numeric_ext(rib):
match = re.search(reg_extract_numeric_ext, rib)
if match:
return int(match.group(2))
return -1
#
def run_batch_script(fullpath):
if os.name == "posix":
os.chmod(fullpath, 0777)
if sys.platform == 'darwin': # MacOSX
args = ['open', fullpath]
else: # linux
args = ['sh', fullpath]
subprocess.Popen(args,stdout=subprocess.PIPE)
else: # windows
args = ['start', fullpath]
subprocess.call(args, shell=True)
#
def call_batch_rif(fullpath):
args = ['/usr/bin/python', fullpath]
if os.name == "posix":
#os.chmod(fullpath, 0777)
subprocess.Popen(args,stdout=subprocess.PIPE)
else: # windows
subprocess.call(args, shell=True)