Source code for helga.maya.rendering.setExrMetadata.setExrMetadata

"""
setExrMetadata
==========================================

Module that will parse the scene and add exr metadata to the rendersettings node.
The module is designed to work with VRay for Maya exclusively.
You can import and run it as a Pre-Frame script while batch rendering (on the farm).

-----------------------

Usage
-----

::
	
	from helga.maya.rendering.setExrMetadata import setExrMetadata
	reload(setExrMetadata)

	#run
	setExrMetadata.run()

.. warning::
	
	Module is known to cause crashes when rendering.
	Use with caution

-----------------------
"""




#Imports
#------------------------------------------------------------------
#python
import sys
import os
from functools import wraps
import cPickle as pickle
import platform
import datetime
import multiprocessing
#maya
import maya.OpenMaya as open_maya
import maya.api.OpenMaya as open_maya_2
import maya.cmds as cmds
import pymel.core as pm




#Globals
#------------------------------------------------------------------
VRAY_LIGHT_PARAMETERS_LIST = ['intensityMult', 'subdivs', 'lightColor', 'shadows', 'invisible', 'rayDistanceOn', 
								'domeSpherical', 'affectDiffuse', 'affectSpecular', 'affectReflections']
MAYA_LIGHT_PARAMETERS_LIST = ['color', 'intensity', 'emitDiffuse', 'emitDiffuse', 'shadowColor', 'useRayTraceShadows', 
								'lightAngle', 'shadowRays', 'rayDepthLimit']

VRAY_CAMERA_PARAMETERS_LIST = []
MAYA_CAMERA_PARAMETERS_LIST = ['focalLength', 'nearClipPlane', 'farClipPlane', 'horizontalFilmAperture', 'verticalFilmAperture'
								'depthOfField', 'focusDistance', 'fStop', 'focusRegionScale', 'backgroundColor', 'shutterAngle'
								'panZoomEnabled', 'horizontalPan', 'verticalPan', 'zoom', 'renderPanZoom', 'orthographic'
								'orthographicWidth']




#General Methods
#------------------------------------------------------------------

#vrayRenderSettingsNode
def vrayRenderSettingsNode():
	"""Get Vray rendersettings node"""
	
	#deselct all
	pm.select(cl = True)
	#select all nodes of type vraysettingsNode
	selList = pm.ls(fl = True, typ = 'VRaySettingsNode')
	
	#If selList < 1 return false and set status
	if not(selList):
		return None
	
	return selList[0]


#vray_settings_test
def vray_settings_test(func):
	"""Decorate adding of metadata with vray settings node existence test"""

	@wraps(func)
	def new_func():
		
		#log_progress
		log_progress = True

		try:
			#vray_settings_node
			vray_settings_node = vrayRenderSettingsNode()
			if not(vray_settings_node):
				print("Could not aquire vray settings node. Not added metadata for function: \n{0}".format(func.__doc__))
				return None

			#execute func
			attr, value = func(vray_settings_node)

			#cut value if larger than 20
			#if(len(str(value)) > 20):
			#	value = str(value)[:20] + '...'

			#log
			if(log_progress):
				print("Successfully added metadata: {0}={1}".format(attr, value))


		except:
			#if(log_progress):
			print("Error executing:\n{0}".format(func.__doc__))

	return new_func


#clear_metadata
def clear_metadata():
	"""Set metadata empty"""

	#log_progress
	log_progress = False

	try:
		#vray_settings_node
		vray_settings_node = vrayRenderSettingsNode()
		if not(vray_settings_node):
			print("Could not aquire vray settings node. Not cleared metadata")
			return None

		#clear
		vray_settings_node.imgOpt_exr_attributes.set("")

		#log
		if(log_progress):
			print("Successfully cleared metadata")


	except:
		#log
		if(log_progress):
			print("Error clearing metadata")


#get_inclusive_matrix
def get_inclusive_matrix(node_name):
	"""Get fn dag path from node name"""

	sel_list = open_maya.MSelectionList()
	try:
		sel_list.add(node_name)
	except:
		return None
	dag_path = open_maya.MDagPath()
	sel_list.getDagPath( 0, dag_path )
	return dag_path.inclusiveMatrix()


#mmatrix_to_list
def mmatrix_to_list(mmatrix):
	"""Convert Maya API 1 Matrix to flat python list"""

	if not(mmatrix):
		return []

	#list_matrix
	list_matrix = []

	#iterate and fill
	for row in range(4):
		for column in range(4):
			list_matrix.append(mmatrix(row, column))

	return list_matrix


