Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collect required data for local and farm render jobs to have a 'colorspace' value specified #75

Merged
merged 3 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
68 changes: 32 additions & 36 deletions client/ayon_houdini/api/colorspace.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,55 @@
from typing import List

import attr
import hou
from ayon_houdini.api.lib import get_color_management_preferences
from ayon_core.pipeline.colorspace import get_display_view_colorspace_name
from ayon_core.pipeline.colorspace import (
get_display_view_colorspace_name,
get_ocio_config_colorspaces
)


@attr.s
class LayerMetadata(object):
"""Data class for Render Layer metadata."""
frameStart = attr.ib()
frameEnd = attr.ib()
products: "List[RenderProduct]" = attr.ib()


@attr.s
class RenderProduct(object):
"""Getting Colorspace as
Specific Render Product Parameter for submitting
publish job.

"""
"""Specific Render Product Parameter for submitting."""
colorspace = attr.ib() # colorspace
view = attr.ib()
productName = attr.ib(default=None)


class ARenderProduct(object):
"""This is the minimal data structure required to get
`ayon_core.pipeline.farm.pyblish_functions.create_instances_for_aov` to
work with deadline addon's job submissions."""
# TODO: The exact data structure should actually be defined in core for all
# addons to align.
def __init__(self, aov_names: List[str]):
colorspace = get_scene_linear_colorspace()
products = [
RenderProduct(colorspace=colorspace, productName=aov_name)
for aov_name in aov_names
]
self.layer_data = LayerMetadata(products=products)

def __init__(self):
"""Constructor."""
# Initialize
self.layer_data = self._get_layer_data()
self.layer_data.products = self.get_colorspace_data()

def _get_layer_data(self):
return LayerMetadata(
frameStart=int(hou.playbar.frameRange()[0]),
frameEnd=int(hou.playbar.frameRange()[1]),
)

def get_colorspace_data(self):
"""To be implemented by renderer class.

This should return a list of RenderProducts.
def get_scene_linear_colorspace():
"""Return colorspace name for Houdini's OCIO config scene linear role.

Returns:
list: List of RenderProduct
By default, renderers in Houdini render output images in the scene linear
role colorspace.

"""
data = get_color_management_preferences()
colorspace_data = [
RenderProduct(
colorspace=data["display"],
view=data["view"],
productName=""
)
]
return colorspace_data
Returns:
Optional[str]: The colorspace name for the 'scene_linear' role in
the OCIO config Houdini is currently set to.
"""
ocio_config_path = hou.Color.ocio_configPath()
colorspaces = get_ocio_config_colorspaces(ocio_config_path)
return colorspaces["roles"].get("scene_linear", {}).get("colorspace")


def get_default_display_view_colorspace():
Expand Down
31 changes: 30 additions & 1 deletion client/ayon_houdini/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,41 @@ def replace(match):

