mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge pull request #4340 from tokejepsen/enchancement/OP-2630_acescg_maya
This commit is contained in:
commit
f037074747
8 changed files with 237 additions and 87 deletions
|
|
@ -15,7 +15,7 @@ from math import ceil
|
|||
from six import string_types
|
||||
|
||||
from maya import cmds, mel
|
||||
import maya.api.OpenMaya as om
|
||||
from maya.api import OpenMaya
|
||||
|
||||
from openpype.client import (
|
||||
get_project,
|
||||
|
|
@ -3509,3 +3509,56 @@ def write_xgen_file(data, filepath):
|
|||
|
||||
with open(filepath, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def get_color_management_preferences():
|
||||
"""Get and resolve OCIO preferences."""
|
||||
data = {
|
||||
# Is color management enabled.
|
||||
"enabled": cmds.colorManagementPrefs(
|
||||
query=True, cmEnabled=True
|
||||
),
|
||||
"rendering_space": cmds.colorManagementPrefs(
|
||||
query=True, renderingSpaceName=True
|
||||
),
|
||||
"output_transform": cmds.colorManagementPrefs(
|
||||
query=True, outputTransformName=True
|
||||
),
|
||||
"output_transform_enabled": cmds.colorManagementPrefs(
|
||||
query=True, outputTransformEnabled=True
|
||||
),
|
||||
"view_transform": cmds.colorManagementPrefs(
|
||||
query=True, viewTransformName=True
|
||||
)
|
||||
}
|
||||
|
||||
# Split view and display from view_transform. view_transform comes in
|
||||
# format of "{view} ({display})".
|
||||
regex = re.compile(r"^(?P<view>.+) \((?P<display>.+)\)$")
|
||||
match = regex.match(data["view_transform"])
|
||||
data.update({
|
||||
"display": match.group("display"),
|
||||
"view": match.group("view")
|
||||
})
|
||||
|
||||
# Get config absolute path.
|
||||
path = cmds.colorManagementPrefs(
|
||||
query=True, configFilePath=True
|
||||
)
|
||||
|
||||
# The OCIO config supports a custom <MAYA_RESOURCES> token.
|
||||
maya_resources_token = "<MAYA_RESOURCES>"
|
||||
maya_resources_path = OpenMaya.MGlobal.getAbsolutePathToResources()
|
||||
path = path.replace(maya_resources_token, maya_resources_path)
|
||||
|
||||
data["config"] = path
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_color_management_output_transform():
|
||||
preferences = get_color_management_preferences()
|
||||
colorspace = preferences["rendering_space"]
|
||||
if preferences["output_transform_enabled"]:
|
||||
colorspace = preferences["output_transform"]
|
||||
return colorspace
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import attr
|
|||
|
||||
from . import lib
|
||||
from . import lib_rendersetup
|
||||
from openpype.pipeline.colorspace import get_ocio_config_views
|
||||
|
||||
from maya import cmds, mel
|
||||
|
||||
|
|
@ -127,6 +128,7 @@ class RenderProduct(object):
|
|||
"""
|
||||
productName = attr.ib()
|
||||
ext = attr.ib() # extension
|
||||
colorspace = attr.ib() # colorspace
|
||||
aov = attr.ib(default=None) # source aov
|
||||
driver = attr.ib(default=None) # source driver
|
||||
multipart = attr.ib(default=False) # multichannel file
|
||||
|
|
@ -562,6 +564,9 @@ class RenderProductsArnold(ARenderProducts):
|
|||
]
|
||||
|
||||
for ai_driver in ai_drivers:
|
||||
colorspace = self._get_colorspace(
|
||||
ai_driver + ".colorManagement"
|
||||
)
|
||||
# todo: check aiAOVDriver.prefix as it could have
|
||||
# a custom path prefix set for this driver
|
||||
|
||||
|
|
@ -599,12 +604,15 @@ class RenderProductsArnold(ARenderProducts):
|
|||
global_aov = self._get_attr(aov, "globalAov")
|
||||
if global_aov:
|
||||
for camera in cameras:
|
||||
product = RenderProduct(productName=name,
|
||||
ext=ext,
|
||||
aov=aov_name,
|
||||
driver=ai_driver,
|
||||
multipart=self.multipart,
|
||||
camera=camera)
|
||||
product = RenderProduct(
|
||||
productName=name,
|
||||
ext=ext,
|
||||
aov=aov_name,
|
||||
driver=ai_driver,
|
||||
multipart=self.multipart,
|
||||
camera=camera,
|
||||
colorspace=colorspace
|
||||
)
|
||||
products.append(product)
|
||||
|
||||
all_light_groups = self._get_attr(aov, "lightGroups")
|
||||
|
|
@ -612,13 +620,16 @@ class RenderProductsArnold(ARenderProducts):
|
|||
# All light groups is enabled. A single multipart
|
||||
# Render Product
|
||||
for camera in cameras:
|
||||
product = RenderProduct(productName=name + "_lgroups",
|
||||
ext=ext,
|
||||
aov=aov_name,
|
||||
driver=ai_driver,
|
||||
# Always multichannel output
|
||||
multipart=True,
|
||||
camera=camera)
|
||||
product = RenderProduct(
|
||||
productName=name + "_lgroups",
|
||||
ext=ext,
|
||||
aov=aov_name,
|
||||
driver=ai_driver,
|
||||
# Always multichannel output
|
||||
multipart=True,
|
||||
camera=camera,
|
||||
colorspace=colorspace
|
||||
)
|
||||
products.append(product)
|
||||
else:
|
||||
value = self._get_attr(aov, "lightGroupsList")
|
||||
|
|
@ -634,12 +645,36 @@ class RenderProductsArnold(ARenderProducts):
|
|||
aov=aov_name,
|
||||
driver=ai_driver,
|
||||
ext=ext,
|
||||
camera=camera
|
||||
camera=camera,
|
||||
colorspace=colorspace
|
||||
)
|
||||
products.append(product)
|
||||
|
||||
return products
|
||||
|
||||
def _get_colorspace(self, attribute):
|
||||
"""Resolve colorspace from Arnold settings."""
|
||||
|
||||
def _view_transform():
|
||||
preferences = lib.get_color_management_preferences()
|
||||
views_data = get_ocio_config_views(preferences["config"])
|
||||
view_data = views_data[
|
||||
"{}/{}".format(preferences["display"], preferences["view"])
|
||||
]
|
||||
return view_data["colorspace"]
|
||||
|
||||
def _raw():
|
||||
preferences = lib.get_color_management_preferences()
|
||||
return preferences["rendering_space"]
|
||||
|
||||
resolved_values = {
|
||||
"Raw": _raw,
|
||||
"Use View Transform": _view_transform,
|
||||
# Default. Same as Maya Preferences.
|
||||
"Use Output Transform": lib.get_color_management_output_transform
|
||||
}
|
||||
return resolved_values[self._get_attr(attribute)]()
|
||||
|
||||
def get_render_products(self):
|
||||
"""Get all AOVs.
|
||||
|
||||
|
|
@ -668,11 +703,19 @@ class RenderProductsArnold(ARenderProducts):
|
|||
]
|
||||
|
||||
default_ext = self._get_attr("defaultRenderGlobals.imfPluginKey")
|
||||
beauty_products = [RenderProduct(
|
||||
productName="beauty",
|
||||
ext=default_ext,
|
||||
driver="defaultArnoldDriver",
|
||||
camera=camera) for camera in cameras]
|
||||
colorspace = self._get_colorspace(
|
||||
"defaultArnoldDriver.colorManagement"
|
||||
)
|
||||
beauty_products = [
|
||||
RenderProduct(
|
||||
productName="beauty",
|
||||
ext=default_ext,
|
||||
driver="defaultArnoldDriver",
|
||||
camera=camera,
|
||||
colorspace=colorspace
|
||||
) for camera in cameras
|
||||
]
|
||||
|
||||
# AOVs > Legacy > Maya Render View > Mode
|
||||
aovs_enabled = bool(
|
||||
self._get_attr("defaultArnoldRenderOptions.aovMode")
|
||||
|
|
@ -825,6 +868,7 @@ class RenderProductsVray(ARenderProducts):
|
|||
productName="",
|
||||
ext=default_ext,
|
||||
camera=camera,
|
||||
colorspace=lib.get_color_management_output_transform(),
|
||||
multipart=self.multipart
|
||||
)
|
||||
)
|
||||
|
|
@ -880,10 +924,13 @@ class RenderProductsVray(ARenderProducts):
|
|||
|
||||
aov_name = self._get_vray_aov_name(aov)
|
||||
for camera in cameras:
|
||||
product = RenderProduct(productName=aov_name,
|
||||
ext=default_ext,
|
||||
aov=aov,
|
||||
camera=camera)
|
||||
product = RenderProduct(
|
||||
productName=aov_name,
|
||||
ext=default_ext,
|
||||
aov=aov,
|
||||
camera=camera,
|
||||
colorspace=lib.get_color_management_output_transform()
|
||||
)
|
||||
products.append(product)
|
||||
|
||||
return products
|
||||
|
|
@ -1367,7 +1414,12 @@ class RenderProductsMayaHardware(ARenderProducts):
|
|||
|
||||
products = []
|
||||
for cam in self.get_renderable_cameras():
|
||||
product = RenderProduct(productName="beauty", ext=ext, camera=cam)
|
||||
product = RenderProduct(
|
||||
productName="beauty",
|
||||
ext=ext,
|
||||
camera=cam,
|
||||
colorspace=lib.get_color_management_output_transform()
|
||||
)
|
||||
products.append(product)
|
||||
|
||||
return products
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ class RenderSettings(object):
|
|||
'vray': 'vraySettings.fileNamePrefix',
|
||||
'arnold': 'defaultRenderGlobals.imageFilePrefix',
|
||||
'renderman': 'rmanGlobals.imageFileFormat',
|
||||
'redshift': 'defaultRenderGlobals.imageFilePrefix'
|
||||
'redshift': 'defaultRenderGlobals.imageFilePrefix',
|
||||
'mayahardware2': 'defaultRenderGlobals.imageFilePrefix'
|
||||
}
|
||||
|
||||
_image_prefixes = {
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ class CollectMayaRender(pyblish.api.ContextPlugin):
|
|||
self.log.info(full_exp_files)
|
||||
self.log.info("collecting layer: {}".format(layer_name))
|
||||
# Get layer specific settings, might be overrides
|
||||
|
||||
colorspace_data = lib.get_color_management_preferences()
|
||||
data = {
|
||||
"subset": expected_layer_name,
|
||||
"attachTo": attach_to,
|
||||
|
|
@ -323,6 +323,9 @@ class CollectMayaRender(pyblish.api.ContextPlugin):
|
|||
"renderSetupIncludeLights": render_instance.data.get(
|
||||
"renderSetupIncludeLights"
|
||||
),
|
||||
"colorspaceConfig": colorspace_data["config"],
|
||||
"colorspaceDisplay": colorspace_data["display"],
|
||||
"colorspaceView": colorspace_data["view"],
|
||||
"strict_error_checking": render_instance.data.get(
|
||||
"strict_error_checking", True
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ from openpype.hosts.maya.api import MayaHost
|
|||
|
||||
from maya import cmds
|
||||
|
||||
|
||||
host = MayaHost()
|
||||
install_host(host)
|
||||
|
||||
|
||||
print("Starting OpenPype usersetup...")
|
||||
|
||||
|
||||
# Open Workfile Post Initialization.
|
||||
key = "OPENPYPE_OPEN_WORKFILE_POST_INITIALIZATION"
|
||||
if bool(int(os.environ.get(key, "0"))):
|
||||
|
|
|
|||
|
|
@ -434,7 +434,9 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
self.log.info(
|
||||
"Finished copying %i files" % len(resource_files))
|
||||
|
||||
def _create_instances_for_aov(self, instance_data, exp_files):
|
||||
def _create_instances_for_aov(
|
||||
self, instance_data, exp_files, additional_data
|
||||
):
|
||||
"""Create instance for each AOV found.
|
||||
|
||||
This will create new instance for every aov it can detect in expected
|
||||
|
|
@ -536,6 +538,14 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
else:
|
||||
files = os.path.basename(col)
|
||||
|
||||
# Copy render product "colorspace" data to representation.
|
||||
colorspace = ""
|
||||
products = additional_data["renderProducts"].layer_data.products
|
||||
for product in products:
|
||||
if product.productName == aov:
|
||||
colorspace = product.colorspace
|
||||
break
|
||||
|
||||
rep = {
|
||||
"name": ext,
|
||||
"ext": ext,
|
||||
|
|
@ -545,7 +555,16 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
# If expectedFile are absolute, we need only filenames
|
||||
"stagingDir": staging,
|
||||
"fps": new_instance.get("fps"),
|
||||
"tags": ["review"] if preview else []
|
||||
"tags": ["review"] if preview else [],
|
||||
"colorspaceData": {
|
||||
"colorspace": colorspace,
|
||||
"config": {
|
||||
"path": additional_data["colorspaceConfig"],
|
||||
"template": additional_data["colorspaceTemplate"]
|
||||
},
|
||||
"display": additional_data["display"],
|
||||
"view": additional_data["view"]
|
||||
}
|
||||
}
|
||||
|
||||
# support conversion from tiled to scanline
|
||||
|
|
@ -569,7 +588,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
self.log.debug("instances:{}".format(instances))
|
||||
return instances
|
||||
|
||||
def _get_representations(self, instance, exp_files):
|
||||
def _get_representations(self, instance, exp_files, additional_data):
|
||||
"""Create representations for file sequences.
|
||||
|
||||
This will return representations of expected files if they are not
|
||||
|
|
@ -914,6 +933,16 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
|
||||
self.log.info(data.get("expectedFiles"))
|
||||
|
||||
additional_data = {
|
||||
"renderProducts": instance.data["renderProducts"],
|
||||
"colorspaceConfig": instance.data["colorspaceConfig"],
|
||||
"display": instance.data["colorspaceDisplay"],
|
||||
"view": instance.data["colorspaceView"],
|
||||
"colorspaceTemplate": instance.data["colorspaceConfig"].replace(
|
||||
str(context.data["anatomy"].roots["work"]), "{root[work]}"
|
||||
)
|
||||
}
|
||||
|
||||
if isinstance(data.get("expectedFiles")[0], dict):
|
||||
# we cannot attach AOVs to other subsets as we consider every
|
||||
# AOV subset of its own.
|
||||
|
|
@ -928,7 +957,9 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
# there are multiple renderable cameras in scene)
|
||||
instances = self._create_instances_for_aov(
|
||||
instance_skeleton_data,
|
||||
data.get("expectedFiles"))
|
||||
data.get("expectedFiles"),
|
||||
additional_data
|
||||
)
|
||||
self.log.info("got {} instance{}".format(
|
||||
len(instances),
|
||||
"s" if len(instances) > 1 else ""))
|
||||
|
|
|
|||
|
|
@ -198,41 +198,19 @@ def validate_imageio_colorspace_in_config(config_path, colorspace_name):
|
|||
return True
|
||||
|
||||
|
||||
def get_ocio_config_colorspaces(config_path):
|
||||
"""Get all colorspace data
|
||||
|
||||
Wrapper function for aggregating all names and its families.
|
||||
Families can be used for building menu and submenus in gui.
|
||||
|
||||
Args:
|
||||
config_path (str): path leading to config.ocio file
|
||||
|
||||
Returns:
|
||||
dict: colorspace and family in couple
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
return get_colorspace_data_subprocess(config_path)
|
||||
|
||||
from ..scripts.ocio_wrapper import _get_colorspace_data
|
||||
return _get_colorspace_data(config_path)
|
||||
|
||||
|
||||
def get_colorspace_data_subprocess(config_path):
|
||||
"""Get colorspace data via subprocess
|
||||
def get_data_subprocess(config_path, data_type):
|
||||
"""Get data via subprocess
|
||||
|
||||
Wrapper for Python 2 hosts.
|
||||
|
||||
Args:
|
||||
config_path (str): path leading to config.ocio file
|
||||
|
||||
Returns:
|
||||
dict: colorspace and family in couple
|
||||
"""
|
||||
with _make_temp_json_file() as tmp_json_path:
|
||||
# Prepare subprocess arguments
|
||||
args = [
|
||||
"run", get_ocio_config_script_path(),
|
||||
"config", "get_colorspace",
|
||||
"config", data_type,
|
||||
"--in_path", config_path,
|
||||
"--out_path", tmp_json_path
|
||||
|
||||
|
|
@ -251,6 +229,47 @@ def get_colorspace_data_subprocess(config_path):
|
|||
return json.loads(return_json_data)
|
||||
|
||||
|
||||
def compatible_python():
|
||||
"""Only 3.9 or higher can directly use PyOpenColorIO in ocio_wrapper"""
|
||||
compatible = False
|
||||
if sys.version[0] == 3 and sys.version[1] >= 9:
|
||||
compatible = True
|
||||
return compatible
|
||||
|
||||
|
||||
def get_ocio_config_colorspaces(config_path):
|
||||
"""Get all colorspace data
|
||||
|
||||
Wrapper function for aggregating all names and its families.
|
||||
Families can be used for building menu and submenus in gui.
|
||||
|
||||
Args:
|
||||
config_path (str): path leading to config.ocio file
|
||||
|
||||
Returns:
|
||||
dict: colorspace and family in couple
|
||||
"""
|
||||
if compatible_python():
|
||||
from ..scripts.ocio_wrapper import _get_colorspace_data
|
||||
return _get_colorspace_data(config_path)
|
||||
else:
|
||||
return get_colorspace_data_subprocess(config_path)
|
||||
|
||||
|
||||
def get_colorspace_data_subprocess(config_path):
|
||||
"""Get colorspace data via subprocess
|
||||
|
||||
Wrapper for Python 2 hosts.
|
||||
|
||||
Args:
|
||||
config_path (str): path leading to config.ocio file
|
||||
|
||||
Returns:
|
||||
dict: colorspace and family in couple
|
||||
"""
|
||||
return get_data_subprocess(config_path, "get_colorspace")
|
||||
|
||||
|
||||
def get_ocio_config_views(config_path):
|
||||
"""Get all viewer data
|
||||
|
||||
|
|
@ -263,12 +282,12 @@ def get_ocio_config_views(config_path):
|
|||
Returns:
|
||||
dict: `display/viewer` and viewer data
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
if compatible_python():
|
||||
from ..scripts.ocio_wrapper import _get_views_data
|
||||
return _get_views_data(config_path)
|
||||
else:
|
||||
return get_views_data_subprocess(config_path)
|
||||
|
||||
from ..scripts.ocio_wrapper import _get_views_data
|
||||
return _get_views_data(config_path)
|
||||
|
||||
|
||||
def get_views_data_subprocess(config_path):
|
||||
"""Get viewers data via subprocess
|
||||
|
|
@ -281,27 +300,7 @@ def get_views_data_subprocess(config_path):
|
|||
Returns:
|
||||
dict: `display/viewer` and viewer data
|
||||
"""
|
||||
with _make_temp_json_file() as tmp_json_path:
|
||||
# Prepare subprocess arguments
|
||||
args = [
|
||||
"run", get_ocio_config_script_path(),
|
||||
"config", "get_views",
|
||||
"--in_path", config_path,
|
||||
"--out_path", tmp_json_path
|
||||
|
||||
]
|
||||
log.info("Executing: {}".format(" ".join(args)))
|
||||
|
||||
process_kwargs = {
|
||||
"logger": log,
|
||||
"env": {}
|
||||
}
|
||||
|
||||
run_openpype_process(*args, **process_kwargs)
|
||||
|
||||
# return all colorspaces
|
||||
return_json_data = open(tmp_json_path).read()
|
||||
return json.loads(return_json_data)
|
||||
return get_data_subprocess(config_path, "get_views")
|
||||
|
||||
|
||||
def get_imageio_config(
|
||||
|
|
|
|||
|
|
@ -157,11 +157,21 @@ def _get_views_data(config_path):
|
|||
|
||||
config = ocio.Config().CreateFromFile(str(config_path))
|
||||
|
||||
return {
|
||||
f"{d}/{v}": {"display": d, "view": v}
|
||||
for d in config.getDisplays()
|
||||
for v in config.getViews(d)
|
||||
}
|
||||
data = {}
|
||||
for display in config.getDisplays():
|
||||
for view in config.getViews(display):
|
||||
colorspace = config.getDisplayViewColorSpaceName(display, view)
|
||||
# Special token. See https://opencolorio.readthedocs.io/en/latest/guides/authoring/authoring.html#shared-views # noqa
|
||||
if colorspace == "<USE_DISPLAY_NAME>":
|
||||
colorspace = display
|
||||
|
||||
data[f"{display}/{view}"] = {
|
||||
"display": display,
|
||||
"view": view,
|
||||
"colorspace": colorspace
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue