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

Maya: Render Creator has configurable options. #3097

Merged
Show file tree
Hide file tree
Changes from 104 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
ed76a59
Remove unused code
BigRoy Feb 2, 2022
f3ac88f
Move deadline url logic closer together
BigRoy Feb 2, 2022
542f634
Re-use "read" logic from avalon.maya
BigRoy Feb 2, 2022
f18b12e
Bugfix: use 'renderer' variable that was defined to correctly capture…
BigRoy Feb 2, 2022
20c4f86
Preserve logic to get renderer from in the renderlayer
BigRoy Feb 2, 2022
a2c05a9
Simplify subset detection code
BigRoy Feb 2, 2022
47622d5
Don't collect aov_separator from settings twice
BigRoy Feb 2, 2022
9f5eb07
Don't provide render instance to override render products aov separat…
BigRoy Feb 2, 2022
44003cc
Move logic closer together
BigRoy Feb 2, 2022
ae35f0e
Refactor the "set_default_render_settings" logic out of CreateRender
BigRoy Feb 3, 2022
5429181
Move more logic to the RenderSettings class
BigRoy Feb 3, 2022
17be6f0
Use log instead of print
BigRoy Feb 3, 2022
8b0f60e
Collect the AOV separator for Render Products in Layer Data
BigRoy Feb 3, 2022
0516bb0
Fix Redshift appending .<aov> even when <aov> or <renderpass> was exp…
BigRoy Feb 3, 2022
f8e8ce5
Add docstring
BigRoy Feb 3, 2022
862167f
Fix types
BigRoy Feb 3, 2022
ee3a363
Move RenderSettings into its on api
BigRoy Feb 3, 2022
fc0891c
Cleanup render_settings.py imports + newline end of file
BigRoy Feb 3, 2022
1177ee2
Refactor Maya Create Render Schema
Apr 11, 2022
8c4d44f
add renderer settings
Apr 11, 2022
b64b0a6
add function to grab Arnold settings
Apr 19, 2022
5d56323
add redshift settings function
Apr 19, 2022
b62fa74
replace redshift settings setters with method
Apr 19, 2022
2a76f12
Merge remote-tracking branch 'origin/pr/2643' into Enhancement/OP-204…
Apr 20, 2022
7ea7a0f
remove extra code in render creator
Apr 20, 2022
854ec3b
add missing get_asset()
Apr 20, 2022
3f48859
remove unused function
Apr 20, 2022
0bc8ad9
change placement of redshift settings function
Apr 20, 2022
71434de
remove unused refactored function
Apr 21, 2022
50e60ac
removed unused refactored vray settings func
Apr 21, 2022
6f58d72
add/cleanup refactored redshift settings function
Apr 21, 2022
105fb3e
remove refactored default renderer settings func
Apr 21, 2022
2cd4229
remove unused import
Apr 21, 2022
54ff5a8
remove extra import
Apr 21, 2022
2867a2f
fix redshift comment
Apr 21, 2022
675c7a0
replace avalon CreatorError with OP's impl.
Apr 21, 2022
74cc823
remove unused import
Apr 21, 2022
4d4ca19
remove redundant code
Apr 21, 2022
9faa7e0
Rename file to match convention.
Apr 21, 2022
24a1dea
Append render settings schema.
Apr 21, 2022
c853e84
Add comment about pools
Apr 21, 2022
b5004ae
Add comment about pool_names source
Apr 21, 2022
05ed9c5
Redshift function cleanup.
Apr 21, 2022
5969124
Arnold function cleanup.
Apr 21, 2022
47e70d3
add comment about vray file format setting
Apr 21, 2022
b902b2a
Remove unnecessary checkbox
Apr 22, 2022
61b59ef
add checkbox to render settings to apply render settings on creation
Apr 25, 2022
998eb0e
remove redundant schema settings
Apr 25, 2022
365a6b3
add menu item to OpenPype menu
Apr 25, 2022
a33a905
modify project settings schema defaults for maya
Apr 25, 2022
18693cf
fix function argument, add renderer
Apr 25, 2022
d3d2757
Fix Arnold function missing arguments.
Apr 25, 2022
09a941a
Fix Redshift function missing arguments.
Apr 25, 2022
6299b01
Fix accidental typo.
Apr 25, 2022
1e251ac
Remove trailing space.
Apr 25, 2022
7a63e52
Append Arnold render settings from project settings.
Apr 25, 2022
14a3483
Add Maya window function call to initalize render objects.
Apr 25, 2022
79d7700
fix asset var name, add relevant comments
Apr 26, 2022
fb424f6
replace render settings workaround with function call
Apr 26, 2022
190c499
Merge branch 'develop' into enhancement/OP-2040_Maya_Render_creator-s…
May 2, 2022
6645be2
minor style/import fixes
May 2, 2022
2cdea36
Remove avalon import.
May 2, 2022
e0b0e30
replace avalon dependency with legacy_io
May 2, 2022
302e493
Change import position.
May 2, 2022
103cd8c
Move settings getter function
May 6, 2022
2bb96a9
Append aov handling
May 6, 2022
f6d4423
Get renderer from within settings function
May 9, 2022
ad6f562
Remove unused parameter
May 9, 2022
e4324a1
Move get_asset()
May 9, 2022
bf1daa4
style fix
May 9, 2022
bb67065
few style changes
antirotor May 10, 2022
ae0708b
Force resetting render settings
May 11, 2022
6809d37
Propagate further attributes.
May 11, 2022
e65798b
Merge remote-tracking branch 'origin/develop' into enhancement/OP-204…
May 11, 2022
b1d4969
Add variable for additional attributes
May 11, 2022
e9426df
Fix dictionary bug.
May 12, 2022
4260f8a
Attr as list to workaround ftrack limitation
May 12, 2022
12a1e9e
Handle additional attributes for MtoA
May 13, 2022
dc95b5a
Import missing library
May 13, 2022
888d700
Merge remote-tracking branch 'origin/develop' into enhancement/OP-204…
May 13, 2022
201aa69
Fix missing deadline import/logic
May 13, 2022
a06bfc1
Style fix
May 13, 2022
3780b37
Remove avalon-core.
Jun 20, 2022
2a78532
Update openpype/hosts/maya/plugins/publish/validate_render_single_cam…
Jun 20, 2022
7e10150
Remove unnecessary var statement.
Jun 20, 2022
9c4791b
Update openpype/settings/defaults/project_settings/maya.json
Jun 27, 2022
f395e65
Update openpype/settings/defaults/project_settings/maya.json
Jun 27, 2022
ecdade9
Update openpype/settings/defaults/project_settings/maya.json
Jun 27, 2022
af5a27d
Merge branch 'develop' into enhancement/OP-2040_Maya_Render_creator-s…
Jul 25, 2022
2657ff2
Replace deprecated functions
Jul 26, 2022
c7bf29d
Style fixes
Jul 26, 2022
a39eef0
Fix frame range reset.
Jul 26, 2022
6e77634
Fix attribute type check bug.
Jul 26, 2022
1cf6045
Merge remote-tracking branch 'origin/develop' into enhancement/OP-204…
Jul 26, 2022
a26fd83
Propagate render settings key to grey out apply button.
Jul 26, 2022
58309c3
Remove Mental Ray related code.
Jul 26, 2022
54bb85b
Remove unnecessary comment.
Jul 26, 2022
8d7b9af
Grab image prefixes from settings.
Jul 26, 2022
c53b7bb
Remove unnecessary unused function.
Jul 26, 2022
d63d0cf
Remove incorrect code.
Jul 29, 2022
a11ef9f
Append frame reset feature, handle prefix key properly
Jul 29, 2022
9967cd0
Append settings propagation to render instance creator.
Jul 29, 2022
1f12697
Style fixes.
Jul 29, 2022
487830f
Style fix
Jul 29, 2022
498ee1d
Fix schema to store as lists
Aug 1, 2022
84a6c14
Handle additional attributes
Aug 1, 2022
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
55 changes: 52 additions & 3 deletions openpype/hosts/maya/api/lib_renderproducts.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@