#get_alembic_details_list
def get_alembic_details_list(include_search_from_alembic_node_type = False):
	"""Parse the scene for alembic nodes and return list with information"""

	#log_progress
	log_progress = False
	
	

	#alembic_details_list
	alembic_details_list = []



	#if include_search_from_alembic_node_type
	if(include_search_from_alembic_node_type):
		
		#iterate and gather from AlembicNodes
		#------------------------------------------------------------------

		#alembic_nodes_list
		alembic_nodes_list = cmds.ls(type = 'AlembicNode')

		#iterate
		for alembic_node_name in alembic_nodes_list:

			#alembic_details_dict
			alembic_details_dict = {}

			#add maya_node_name
			alembic_details_dict['maya_node_name'] = alembic_node_name

			#add maya_node_type
			alembic_details_dict['maya_node_type'] = cmds.nodeType(alembic_node_name)

			#alembic_path
			alembic_details_dict['alembic_path'] = cmds.getAttr(alembic_node_name +'.abc_File')

			#alembic_textures
			alembic_details_dict['alembic_textures'] = ''
			
			#append dict to list
			alembic_details_list.append(alembic_details_dict)


	


	#iterate and gather from metadata nodes
	#------------------------------------------------------------------
	
	#metadata_nodes_list
	metadata_nodes_list = pm.ls(type = 'metadata')

	for metadata_node in metadata_nodes_list:

		#alembic_details_dict
		alembic_details_dict = {}

		#add maya_node_name
		alembic_details_dict['maya_node_name'] = metadata_node.name()

		#add maya_node_type
		alembic_details_dict['maya_node_type'] = pm.nodeType(metadata_node)

		#alembic_path
		alembic_details_dict['alembic_path'] = cmds.getAttr(metadata_node.name() +'.alembic_path')

		#alembic_textures
		alembic_details_dict['alembic_textures'] = cmds.getAttr(metadata_node.name() +'.alembic_textures')
		
		#append dict to list
		alembic_details_list.append(alembic_details_dict)

	




	return alembic_details_list


#get_all_scene_lights
def get_all_scene_lights():
	"""get_all_scene_lights"""
	
	#clear selection
	pm.select(cl = True)
	
	#get standard maya lightslist
	mayaLightsList = pm.ls(fl = True, type = 'light')
	
	#get VRay Sphere Lights List
	vraySphereLightsList = pm.ls(fl = True, type = 'VRayLightSphereShape')
	
	#get VRay Dome Lights List
	vrayDomeLightsList = pm.ls(fl = True, type = 'VRayLightDomeShape')
	
	#get VRay Rect Lights List
	vrayRectLightsList = pm.ls(fl = True, type = 'VRayLightRectShape')
	
	#get VRay IES Lights List
	vrayIESLightsList = pm.ls(fl = True, type = 'VRayLightIESShape')

	#get VRay sun light List
	vraySunLightsList = pm.ls(fl = True, type = 'VRaySunShape')
	
	
	#return combined Lists
	return mayaLightsList + vraySphereLightsList + vrayDomeLightsList + vrayRectLightsList + vrayIESLightsList + vraySunLightsList


#get_light_details_list
def get_light_details_list():
	"""Parse the scene for light nodes and return list with information"""

	#log_progress
	log_progress = False

	#scene_lights_list
	scene_lights_list = get_all_scene_lights()
	#empty
	if not(scene_lights_list):
		print('No light nodes in the scene.')
		return []

	#scene_light_details_list
	scene_light_details_list = []

	#iterate and add details
	for light_node in scene_lights_list:

		#light_details_dict
		light_details_dict = {}

		#light_shape_name
		light_details_dict['light_shape_name'] = light_node.name()
		#light_transform_name
		light_details_dict['light_transform_name'] = light_node.getParent().name()
		#light_type
		light_details_dict['light_type'] = pm.nodeType(light_node)

		
		#inclusive_matrix
		inclusive_matrix = get_inclusive_matrix(light_node.name())
		#list_matrix
		list_matrix = mmatrix_to_list(inclusive_matrix)
		#add to dict
		light_details_dict['matrix'] = list_matrix




		#iterate LIGHT_PARAMETERS_LIST and add values if existing
		LIGHT_PARAMETERS_LIST = VRAY_LIGHT_PARAMETERS_LIST + MAYA_LIGHT_PARAMETERS_LIST
		for attr in LIGHT_PARAMETERS_LIST:
			if(light_node.hasAttr(attr)):
				#attr_value
				attr_value = pm.getAttr(light_node.name() +'.' +attr)
				#append to dict
				light_details_dict[attr] = attr_value

		

		#append dict to list
		scene_light_details_list.append(light_details_dict)


	return scene_light_details_list


