conductor.lib.maya_utils module

class conductor.lib.maya_utils.ArnoldInfo

Bases: conductor.lib.maya_utils.MayaPluginInfo

A class for retrieving version information about the arnold plugin in maya

Will ultimately produce something like this:

{'product': 'mtoa',
'major_version': u'1',
'minor_version': u'2',
'release_version': u'6',
'build_version': u'1',
'plugin_host_product': 'maya',
'plugin_host_version': u'2015'}
classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()

‘1.2.6.1’

plugin_name = 'mtoa'
class conductor.lib.maya_utils.MayaInfo

Bases: conductor.lib.package_utils.ProductInfo

A class for retrieving version information about the current maya session.

Will ultimately produce something like this:

# This is package for Maya
{'product': 'Maya'
'version': "Autodesk Maya 2015 SP4"
'host_product': '',
'host_version': ''},
classmethod get_major_version()

Return the major version of the product, e.g.

“2015”
classmethod get_minor_version()

Return the minor version of the product, e.g.

“SP4”
classmethod get_product()

Return the name of the product, e.g.

“Maya”
classmethod get_regex()

Regex the Maya product version string

Autodesk Maya 2014 x64 Service Pack 1 Autodesk Maya 2014 Service Pack 2 Autodesk Maya 2014 Service Pack 3 Autodesk Maya 2015 SP1 Autodesk Maya 2015 SP4 Autodesk Maya 2016 SP4 Autodesk Maya 2016 Extension 1 + SP5

classmethod get_vendor()

Return the Product vendor name, e.g. “Autodesk”

classmethod get_version()

Return the product verion, e.g.

“Autodesk Maya 2015 SP4”
product = 'maya'
class conductor.lib.maya_utils.MayaPluginInfo

Bases: conductor.lib.package_utils.ProductInfo

A class for retrieving version information about a plugin in maya

Will ultimately produce something like this:

{'product': '<plugin name>',
'major_version': u'3',
'minor_version': u'00',
'release_version': u'01',
'build_version': '',
'plugin_host_product': 'maya',
'plugin_host_version': u'2015'}
classmethod exists()
classmethod get_plugin_host_product()

Return the name of the host software package, e.g. “Maya” or “Katana”

classmethod get_plugin_host_version()

Return the name of the host software package, e.g. “Autodesk Maya 2015 SP4”

classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()
classmethod get_version()

Return the name of the software package, e.g. “Autodesk Maya 2015 SP4”

plugin_name = None
class conductor.lib.maya_utils.MiarmyBaseInfo

Bases: conductor.lib.maya_utils.MayaPluginInfo

Base class for all Miarmy plugins. This base class DOES NOT represent any one miarmy plugin. It must be subclassed.

A class for retrieving version information about the Miarmy plugin in maya

Will ultimately produce something like this:

{'product': 'miarmy',
'major_version': u'5',
'minor_version': u'2',
'release_version': u'25',
'build_version': u'',
'plugin_host_product': 'maya',
'plugin_host_version': u'2016'}
classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()

‘1.2.6’

class conductor.lib.maya_utils.MiarmyExpressForMaya20165Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyExpressForMaya20165'
class conductor.lib.maya_utils.MiarmyExpressForMaya2016Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyExpressForMaya2016'
class conductor.lib.maya_utils.MiarmyExpressForMaya2017Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyExpressForMaya2017'
class conductor.lib.maya_utils.MiarmyProForMaya20165Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyProForMaya20165'
class conductor.lib.maya_utils.MiarmyProForMaya2016Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyProForMaya2016'
class conductor.lib.maya_utils.MiarmyProForMaya2017Info

Bases: conductor.lib.maya_utils.MiarmyBaseInfo

plugin_name = 'MiarmyProForMaya2017'
class conductor.lib.maya_utils.RendermanInfo

Bases: conductor.lib.maya_utils.MayaPluginInfo