RENDERMAN_IMAGE_DIR = "maya/<scene>/<layer>"


def has_tokens(string, tokens):
"""Return whether any of tokens is in input string (case-insensitive)"""
pattern = "({})".format("|".join(re.escape(token) for token in tokens))
match = re.search(pattern, string, re.IGNORECASE)
return bool(match)


@attr.s
class LayerMetadata(object):
"""Data class for Render Layer metadata."""
Expand All @@ -99,6 +107,12 @@ class LayerMetadata(object):
# Render Products
products = attr.ib(init=False, default=attr.Factory(list))

# The AOV separator token. Note that not all renderers define an explicit
# render separator but allow to put the AOV/RenderPass token anywhere in
# the file path prefix. For those renderers we'll fall back to whatever
# is between the last occurrences of <RenderLayer> and <RenderPass> tokens.
aov_separator = attr.ib(default="_")


@attr.s
class RenderProduct(object):
Expand Down Expand Up @@ -183,7 +197,6 @@ def __init__(self, layer, render_instance):
self.layer = layer
self.render_instance = render_instance
self.multipart = False
self.aov_separator = render_instance.data.get("aovSeparator", "_")

# Initialize
self.layer_data = self._get_layer_data()
Expand Down Expand Up @@ -319,6 +332,31 @@ def _get_layer_data(self):
# defaultRenderLayer renders as masterLayer
layer_name = "masterLayer"