#get_camera_details_list
def get_camera_details_list():
	"""Parse the scene for camera nodes and return list with information"""

	#log_progress
	log_progress = False

	#scene_cameras_list
	scene_cameras_list = pm.ls(ca = True)
	#empty
	if not(scene_cameras_list):
		print('No camera nodes in the scene.')
		return []

	#camera_details_list
	camera_details_list = []

	#iterate and add details
	for camera_node in scene_cameras_list:

		#camera_details_dict
		camera_details_dict = {}

		#camera_shape_name
		camera_details_dict['camera_shape_name'] = camera_node.name()
		#camera_transform_name
		camera_details_dict['camera_transform_name'] = camera_node.getParent().name()
		#camera_type
		camera_details_dict['camera_type'] = pm.nodeType(camera_node)

		
		#inclusive_matrix
		inclusive_matrix = get_inclusive_matrix(camera_node.name())
		#list_matrix
		list_matrix = mmatrix_to_list(inclusive_matrix)
		#add to dict
		camera_details_dict['matrix'] = list_matrix




		#iterate LIGHT_PARAMETERS_LIST and add values if existing
		CAMERA_PARAMETERS_LIST = VRAY_CAMERA_PARAMETERS_LIST + MAYA_CAMERA_PARAMETERS_LIST
		for attr in CAMERA_PARAMETERS_LIST:
			if(camera_node.hasAttr(attr)):
				#attr_value
				attr_value = pm.getAttr(camera_node.name() +'.' +attr)
				#append to dict
				camera_details_dict[attr] = attr_value

		

		#append dict to list
		camera_details_list.append(camera_details_dict)


	return camera_details_list


#get_rendersettings_dict
def get_rendersettings_dict():
	"""Parse the vray rendersettings node and return dict with information"""

	#log_progress
	log_progress = False

	#vray_settings_node
	vray_settings_node = vrayRenderSettingsNode()
	#empty
	if not(vray_settings_node):
		print('No vray rendersettings node in the scene.')
		return {}

	#rendersettings_details_dict
	rendersettings_details_dict = {}

	#iterate attrs
	for attr in vray_settings_node.listAttr():
		try:
			if(vray_settings_node.fileNamePrefix.name() != attr.name()):
				rendersettings_details_dict[pm.attributeName(attr)] = attr.get()
		except:
			#log
			if(log_process):
				print("Error getting value from attr. {0} from vray settings node {1}".format(pm.attributeName(attr), vray_settings_node.name()))


	return rendersettings_details_dict




#Add Data Methods
#------------------------------------------------------------------