def get_color_management_preferences():
"""Get default OCIO preferences"""
return {

preferences = {
"config": hou.Color.ocio_configPath(),
"display": hou.Color.ocio_defaultDisplay(),
"view": hou.Color.ocio_defaultView()
}

# Note: For whatever reason they are cases where `view` may be an empty
# string even though a valid default display is set where `PyOpenColorIO`
# does correctly return the values.
# Workaround to get the correct default view
if preferences["config"] and not preferences["view"]:
log.debug(
"Houdini `hou.Color.ocio_defaultView()` returned empty value."
" Falling back to `PyOpenColorIO` to get the default view.")
try:
import PyOpenColorIO
except ImportError:
log.warning(
"Unable to workaround empty return value of "
"`hou.Color.ocio_defaultView()` because `PyOpenColorIO` is "
"not available.")
return preferences

config_path = preferences["config"]
config = PyOpenColorIO.Config.CreateFromFile(config_path)
display = config.getDefaultDisplay()
assert display == preferences["display"], \
"Houdini default OCIO display must match config default display"
view = config.getDefaultView(display)
preferences["display"] = display
preferences["view"] = view

return preferences


def get_obj_node_output(obj_node):
"""Find output node.
Expand Down
14 changes: 2 additions & 12 deletions client/ayon_houdini/plugins/publish/collect_arnold_rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
import hou
import pyblish.api

from ayon_houdini.api import colorspace, plugin
from ayon_houdini.api.lib import (
get_color_management_preferences,
evalParmNoFrame
)
from ayon_houdini.api import plugin
from ayon_houdini.api.lib import evalParmNoFrame


class CollectArnoldROPRenderProducts(plugin.HoudiniInstancePlugin):
Expand Down Expand Up @@ -100,7 +97,6 @@ def process(self, instance):
self.log.debug("Found render product: {}".format(product))

instance.data["files"] = list(render_products)
instance.data["renderProducts"] = colorspace.ARenderProduct()

# For now by default do NOT try to publish the rendered output
instance.data["publishJobState"] = "Suspended"
Expand All @@ -110,12 +106,6 @@ def process(self, instance):
instance.data["expectedFiles"] = list()
instance.data["expectedFiles"].append(files_by_aov)

# update the colorspace data
colorspace_data = get_color_management_preferences()
instance.data["colorspaceConfig"] = colorspace_data["config"]
instance.data["colorspaceDisplay"] = colorspace_data["display"]
instance.data["colorspaceView"] = colorspace_data["view"]

def get_render_product_name(self, prefix, suffix):
"""Return the output filename using the AOV prefix and suffix"""

Expand Down
17 changes: 2 additions & 15 deletions client/ayon_houdini/plugins/publish/collect_karma_rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@
import hou
import pyblish.api

from ayon_houdini.api.lib import (
evalParmNoFrame,
get_color_management_preferences
)
from ayon_houdini.api import (
colorspace,
plugin
)
from ayon_houdini.api.lib import evalParmNoFrame
from ayon_houdini.api import plugin


class CollectKarmaROPRenderProducts(plugin.HoudiniInstancePlugin):
Expand Down Expand Up @@ -63,7 +57,6 @@ def process(self, instance):

filenames = list(render_products)
instance.data["files"] = filenames
instance.data["renderProducts"] = colorspace.ARenderProduct()

for product in render_products:
self.log.debug("Found render product: %s" % product)
Expand All @@ -72,12 +65,6 @@ def process(self, instance):
instance.data["expectedFiles"] = list()
instance.data["expectedFiles"].append(files_by_aov)

# update the colorspace data
colorspace_data = get_color_management_preferences()
instance.data["colorspaceConfig"] = colorspace_data["config"]
instance.data["colorspaceDisplay"] = colorspace_data["display"]
instance.data["colorspaceView"] = colorspace_data["view"]

def get_render_product_name(self, prefix, suffix):
product_name = prefix
if suffix:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
from ayon_core.pipeline.farm.patterning import match_aov_pattern
from ayon_core.pipeline.publish import (
get_plugin_settings,
apply_plugin_settings_automatically
apply_plugin_settings_automatically,
ColormanagedPyblishPluginMixin
)
from ayon_houdini.api import plugin
from ayon_houdini.api.colorspace import get_scene_linear_colorspace


class CollectLocalRenderInstances(plugin.HoudiniInstancePlugin):
class CollectLocalRenderInstances(plugin.HoudiniInstancePlugin,
ColormanagedPyblishPluginMixin):
"""Collect instances for local render.

Agnostic Local Render Collector.
Expand Down Expand Up @@ -49,9 +52,9 @@ def apply_settings(cls, project_settings):
# get aov_filter from deadline settings
cls.aov_filter = project_settings["deadline"]["publish"]["ProcessSubmittedJobOnFarm"]["aov_filter"]
cls.aov_filter = {
item["name"]: item["value"]
for item in cls.aov_filter
}
item["name"]: item["value"]
for item in cls.aov_filter
}

def process(self, instance):

Expand All @@ -74,6 +77,14 @@ def process(self, instance):
instance.data["productName"]
)

# NOTE: The assumption that the output image's colorspace is the
# scene linear role may be incorrect. Certain renderers, like
# Karma allow overriding explicitly the output colorspace of the
# image. Such override are currently not considered since these
# would need to be detected in a renderer-specific way and the
# majority of production scenarios these would not be overridden.
# TODO: Support renderer-specific explicit colorspace overrides
colorspace = get_scene_linear_colorspace()
for aov_name, aov_filepaths in expectedFiles.items():
product_name = product_group