# AOV separator - default behavior extracts the part between
# last occurences of <RenderLayer> and <RenderPass>
# todo: This code also triggers for V-Ray which overrides it explicitly
# so this code will invalidly debug log it couldn't extract the
# aov separator even though it does set it in RenderProductsVray
layer_tokens = ["<renderlayer>", "<layer>"]
aov_tokens = ["<aov>", "<renderpass>"]

def match_last(tokens, text):
"""regex match the last occurence from a list of tokens"""
pattern = "(?:.*)({})".format("|".join(tokens))
return re.search(pattern, text, re.IGNORECASE)

layer_match = match_last(layer_tokens, file_prefix)
aov_match = match_last(aov_tokens, file_prefix)
kwargs = {}
if layer_match and aov_match:
matches = sorted((layer_match, aov_match),
key=lambda match: match.end(1))
separator = file_prefix[matches[0].end(1):matches[1].start(1)]
kwargs["aov_separator"] = separator
else:
log.debug("Couldn't extract aov separator from "
"file prefix: {}".format(file_prefix))

# todo: Support Custom Frames sequences 0,5-10,100-120
# Deadline allows submitting renders with a custom frame list
# to support those cases we might want to allow 'custom frames'
Expand All @@ -335,7 +373,8 @@ def _get_layer_data(self):
layerName=layer_name,
renderer=self.renderer,
defaultExt=self._get_attr("defaultRenderGlobals.imfPluginKey"),
filePrefix=file_prefix
filePrefix=file_prefix,
**kwargs
)