A class for retrieving version information about the renderman plugin in maya

Will ultimately produce something like this:

{'product': 'mtoa',
'major_version': u'1',
'minor_version': u'2',
'release_version': u'6',
'build_version': u'1',
'plugin_host_product': 'maya',
'plugin_host_version': u'2015'}
classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()

‘21.5’

plugin_name = 'RenderMan_for_Maya'
class conductor.lib.maya_utils.VrayInfo

Bases: conductor.lib.maya_utils.MayaPluginInfo

A class for retrieving version information about the vray plugin in maya

Will ultimately produce something like this:

{'product': 'vrayformaya',
'major_version': u'3',
'minor_version': u'00',
'release_version': u'01',
'build_version': '',
'plugin_host_product': 'maya',
'plugin_host_version': u'2015'}
classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()

3.00.01

plugin_name = 'vrayformaya'
class conductor.lib.maya_utils.YetiInfo

Bases: conductor.lib.maya_utils.MayaPluginInfo

A class for retrieving version information about the yeti plugin in maya

Will ultimately produce something like this:

{"product": "yeti",
"major_version": "2",
"minor_version": "1",
"release_version": "9",
"build_version": "",
"plugin_host_product": "maya",
"plugin_host_version": "2016"}
classmethod get_product()

Return the name of the software package, e.g. “Maya” or “Vray for Maya”, or “Katana”

classmethod get_regex()

2.1.9

plugin_name = 'pgYetiMaya'
conductor.lib.maya_utils.collect_dependencies(node_attrs)

Return a list of filepaths that the current maya scene has dependencies on. This is achieved by inspecting maya’s nodes.

Use the node_attrs argument to pass in a dictionary

conductor.lib.maya_utils.dec_undo(func)

DECORATOR - Wrap the decorated function in a Maya undo block. This is useful when wrapping functions which execute multiple maya commands, thereby altering maya’s state and undo stack with multiple operations. This allows the artist to simply execute one undo call to undo all of the calls that this wrapped function executed (as opposed to having the artist press undo undo undo undo..etc)

conductor.lib.maya_utils.derive_prefix_directory(file_prefix)

This is a super hack that makes many assumptions. It’s purpose is to determine the top level render output directory. Normally one could query the workspace’s “images” directory to get this information, but in cases where the render file prefix specifies an absolute path(thereby overriding the workspace’s specified directory), we must honor that prefix path.

The problem is that prefix path can contain variables, such as <Scene> or <RenderLayer>, which could be specific to whichever render layer is currently being rendered. So we need to navigate to highest common directory across all render layers.

So if this is the prefix:

"/shot_105/v076/<Layer>/105_light_<RenderLayer>_v076"

…then this is directory we want to return:

"/shot_105/v076"

However, there may not be any variables used. So if this is the prefix:

"/shot_105/v076/105_light_v076"

…then this is directory we want to return (same as before):

"/shot_105/v076"

Note that the provided file_prefix is expected to be absolute path

variables are such as:

<Scene>
<RenderLayer>
<Camera>
<RenderPassFileGroup>
<RenderPass>
<RenderPassType>
<Extension>
<Version>
<Layer>
conductor.lib.maya_utils.get_active_renderer()

Return the name of the active renderer, e.g “vray” or “arnold

conductor.lib.maya_utils.get_arnold_settings_node(strict=True)

Return the aiOptions node in the maya scene. If strict is True, and no node is found, raise an exception.

conductor.lib.maya_utils.get_current_renderer()

Return the name of the current renderer for the maya scene. e.g. ‘vray’ or ‘arnold’, etc

conductor.lib.maya_utils.get_frame_range()

Return the current frame range for the current maya scene.

This consists of both the “playback” start/end frames, as well as the “range” start/end frames.

Note that only integers are currently support for frames

