Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Maya: handle referenced AOVs for Vray #824

Merged
merged 5 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 42 additions & 24 deletions pype/hosts/maya/expected_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
ImagePrefixes (dict): Mapping between renderers and their respective
image prefix atrribute names.

Todo:
Determine `multipart` from render instance.

"""

import types
Expand Down Expand Up @@ -94,6 +97,10 @@ class ExpectedFiles:

multipart = False

def __init__(self, render_instance):
"""Constructor."""
self._render_instance = render_instance

def get(self, renderer, layer):
"""Get expected files for given renderer and render layer.

Expand All @@ -114,15 +121,20 @@ def get(self, renderer, layer):
renderSetup.instance().switchToLayerUsingLegacyName(layer)

if renderer.lower() == "arnold":
return self._get_files(ExpectedFilesArnold(layer))
return self._get_files(ExpectedFilesArnold(layer,
self._render_instance))
elif renderer.lower() == "vray":
return self._get_files(ExpectedFilesVray(layer))
return self._get_files(ExpectedFilesVray(
layer, self._render_instance))
elif renderer.lower() == "redshift":
return self._get_files(ExpectedFilesRedshift(layer))
return self._get_files(ExpectedFilesRedshift(
layer, self._render_instance))
elif renderer.lower() == "mentalray":
return self._get_files(ExpectedFilesMentalray(layer))
return self._get_files(ExpectedFilesMentalray(
layer, self._render_instance))
elif renderer.lower() == "renderman":
return self._get_files(ExpectedFilesRenderman(layer))
return self._get_files(ExpectedFilesRenderman(
layer, self._render_instance))
else:
raise UnsupportedRendererException(
"unsupported {}".format(renderer)
Expand All @@ -149,9 +161,10 @@ class AExpectedFiles:
layer = None
multipart = False

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Constructor."""
self.layer = layer
self.render_instance = render_instance

@abstractmethod
def get_aovs(self):
Expand Down Expand Up @@ -460,9 +473,9 @@ class ExpectedFilesArnold(AExpectedFiles):
"maya": "",
}

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Constructor."""
super(ExpectedFilesArnold, self).__init__(layer)
super(ExpectedFilesArnold, self).__init__(layer, render_instance)
self.renderer = "arnold"

def get_aovs(self):
Expand Down Expand Up @@ -531,9 +544,9 @@ def get_aovs(self):
class ExpectedFilesVray(AExpectedFiles):
"""Expected files for V-Ray renderer."""

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Constructor."""
super(ExpectedFilesVray, self).__init__(layer)
super(ExpectedFilesVray, self).__init__(layer, render_instance)
self.renderer = "vray"

def get_renderer_prefix(self):
Expand Down Expand Up @@ -614,15 +627,20 @@ def get_aovs(self):
if default_ext == "exr (multichannel)" or default_ext == "exr (deep)":
default_ext = "exr"

# filter all namespace prefixed AOVs - they are pulled in from
# references and are not rendered.
vr_aovs = [
n
for n in cmds.ls(
type=["VRayRenderElement", "VRayRenderElementSet"]
)
if len(n.split(":")) == 1
]
# handle aovs from references
use_ref_aovs = self.render_instance.data.get(
"vrayUseReferencedAovs", False) or False

# this will have list of all aovs no matter if they are coming from
# reference or not.
vr_aovs = cmds.ls(
type=["VRayRenderElement", "VRayRenderElementSet"]) or []
if not use_ref_aovs:
ref_aovs = cmds.ls(
type=["VRayRenderElement", "VRayRenderElementSet"],
referencedNodes=True) or []
# get difference
vr_aovs = list(set(vr_aovs) - set(ref_aovs))

for aov in vr_aovs:
enabled = self.maya_is_true(cmds.getAttr("{}.enabled".format(aov)))
Expand Down Expand Up @@ -696,9 +714,9 @@ class ExpectedFilesRedshift(AExpectedFiles):

ext_mapping = ["iff", "exr", "tif", "png", "tga", "jpg"]

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Construtor."""
super(ExpectedFilesRedshift, self).__init__(layer)
super(ExpectedFilesRedshift, self).__init__(layer, render_instance)
self.renderer = "redshift"

def get_renderer_prefix(self):
Expand Down Expand Up @@ -815,9 +833,9 @@ class ExpectedFilesRenderman(AExpectedFiles):
This is very rudimentary and needs more love and testing.
"""

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Constructor."""
super(ExpectedFilesRenderman, self).__init__(layer)
super(ExpectedFilesRenderman, self).__init__(layer, render_instance)
self.renderer = "renderman"

def get_aovs(self):
Expand Down Expand Up @@ -880,7 +898,7 @@ def get_files(self):
class ExpectedFilesMentalray(AExpectedFiles):
"""Skeleton unimplemented class for Mentalray renderer."""

def __init__(self, layer):
def __init__(self, layer, render_instance):
"""Constructor.

Raises:
Expand Down
1 change: 1 addition & 0 deletions pype/plugins/maya/create/create_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ def _create_render_settings(self):
self.data["tilesX"] = 2
self.data["tilesY"] = 2
self.data["convertToScanline"] = False
self.data["vrayUseReferencedAovs"] = False
# Disable for now as this feature is not working yet
# self.data["assScene"] = False

Expand Down
5 changes: 3 additions & 2 deletions pype/plugins/maya/publish/collect_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def process(self, context):

# return all expected files for all cameras and aovs in given
# frame range
ef = ExpectedFiles()
ef = ExpectedFiles(render_instance)
exp_files = ef.get(renderer, layer_name)
self.log.info("multipart: {}".format(ef.multipart))
assert exp_files, "no file names were generated, this is bug"
Expand Down Expand Up @@ -248,7 +248,8 @@ def process(self, context):
"tilesX": render_instance.data.get("tilesX") or 2,
"tilesY": render_instance.data.get("tilesY") or 2,
"priority": render_instance.data.get("priority"),
"convertToScanline": render_instance.data.get("convertToScanline") or False # noqa: E501
"convertToScanline": render_instance.data.get("convertToScanline") or False, # noqa: E501
"vrayUseReferencedAovs": render_instance.data.get("vrayUseReferencedAovs") or False # noqa: E501
}

if self.sync_workfile_version:
Expand Down
90 changes: 90 additions & 0 deletions pype/plugins/maya/publish/validate_vray_referenced_aovs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
"""Validate if there are AOVs pulled from references."""
import pyblish.api
import types
from maya import cmds

import pype.hosts.maya.action


class ValidateVrayReferencedAOVs(pyblish.api.InstancePlugin):
"""Validate whether the V-Ray Render Elements (AOVs) include references.
This will check if there are AOVs pulled from references. If
`Vray Use Referenced Aovs` is checked on render instance, u must add those
manually to Render Elements as Pype will expect them to be rendered.
"""

order = pyblish.api.ValidatorOrder
label = 'VRay Referenced AOVs'
hosts = ['maya']
families = ['renderlayer']
actions = [pype.api.RepairContextAction]

def process(self, instance):
"""Plugin main entry point."""
if instance.data.get("renderer") != "vray":
# If not V-Ray ignore..
return

ref_aovs = cmds.ls(
type=["VRayRenderElement", "VRayRenderElementSet"],
referencedNodes=True)
ref_aovs_enabled = ValidateVrayReferencedAOVs.maya_is_true(
cmds.getAttr("vraySettings.relements_usereferenced"))

if not instance.data.get("vrayUseReferencedAovs"):
if ref_aovs_enabled and ref_aovs:
self.log.warning((
"Referenced AOVs are enabled in Vray "
"Render Settings and are detected in scene, but "
"Pype render instance option for referenced AOVs is "
"disabled. Those AOVs will be rendered but not published "
"by Pype."
))
self.log.warning(", ".join(ref_aovs))
else:
if not ref_aovs:
self.log.warning((
"Use of referenced AOVs enabled but there are none "
"in the scene."
))
if not ref_aovs_enabled:
self.log.error((
"'Use referenced' not enabled in Vray Render Settings."
))
raise AssertionError("Invalid render settings")

@classmethod
def repair(cls, context):
"""Repair action."""
vray_settings = cmds.ls(type="VRaySettingsNode")
if not vray_settings:
node = cmds.createNode("VRaySettingsNode")
else:
node = vray_settings[0]

cmds.setAttr("{}.relements_usereferenced".format(node), True)

@staticmethod
def maya_is_true(attr_val):
"""Whether a Maya attr evaluates to True.
When querying an attribute value from an ambiguous object the
Maya API will return a list of values, which need to be properly
handled to evaluate properly.
Args:
attr_val (mixed): Maya attribute to be evaluated as bool.
Returns:
bool: cast Maya attribute to Pythons boolean value.
"""
if isinstance(attr_val, types.BooleanType):
return attr_val
elif isinstance(attr_val, (types.ListType, types.GeneratorType)):
return any(attr_val)
else:
return bool(attr_val)