def _generate_file_sequence(
Expand Down Expand Up @@ -680,9 +719,17 @@ def get_renderer_prefix(self):

"""
prefix = super(RenderProductsVray, self).get_renderer_prefix()
prefix = "{}{}<aov>".format(prefix, self.aov_separator)
aov_separator = self._get_aov_separator()
prefix = "{}{}<aov>".format(prefix, aov_separator)
return prefix

def _get_aov_separator(self):
# type: () -> str
"""Return the V-Ray AOV/Render Elements separator"""
return self._get_attr(
"vraySettings.fileNameRenderElementSeparator"
)

def _get_layer_data(self):
# type: () -> LayerMetadata
"""Override to get vray specific extension."""
Expand All @@ -694,6 +741,8 @@ def _get_layer_data(self):
layer_data.defaultExt = default_ext
layer_data.padding = self._get_attr("vraySettings.fileNamePadding")

layer_data.aov_separator = self._get_aov_separator()

return layer_data

def get_render_products(self):
Expand Down
216 changes: 216 additions & 0 deletions openpype/hosts/maya/api/lib_rendersettings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
"""Class for handling Render Settings."""
from maya import cmds # noqa
import maya.mel as mel
import six
import sys

from openpype.api import (
get_project_settings,
get_current_project_settings
)

from openpype.pipeline import legacy_io
from openpype.pipeline import CreatorError
from openpype.pipeline.context_tools import get_current_project_asset
from openpype.hosts.maya.api.commands import reset_frame_range


class RenderSettings(object):

_image_prefix_nodes = {
'vray': 'vraySettings.fileNamePrefix',
'arnold': 'defaultRenderGlobals.imageFilePrefix',
'renderman': 'defaultRenderGlobals.imageFilePrefix',
'redshift': 'defaultRenderGlobals.imageFilePrefix'
}

_image_prefixes = {
'vray': get_current_project_settings()["maya"]["RenderSettings"]["vray_renderer"]["image_prefix"], # noqa
'arnold': get_current_project_settings()["maya"]["RenderSettings"]["arnold_renderer"]["image_prefix"], # noqa
'renderman': 'maya/<Scene>/<layer>/<layer>{aov_separator}<aov>',
'redshift': get_current_project_settings()["maya"]["RenderSettings"]["redshift_renderer"]["image_prefix"] # noqa
}

_aov_chars = {
"dot": ".",
"dash": "-",
"underscore": "_"
}

@classmethod
def get_image_prefix_attr(cls, renderer):
return cls._image_prefix_nodes[renderer]

def __init__(self, project_settings=None):
self._project_settings = project_settings
if not self._project_settings:
self._project_settings = get_project_settings(
legacy_io.Session["AVALON_PROJECT"]
)

def set_default_renderer_settings(self, renderer=None):
"""Set basic settings based on renderer."""
if not renderer:
renderer = cmds.getAttr(
'defaultRenderGlobals.currentRenderer').lower()

asset_doc = get_current_project_asset()
# project_settings/maya/create/CreateRender/aov_separator
try:
aov_separator = self._aov_chars[(
self._project_settings["maya"]
["create"]
["CreateRender"]
["aov_separator"]
)]
except KeyError:
aov_separator = "_"
reset_frame = self._project_settings["maya"]["RenderSettings"]["reset_current_frame"] # noqa

if reset_frame:
start_frame = cmds.getAttr("defaultRenderGlobals.startFrame")
cmds.currentTime(start_frame, edit=True)

if renderer in self._image_prefix_nodes:
prefix = self._image_prefixes[renderer]
prefix = prefix.replace("{aov_separator}", aov_separator)
cmds.setAttr(self._image_prefix_nodes[renderer],
prefix, type="string") # noqa
else:
print("{0} isn't a supported renderer to autoset settings.".format(renderer)) # noqa

# TODO: handle not having res values in the doc
width = asset_doc["data"].get("resolutionWidth")
height = asset_doc["data"].get("resolutionHeight")

if renderer == "arnold":
# set renderer settings for Arnold from project settings
self._set_arnold_settings(width, height)

if renderer == "vray":
self._set_vray_settings(aov_separator, width, height)

if renderer == "redshift":
self._set_redshift_settings(width, height)

def _set_arnold_settings(self, width, height):
"""Sets settings for Arnold."""
from mtoa.core import createOptions # noqa
from mtoa.aovs import AOVInterface # noqa
createOptions()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move the mtoa import here? Technically you can install Maya without Arnold so I'd rather not have it required by forcing the import on top level.

Also, since this file also has other renderers implemented I'd avoid importing createOptions into this module but instead just do import mtoa.core and mtoa.core.createOptions() to remain explicit.

Additionally, be aware that the call to createOptions required the mtoa plug-in to currently be loaded in the Plug-in Manager.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Roy those are good points I'll do that!

arnold_render_presets = self._project_settings["maya"]["RenderSettings"]["arnold_renderer"] # noqa
# Force resetting settings and AOV list to avoid having to deal with
# AOV checking logic, for now.
# This is a work around because the standard
# function to revert render settings does not reset AOVs list in MtoA
# Fetch current aovs in case there's any.
current_aovs = AOVInterface().getAOVs()
# Remove fetched AOVs
AOVInterface().removeAOVs(current_aovs)
mel.eval("unifiedRenderGlobalsRevertToDefault")
img_ext = arnold_render_presets["image_format"]
img_prefix = arnold_render_presets["image_prefix"]
aovs = arnold_render_presets["aov_list"]
img_tiled = arnold_render_presets["tiled"]
multi_exr = arnold_render_presets["multilayer_exr"]
additional_options = arnold_render_presets["additional_options"]
for aov in aovs:
AOVInterface('defaultArnoldRenderOptions').addAOV(aov)

cmds.setAttr("defaultResolution.width", width)
cmds.setAttr("defaultResolution.height", height)

self._set_global_output_settings()

cmds.setAttr(
"defaultRenderGlobals.imageFilePrefix", img_prefix, type="string")

cmds.setAttr(
"defaultArnoldDriver.ai_translator", img_ext, type="string")

cmds.setAttr(
"defaultArnoldDriver.exrTiled", img_tiled)

cmds.setAttr(
"defaultArnoldDriver.mergeAOVs", multi_exr)
# Passes additional options in from the schema as a list
# but converts it to a dictionary because ftrack doesn't
# allow fullstops in custom attributes. Then checks for
# type of MtoA attribute passed to adjust the `setAttr`
# command accordingly.
for item in additional_options:
attribute, value = item
if (cmds.getAttr(str(attribute), type=True)) == "long":
cmds.setAttr(str(attribute), int(value))
elif (cmds.getAttr(str(attribute), type=True)) == "bool":
cmds.setAttr(str(attribute), int(value), type = "Boolean") # noqa
elif (cmds.getAttr(str(attribute), type=True)) == "string":
cmds.setAttr(str(attribute), str(value), type = "string") # noqa
reset_frame_range()

def _set_redshift_settings(self, width, height):
"""Sets settings for Redshift."""
redshift_render_presets = (
self._project_settings
["maya"]
["RenderSettings"]
["redshift_renderer"]
)
img_ext = redshift_render_presets.get("image_format")
self._set_global_output_settings()
cmds.setAttr("redshiftOptions.imageFormat", img_ext)
cmds.setAttr("defaultResolution.width", width)
cmds.setAttr("defaultResolution.height", height)

def _set_vray_settings(self, aov_separator, width, height):
# type: (str, int, int) -> None
"""Sets important settings for Vray."""
settings = cmds.ls(type="VRaySettingsNode")
node = settings[0] if settings else cmds.createNode("VRaySettingsNode")

# Set aov separator
# First we need to explicitly set the UI items in Render Settings
# because that is also what V-Ray updates to when that Render Settings
# UI did initialize before and refreshes again.
MENU = "vrayRenderElementSeparator"
if cmds.optionMenuGrp(MENU, query=True, exists=True):
items = cmds.optionMenuGrp(MENU, query=True, ill=True)
separators = [cmds.menuItem(i, query=True, label=True) for i in items] # noqa: E501
try:
sep_idx = separators.index(aov_separator)
except ValueError as e:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local variable 'e' is assigned to but never used

six.reraise(
CreatorError,
CreatorError(
"AOV character {} not in {}".format(
aov_separator, separators)),
sys.exc_info()[2])

cmds.optionMenuGrp(MENU, edit=True, select=sep_idx + 1)

# Set the render element attribute as string. This is also what V-Ray
# sets whenever the `vrayRenderElementSeparator` menu items switch
cmds.setAttr(
"{}.fileNameRenderElementSeparator".format(node),
aov_separator,
type="string"
)

# Set render file format to exr
cmds.setAttr("{}.imageFormatStr".format(node), "exr", type="string")

# animType
cmds.setAttr("{}.animType".format(node), 1)

# resolution
cmds.setAttr("{}.width".format(node), width)
cmds.setAttr("{}.height".format(node), height)

@staticmethod
def _set_global_output_settings():
# enable animation
cmds.setAttr("defaultRenderGlobals.outFormatControl", 0)
cmds.setAttr("defaultRenderGlobals.animation", 1)
cmds.setAttr("defaultRenderGlobals.putFrameBeforeExt", 1)
cmds.setAttr("defaultRenderGlobals.extensionPadding", 4)
10 changes: 9 additions & 1 deletion openpype/hosts/maya/api/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from openpype.settings import get_project_settings
from openpype.pipeline import legacy_io
from openpype.tools.utils import host_tools
from openpype.hosts.maya.api import lib
from openpype.hosts.maya.api import lib, lib_rendersettings
from .lib import get_main_window, IS_HEADLESS
from .commands import reset_frame_range

Expand Down Expand Up @@ -44,6 +44,7 @@ def deferred():
parent="MayaWindow"
)

renderer = cmds.getAttr('defaultRenderGlobals.currentRenderer').lower()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local variable 'renderer' is assigned to but never used

# Create context menu
context_label = "{}, {}".format(
legacy_io.Session["AVALON_ASSET"],
Expand Down Expand Up @@ -98,6 +99,13 @@ def deferred():

cmds.menuItem(divider=True)

cmds.menuItem(
"Set Render Settings",
command=lambda *args: lib_rendersettings.RenderSettings().set_default_renderer_settings() # noqa
)

cmds.menuItem(divider=True)

cmds.menuItem(
"Work Files...",
command=lambda *args: host_tools.show_workfiles(
Expand Down
Loading