Returns:List of two tuples, where the first tuple is the “playback” start/end frames and the second is the “range” start/end frames, e.g.:
[(1.0, 24.0), (5.0, 10.0)]
Return type:list[tuple]
conductor.lib.maya_utils.get_image_dirpath()

This is high level function that “figures out” the proper “output directory” for the conductor job being submitted.

To Do:
(lws) Need to break up the logic on a per-plugin/renderer basis.

As of now, the output directory is used for two separate purposes (which desperately need to be separated at some point).

  1. Dictates the directory to search for rendered images on the render node when the render task completes. If the rendered images cannot be found recursively within the given output path then the images will not get transferred to GCS, and therefore the task will have no frames to download.
  2. Dictates the default directory that the client downloader will download the task’s frames to. Note that the client downloader can manually override the download directory when evoking the downloader command manually (as opposed to running it in daemon mode).

On a simple level, the output directory should be the directory in which maya renders its images to. However, this is directory is not straight forward process to derive.

For starters, the “output directory” is not necessarily flat; it may contain nested directories (such as for render layers, etc) that were created by the rendering process. This is not actually a problem, but something to consider.

Those nested directories will be represented/recreated when the resulting images are downloaded by the client. But the important piece to note is that the output directory should be the “lowest” (longest) directory possible, while encompassing all rendered images from that task.

The other part of the complexity, is that there are multiple places in Maya to dictate where the “output directory” is (and I can’t pretend to know every possible way of achieving this). As of now, these are the known factors:

  1. The Workspace’s “image” directory is the default location for renders. (I’m not sure if this is even true).
  2. However, this can be essentially overridden within the global render settings if one were to populate “File Name Prefix” field with an absolute path. (perhaps there’s another way to override the output directory but this is what I’ve observed thus far).
  3. Each renderer (such as vray or maya software) has a different node/attribute to set the File Name Prefix field. So it’s important to know which renderer is active in order to query the proper node for its data. As other renderers are added/supported by conductor, those nodes will need to be considered when querying for data.
conductor.lib.maya_utils.get_maya_image_dirpath()

Return the “images” directory for the active maya workspace

conductor.lib.maya_utils.get_maya_save_state()

Returns True if the current Maya scene has unsaved changes

conductor.lib.maya_utils.get_maya_scene_filepath()
conductor.lib.maya_utils.get_maya_version()

Return the version string of the currently running maya session. e.g. “Autodesk Maya 2015 SP4”

conductor.lib.maya_utils.get_mayasoftware_settings_node(strict=True)

Return the renderGlobals node in the maya scene. If strict is True, and no node is found, raise an exception.

conductor.lib.maya_utils.get_node_by_type(node_type, must_exist=True, many=False)

For the given node type, return the one node found in the maya scene of that type. If many is True, allow more than one to be returned, otherwise raise an exception if more than one is found. If must_exist is True, raise an exception if no nodes are found in the maya scene.

conductor.lib.maya_utils.get_ocio_config_filepath()

Return the OCIO config filepath from maya settings.

Only return the filepath if color managment is enabled and OCIO config is enabled.

conductor.lib.maya_utils.get_plugin_info()

Return the conductor package information for any supported plugins that are loaded.

e.g.:

{'arnold-maya': u'1.4.2.1',
 'miarmy': u'5.2.25',
 'v-ray-maya': u'3.40.02'}
conductor.lib.maya_utils.get_plugin_info_class(plugin_name)
conductor.lib.maya_utils.get_plugin_versions()

Query maya for all of it’s plugins and their versions.