@vray_settings_test
def add_render_settings_attr(vray_settings_node = None):
	"""render_settings"""

	#render_settings_dict
	render_settings_dict = get_rendersettings_dict()

	#attr
	attr = 'render_settings'
	#value
	value = pickle.dumps(render_settings_dict)
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_test_attr(vray_settings_node = None):
	"""myTestAttr"""

	#attr
	attr = 'test_attr'
	#value
	value = 'test_value'
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_pickle_list_attr(vray_settings_node = None):
	"""pickle_list"""

	#attr
	attr = 'pickle_list'
	#value
	value = 'render_settings, alembic_details, light_details, camera_details, scene_geometry_objects, scene_light_objects, scene_material_objects, scene_reference_pathes, scene_objects'
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_username_attr(vray_settings_node = None):
	"""username"""

	#attr
	attr = 'username'
	#value
	value = os.environ.get('USERNAME')
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_machine_name_attr(vray_settings_node = None):
	"""machine_name"""

	#attr
	attr = 'machine_name'
	#value
	value = platform.node()
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_render_start_time_attr(vray_settings_node = None):
	"""render_start_time"""

	#attr
	attr = 'render_start_time'
	#value
	value = repr(datetime.datetime.now())
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_render_cores_attr(vray_settings_node = None):
	"""render_cores"""

	#attr
	attr = 'render_cores'
	#value
	value = multiprocessing.cpu_count()
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_alembic_details_attr(vray_settings_node = None):
	"""alembic_details"""

	#alembic_details_list
	alembic_details_list = get_alembic_details_list()
	

	#attr
	attr = 'alembic_details'
	#value
	value = pickle.dumps(alembic_details_list)
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_light_details_attr(vray_settings_node = None):
	"""light_details"""

	#light_details_list
	light_details_list = get_light_details_list()
	

	#attr
	attr = 'light_details'
	#value
	value = pickle.dumps(light_details_list)
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_camera_details_attr(vray_settings_node = None):
	"""camera_details"""

	#camera_details_list
	camera_details_list = get_camera_details_list()
	

	#attr
	attr = 'camera_details'
	#value
	value = pickle.dumps(camera_details_list)
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_scene_geometry_objects_attr(vray_settings_node = None):
	"""scene_geometry_objects"""

	#scene_objects_list
	scene_objects_list = pm.ls(g = True)
	#scene_objects_name_list
	scene_objects_name_list = [node.name() for node in scene_objects_list]

	print("{0}-{1}".format('Scene objects list', scene_objects_list))
	print("{0}-{1}".format('Scene objects name list', scene_objects_name_list))

	#attr
	attr = 'scene_geometry_objects'
	#value
	value = pickle.dumps(scene_objects_name_list)

	#temp
	print('Add pickled list to vray options')

	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_scene_light_objects_attr(vray_settings_node = None):
	"""scene_light_objects"""

	#scene_objects_list
	scene_objects_list = pm.ls(lt = True)
	#scene_objects_name_list
	scene_objects_name_list = [node.name() for node in scene_objects_list]

	print("{0}-{1}".format('Scene lights list', scene_objects_list))
	print("{0}-{1}".format('Scene lights name list', scene_objects_name_list))

	#attr
	attr = 'scene_light_objects'
	#value
	value = pickle.dumps(scene_objects_name_list)

	#temp
	print('Add pickled list to vray options')

	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_scene_material_objects_attr(vray_settings_node = None):
	"""scene_material_objects"""

	#scene_objects_list
	scene_objects_list = pm.ls(mat = True)
	#scene_objects_name_list
	scene_objects_name_list = [node.name() for node in scene_objects_list]

	#attr
	attr = 'scene_material_objects'
	#value
	value = pickle.dumps(scene_objects_name_list)

	#temp
	print('Add pickled list to vray options')

	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_scene_reference_pathes_attr(vray_settings_node = None):
	"""scene_reference_pathes"""

	#scene_objects_list
	scene_objects_list = pm.ls(rf = True)
	#scene_objects_name_list
	scene_objects_name_list = [node.referenceFile() for node in scene_objects_list]

	#attr
	attr = 'scene_reference_pathes'
	#value
	value = pickle.dumps(scene_objects_name_list)

	#temp
	print('Add pickled list to vray options')

	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]


@vray_settings_test
def add_scene_objects_attr(vray_settings_node = None):
	"""scene_objects"""

	#scene_objects_list
	scene_objects_list = pm.ls()
	#scene_objects_name_type_list
	scene_objects_name_type_list = [[node.name(), node.type()] for node in scene_objects_list]

	#attr
	attr = 'scene_objects'
	#value
	value = pickle.dumps(scene_objects_name_type_list)

	#temp
	print('Add pickled list to vray options')
	
	#add
	vray_settings_node.imgOpt_exr_attributes.set("{0}{1}={2};".format(vray_settings_node.imgOpt_exr_attributes.get(), attr, value))

	return [attr, value]



#Run
#------------------------------------------------------------------
def run():
[docs] """General and only method to invoke to start adding metadata""" #clear metadata clear_metadata() #add_render_settings_attr add_render_settings_attr() #test_attr add_test_attr() #add_pickle_list_attr add_pickle_list_attr() #add_username_attr add_username_attr() #add_machine_name_attr add_machine_name_attr() #add_render_start_time_attr add_render_start_time_attr() #add_render_cores_attr add_render_cores_attr() #add_alembic_details_attr add_alembic_details_attr() #add_light_details_attr add_light_details_attr() #add_camera_details_attr add_camera_details_attr() #add_scene_geometry_objects_attr add_scene_geometry_objects_attr() #add_scene_light_objects_attr add_scene_light_objects_attr() #add_scene_material_objects_attr add_scene_material_objects_attr() #add_scene_reference_pathes_attr add_scene_reference_pathes_attr() #add_scene_objects_attr add_scene_objects_attr() #Execute #------------------------------------------------------------------ if(__name__ == '__main__'):
#run run()