Expand Down Expand Up @@ -108,6 +119,21 @@ def process(self, instance):
if len(aov_filenames) == 1:
aov_filenames = aov_filenames[0]

representation = {
"stagingDir": staging_dir,
"ext": ext,
"name": ext,
"tags": ["review"] if preview else [],
"files": aov_filenames,
"frameStart": instance.data["frameStartHandle"],
"frameEnd": instance.data["frameEndHandle"]
}

# Set the colorspace for the representation
self.set_representation_colorspace(representation,
context,
colorspace=colorspace)

aov_instance.data.update({
# 'label': label,
"task": instance.data["task"],
Expand All @@ -120,17 +146,7 @@ def process(self, instance):
"productGroup": product_group,
"families": ["render.local.hou", "review"],
"instance_node": instance.data["instance_node"],
"representations": [
{
"stagingDir": staging_dir,
"ext": ext,
"name": ext,
"tags": ["review"] if preview else [],
"files": aov_filenames,
"frameStart": instance.data["frameStartHandle"],
"frameEnd": instance.data["frameEndHandle"]
}
]
"representations": [representation]
})

# Skip integrating original render instance.
Expand Down
17 changes: 2 additions & 15 deletions client/ayon_houdini/plugins/publish/collect_mantra_rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@
import hou
import pyblish.api

from ayon_houdini.api.lib import (
evalParmNoFrame,
get_color_management_preferences
)
from ayon_houdini.api import (
colorspace,
plugin
)
from ayon_houdini.api.lib import evalParmNoFrame
from ayon_houdini.api import plugin


class CollectMantraROPRenderProducts(plugin.HoudiniInstancePlugin):
Expand Down Expand Up @@ -108,7 +102,6 @@ def process(self, instance):

filenames = list(render_products)
instance.data["files"] = filenames
instance.data["renderProducts"] = colorspace.ARenderProduct()

# For now by default do NOT try to publish the rendered output
instance.data["publishJobState"] = "Suspended"
Expand All @@ -118,12 +111,6 @@ def process(self, instance):
instance.data["expectedFiles"] = list()
instance.data["expectedFiles"].append(files_by_aov)

# update the colorspace data
colorspace_data = get_color_management_preferences()
instance.data["colorspaceConfig"] = colorspace_data["config"]
instance.data["colorspaceDisplay"] = colorspace_data["display"]
instance.data["colorspaceView"] = colorspace_data["view"]

def get_render_product_name(self, prefix, suffix):
product_name = prefix
if suffix:
Expand Down
17 changes: 2 additions & 15 deletions client/ayon_houdini/plugins/publish/collect_redshift_rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@
import hou
import pyblish.api

from ayon_houdini.api.lib import (
evalParmNoFrame,
get_color_management_preferences
)
from ayon_houdini.api import (
colorspace,
plugin
)
from ayon_houdini.api.lib import evalParmNoFrame
from ayon_houdini.api import plugin


class CollectRedshiftROPRenderProducts(plugin.HoudiniInstancePlugin):
Expand Down Expand Up @@ -119,7 +113,6 @@ def process(self, instance):

filenames = list(render_products)
instance.data["files"] = filenames
instance.data["renderProducts"] = colorspace.ARenderProduct()

# For now by default do NOT try to publish the rendered output
instance.data["publishJobState"] = "Suspended"
Expand All @@ -129,12 +122,6 @@ def process(self, instance):
instance.data["expectedFiles"] = []
instance.data["expectedFiles"].append(files_by_aov)

# update the colorspace data
colorspace_data = get_color_management_preferences()
instance.data["colorspaceConfig"] = colorspace_data["config"]
instance.data["colorspaceDisplay"] = colorspace_data["display"]
instance.data["colorspaceView"] = colorspace_data["view"]

def get_render_product_name(self, prefix, suffix):
"""Return the output filename using the AOV prefix and suffix"""

Expand Down
Loading