Returns:such as:
{'AbcExport': '1.0',
'AbcImport': '1.0',
'BifrostMain': '1.0',
'HoldOut': '1.0',
'MayaMuscle': '2.00 (Build: 004)',
'Mayatomr': '2015.0 - 3.12.1.18 ',
'Substance': '1.11143',
'autoLoader': '1.0',
'bifrostshellnode': '2015',
'bifrostvisplugin': '3.0',
'cgfxShader': 'cgfxShader 4.5 for Maya 2015.0 (Apr  9 2015)',
'fbxmaya': '2015.1',
'glmCrowd': '4.1.3[21f4d33]-2015/08/25',
'gpuCache': '1.0',
'iDeform': '1.0',
'ik2Bsolver': '2.5',
'ikSpringSolver': '1.0',
'matrixNodes': '1.0',
'mayaCharacterization': '5',
'mayaHIK': '1.0_HIK_2014.2',
'modelingToolkit': 'Unknown',
'modelingToolkitStd': '0.0.0.0',
'quatNodes': '1.0',
'relax_node': 'Unknown',
'retargeterNodes': '1.0',
'rotateHelper': '1.0',
'sceneAssembly': '1.0',
'shaderFXPlugin': '1.0',
'skinningDecomposition': '1.0',
'spReticleLoc': '2.0',
'tiffFloatReader': '8.0',
'vrayformaya': '3.00.01',
'xgenMR': '1.0',
'xgenToolkit': '1.0'}
Return type:dict
conductor.lib.maya_utils.get_render_file_prefix()

Return the “File Name Prefix” from the global render settings. Note that this is a read from different node/attribute depending on which renderer is currently active.

Note that as more renderers are supported by Conductor, this function may need to be updated to properly query those renderers’ information.

conductor.lib.maya_utils.get_render_layers_info(*a, **kw)

Return a list of dictionaries where each dictionary represents data for a a render layer.

Each dictionary provides the following information:

  • render layer name
  • whether the render layer is set to renderable
  • the cameras that the render layer is set to render
To Do:
  • Does the default render layer name need to be augmented when passed to Maya’s rendering command?
  • Should the default render layer be included at all? And should it be unselected by default?

Note that this function is wrapped in an undo block because it actually changes the state of the maya session (unfortunately). There doesn’t appear to be an available api call to query maya for this information, without changing it’s state (switching the active render layer)

conductor.lib.maya_utils.get_render_settings_node(renderer_name, strict=True)

return the name of the renderer’s settings node. e.g. “defaultRenderGlobals” or “vraySettings” or “defaultArnoldRenderOptions”

conductor.lib.maya_utils.get_renderer_globals_node(renderer_name)

For the given renderer name, return the name of its renderer globals node.

To Do:
(lws) Note that if more than one node is found, raise an exception. This is to simplify things for now, but may need to support multiple nodes later.
Parameters:renderer_name (str) – e.g. “vray” or “arnold”
Returns:e.g. “defaultRenderGlobals”
Return type:str
conductor.lib.maya_utils.get_renderer_info(renderer_name=None)
Parameters:renderer_name (str) – e.g. “vray” or “arnold”
Returns:For example:
{"renderer_name": "vray",
"plugin_name": "vrayformaya",
"plugin_version": 3.00.01'}
Return type:dict
conductor.lib.maya_utils.get_renderer_plugin(renderer_name)

For the given renderer name, return the renderer’s plugin name

Attempt to find the correlation between the renderer name and the plugin name by asking maya for it’s active renderer’s global render settings node, and then asking what node type that is, and then asking which plugin provides the node type.

Warning

THIS DOESN’T ALWAYS WORK!

For some reason the “vraysettings” node isn’t always listed as one of the global render settings nodes. So we resort to a hard mapping.

conductor.lib.maya_utils.get_short_name(node)

Return the short name of a given maya node

conductor.lib.maya_utils.get_transform(shape_node)

Return the transform node of a given shape node

conductor.lib.maya_utils.get_vray_settings_node(strict=True)

Return the VRaySettingsNode node in the maya scene. If strict is True, and no node is found, raise an exception.

conductor.lib.maya_utils.get_workspace_dirpath()

Return the current Workspace directory

conductor.lib.maya_utils.get_workspace_image_dirpath()

Return the current workspace’s image directory

conductor.lib.maya_utils.is_arnold_renderer()

Return boolean to indicat whether arnold is the current renderer for the maya scene

conductor.lib.maya_utils.is_arnold_tx_enabled()

Return True if the “Use Existing .tx Textures” option is enabled in Arnolds render settings

conductor.lib.maya_utils.is_renderman_renderer()

Return boolean to indicat whether vray is the current renderer for the maya scene

conductor.lib.maya_utils.is_vray_gpu_enabled()

Return True if a GPU mode is selected in V-Ray’s render settings Current potential values set on V-Ray’s productionEngine attr are:

  • 0 = CPU mode (False)
  • 1 = OpenCL mode (False - not supported on Intel/NVIDIA hardware)
  • 2 = CUDA mode (True)
conductor.lib.maya_utils.is_vray_renderer()

Return boolean to indicat whether vray is the current renderer for the maya scene

conductor.lib.maya_utils.parse_ocio_config_paths(config_filepath)

Parse the given OCIO config file for any paths that we may be interested in (for uploads)

For now, we’ll keep this simple and simply scrape the “search_path” value in the config file. However, it’s possible that additional attributes in the config will need to be queried.

conductor.lib.maya_utils.parse_rib_file(filepath)

Parse the given rib filepath for file dependencies

In leui of python rib parser/api, we need need to resort to some awful hacks here.

We use prman library to read the rib file. The only benefit that this provides is that it can read a binary rib file and output it to ascii. Aside from that, we’re doing crude regex matching from the content (no api for interfacing with ribs :( ).

Regex for attributes such as:

filename
fileTextureName
conductor.lib.maya_utils.parse_vrscene_file(path)

Parse the vrscene file paths…

conductor.lib.maya_utils.parse_xgen_command(cmd_str)

Parse xgen procedural command/args. Very crude with many assumptions.

Parameters:cmd_str (str) –

The string to parse, e.g.:

(
    '-debug 1 -warning 1 -stats 1  -frame 1.000000 '
    '-nameSpace cat_main -file /tmp/cat.xgen '
    '-palette cat_xgen_coll -geom /tmp/cat_xgen_coll.abc '
    '-patch Paw_R_emitter -description catcuff_xgen_desc '
    '-fps 24.000000  -motionSamplesLookup -0.250000 0.250000 '
    '-motionSamplesPlacement -0.250000 0.250000 '
    '-world 1;0;0;0;0;1;0;0;0;0;1;0;0;0;0;1'
)
Returns:e.g.:
{'debug': '1',
'description': 'catcuff_xgen_desc',
'file': '/tmp/cat.xgen',
'fps': '24.000000',
'frame': '1.000000',
'geom': '/tmp/cat_xgen_coll.abc',
'motionSamplesLookup': ['-0.250000', '0.250000'],
'motionSamplesPlacement': ['-0.250000', '0.250000'],
'nameSpace': 'cat_main',
'palette': 'cat_xgen_coll',
'patch': 'Paw_R_emitter',
'stats': '1',
'warning': '1',
'world': '1;0;0;0;0;1;0;0;0;0;1;0;0;0;0;1'}
Return type:dict
conductor.lib.maya_utils.parse_xgen_file(filepath)

Crude .xgen file parser for reading palette files.

Return a dictionary where the key is the module type, and the value is a list of modules of that type. Each module is a dictionary of data, where the key is the property/attribute name, and the value is the raw value of the property.

Example input file content:

Palette
    name            robert_xgen_coll
    parent
    xgDataPath        /test/robert/collections/robert_xgen_coll
    xgProjectPath        /test/shot_100/lighting/
    xgDogTag
    endAttrs

Example output:

{"Palette": [
    {
       'name': 'robert_xgen_coll',
       'parent': '',
       'xgDataPath': '/test/robert/collections/robert_xgen_coll',
       'xgDogTag': '',
       'xgProjectPath': '/test/shot_100/lighting/',
       'endAttrs': '',
    }
 ]}
conductor.lib.maya_utils.renderer_exists(renderer_name)

Return True if the given renderer (name) can be found in the maya session

Parameters:renderer_name (str) – e.g. “vray” or “arnold”
conductor.lib.maya_utils.save_current_maya_scene()

Saves current Maya scene using standard save command

conductor.lib.maya_utils.scrape_arnold_xgen_data_str(string)

Parse the given xgen_procedural.data string value into separate parts, and scrape each part for dependencies

conductor.lib.maya_utils.scrape_ass_file(ass_filepath, node_attrs, plugin_paths=())

Read/load the given arnold file with the arnold api, and seek out nodes that have filepaths of interest.

To Do:
(lws) Still need to investigate why this crashes in mayapy when arnold plugins are present (such as yeti or alshaders).
Parameters:
  • node_attrs (dict) – Key is the node type, value is a list of node attributes to query.
  • plugin_paths (tuple[str]) –

    This may be necessary when running outside of maya/interactive, so that nodes for arnold plugins (yeti, etc) can be properly loaded/used. e.g.:

    (
        "/usr/anderslanglands/alshaders/alShaders-linux-2.0.0b2-ai5.0.1.0/bin",
        "/usr/peregrinelabs/yeti/Maya2017/Yeti-v2.2.6_Maya2017-linux64/bin"
    )
    
conductor.lib.maya_utils.scrape_ass_files(ass_filepaths, node_attrs, plugin_paths=())

Read/load the given arnold files with the arnold api, and seek out nodes that have filepaths of interest.

To Do:
(lws) Still need to investigate why this crashes in mayapy when arnold plugins are present (such as yeti or alshaders).
Parameters:
  • node_attrs (dict) – Key is the node type, value is a list of node attributes to query.
  • plugin_paths (tuple[str]) –

    This may be necessary when running outside of maya/interactive, so that nodes for arnold plugins (yeti, etc) can be properly loaded/used. e.g.:

    (
        "/usr/anderslanglands/alshaders/alShaders-linux-2.0.0b2-ai5.0.1.0/bin",
        "/usr/peregrinelabs/yeti/Maya2017/Yeti-v2.2.6_Maya2017-linux64/bin"
    )
    
conductor.lib.maya_utils.scrape_ocio_dependencies()

Find the ocio config file (if it exists) and scrape it for external file dependencies

conductor.lib.maya_utils.scrape_palette_node(palette_node, palette_filepath)

Inspect/scrape the xgen palette node and parse it’s associated .xgen file for file dependencies named.

conductor.lib.maya_utils.scrape_xgen_file(filepath)

Scrape the given .xgen file for file dependencies.

conductor.lib.maya_utils.scrape_yeti_graph(yeti_node)

For the given pgYetiMaya node, scrape all of it’s external file dependencies.

Note that this node not only contains typical string attributes which may contain filepaths, but it also is a “gateway” into yeti’s own internal dependency node system…. which must be queried for file dependencies as well.

To further complicate things, these nodes allow paths to be defined relative/global (rather than absolute), so we’ll need to resolve them by reading the imageSearchPath attribute on the yeti node, as well as searching any search paths defined in PG_IMAGE_PATH environment variable.

conductor.lib.maya_utils.scrape_yeti_node_type(yeti_node, node_type, attr_names, search_paths=())

Scrape the given PgYetiMaya node for all yeti nodes of the given node_type.

Parameters:
  • yeti_node (str) – The name of the PyYetiNode to scrape for dependencies.
  • node_type (str) – The name of yeti node type to scrape for dependencies.
  • attr_names (list[str]) – The names of the yeti node’s attributes to read for dependencies.
  • search_paths (list[str]) – an optional list of directories to resolved any relative/global files that are found.
Returns:

A list of filepaths

Return type:

list[str]