From 54e2687afa13b4963b86ecbc4b99786e1a57ced2 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Tue, 18 Jul 2023 10:21:21 +0300 Subject: [PATCH 01/25] create review validator --- .../publish/validate_review_colorspace.py | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py new file mode 100644 index 0000000000..18ca39234c --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +import pyblish.api + +from collections import defaultdict +from openpype.pipeline import PublishValidationError + + +class ValidateReviewColorspace(pyblish.api.InstancePlugin): + """Validate Review Colorspace parameters. + + + """ + + order = pyblish.api.ValidatorOrder + 0.1 + families = ["review"] + hosts = ["houdini"] + label = "Validate Review Colorspace" + + def process(self, instance): + invalid = self.get_invalid(instance) + if invalid: + raise PublishValidationError( + ("Colorspace parameter is not valid."), + title=self.label + ) + + @classmethod + def get_invalid(cls, instance): + import hou # noqa + output_node = instance.data.get("output_node") + rop_node = hou.node(instance.data["instance_node"]) + if output_node is None: + cls.log.error( + "SOP Output node in '%s' does not exist. " + "Ensure a valid SOP output path is set." % rop_node.path() + ) + + return [rop_node.path()] + + pattern = rop_node.parm("prim_to_detail_pattern").eval().strip() + if not pattern: + cls.log.debug( + "Alembic ROP has no 'Primitive to Detail' pattern. " + "Validation is ignored.." + ) + return + + build_from_path = rop_node.parm("build_from_path").eval() + if not build_from_path: + cls.log.debug( + "Alembic ROP has 'Build from Path' disabled. " + "Validation is ignored.." + ) + return + + path_attr = rop_node.parm("path_attrib").eval() + if not path_attr: + cls.log.error( + "The Alembic ROP node has no Path Attribute" + "value set, but 'Build Hierarchy from Attribute'" + "is enabled." + ) + return [rop_node.path()] + + # Let's assume each attribute is explicitly named for now and has no + # wildcards for Primitive to Detail. This simplifies the check. + cls.log.debug("Checking Primitive to Detail pattern: %s" % pattern) + cls.log.debug("Checking with path attribute: %s" % path_attr) + + if not hasattr(output_node, "geometry"): + # In the case someone has explicitly set an Object + # node instead of a SOP node in Geometry context + # then for now we ignore - this allows us to also + # export object transforms. + cls.log.warning("No geometry output node found, skipping check..") + return + + # Check if the primitive attribute exists + frame = instance.data.get("frameStart", 0) + geo = output_node.geometryAtFrame(frame) + + # If there are no primitives on the start frame then it might be + # something that is emitted over time. As such we can't actually + # validate whether the attributes exist, because they won't exist + # yet. In that case, just warn the user and allow it. + if len(geo.iterPrims()) == 0: + cls.log.warning( + "No primitives found on current frame. Validation" + " for Primitive to Detail will be skipped." + ) + return + + attrib = geo.findPrimAttrib(path_attr) + if not attrib: + cls.log.info( + "Geometry Primitives are missing " + "path attribute: `%s`" % path_attr + ) + return [output_node.path()] + + # Ensure at least a single string value is present + if not attrib.strings(): + cls.log.info( + "Primitive path attribute has no " + "string values: %s" % path_attr + ) + return [output_node.path()] + + paths = None + for attr in pattern.split(" "): + if not attr.strip(): + # Ignore empty values + continue + + # Check if the primitive attribute exists + attrib = geo.findPrimAttrib(attr) + if not attrib: + # It is allowed to not have the attribute at all + continue + + # The issue can only happen if at least one string attribute is + # present. So we ignore cases with no values whatsoever. + if not attrib.strings(): + continue + + check = defaultdict(set) + values = geo.primStringAttribValues(attr) + if paths is None: + paths = geo.primStringAttribValues(path_attr) + + for path, value in zip(paths, values): + check[path].add(value) + + for path, values in check.items(): + # Whenever a single path has multiple values for the + # Primitive to Detail attribute then we consider it + # inconsistent and invalidate the ROP node's content. + if len(values) > 1: + cls.log.warning( + "Path has multiple values: %s (path: %s)" + % (list(values), path) + ) + return [output_node.path()] From 94ec68ab21182bbb01258a9e73ccb01b10a5a1e8 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 19 Jul 2023 00:13:51 +0300 Subject: [PATCH 02/25] update review validator --- .../publish/validate_review_colorspace.py | 153 ++++++------------ 1 file changed, 49 insertions(+), 104 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 18ca39234c..47c1e886d1 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -1,143 +1,88 @@ # -*- coding: utf-8 -*- import pyblish.api - -from collections import defaultdict from openpype.pipeline import PublishValidationError +from openpype.pipeline.publish import RepairAction +from openpype.hosts.houdini.api.action import SelectROPAction + + +class SetDefaultViewSpaceAction(RepairAction): + label = "Set default view space" + icon = "mdi.monitor" class ValidateReviewColorspace(pyblish.api.InstancePlugin): """Validate Review Colorspace parameters. - + It checks if 'OCIO Colorspace' parameter was set to valid value. """ order = pyblish.api.ValidatorOrder + 0.1 families = ["review"] hosts = ["houdini"] label = "Validate Review Colorspace" + actions = [SetDefaultViewSpaceAction, SelectROPAction] def process(self, instance): invalid = self.get_invalid(instance) if invalid: raise PublishValidationError( - ("Colorspace parameter is not valid."), + ("'OCIO Colorspace' parameter is not valid."), title=self.label ) @classmethod def get_invalid(cls, instance): import hou # noqa - output_node = instance.data.get("output_node") + rop_node = hou.node(instance.data["instance_node"]) - if output_node is None: - cls.log.error( - "SOP Output node in '%s' does not exist. " - "Ensure a valid SOP output path is set." % rop_node.path() - ) - - return [rop_node.path()] - - pattern = rop_node.parm("prim_to_detail_pattern").eval().strip() - if not pattern: - cls.log.debug( - "Alembic ROP has no 'Primitive to Detail' pattern. " - "Validation is ignored.." - ) - return - - build_from_path = rop_node.parm("build_from_path").eval() - if not build_from_path: - cls.log.debug( - "Alembic ROP has 'Build from Path' disabled. " - "Validation is ignored.." - ) - return - - path_attr = rop_node.parm("path_attrib").eval() - if not path_attr: - cls.log.error( - "The Alembic ROP node has no Path Attribute" - "value set, but 'Build Hierarchy from Attribute'" - "is enabled." - ) - return [rop_node.path()] - - # Let's assume each attribute is explicitly named for now and has no - # wildcards for Primitive to Detail. This simplifies the check. - cls.log.debug("Checking Primitive to Detail pattern: %s" % pattern) - cls.log.debug("Checking with path attribute: %s" % path_attr) - - if not hasattr(output_node, "geometry"): - # In the case someone has explicitly set an Object - # node instead of a SOP node in Geometry context - # then for now we ignore - this allows us to also - # export object transforms. - cls.log.warning("No geometry output node found, skipping check..") - return - - # Check if the primitive attribute exists - frame = instance.data.get("frameStart", 0) - geo = output_node.geometryAtFrame(frame) - - # If there are no primitives on the start frame then it might be - # something that is emitted over time. As such we can't actually - # validate whether the attributes exist, because they won't exist - # yet. In that case, just warn the user and allow it. - if len(geo.iterPrims()) == 0: + if hou.Color.ocio_defaultDisplay() == "default": cls.log.warning( - "No primitives found on current frame. Validation" - " for Primitive to Detail will be skipped." + "Default Houdini colorspace is used, " + " skipping check.." ) return - attrib = geo.findPrimAttrib(path_attr) - if not attrib: - cls.log.info( - "Geometry Primitives are missing " - "path attribute: `%s`" % path_attr + if rop_node.evalParm("colorcorrect") != 2: + # any colorspace settings other than default requires + # 'Color Correct' parm to be set to 'OpenColorIO' + rop_node.setParms({"colorcorrect": 2}) + cls.log.debug( + "'Color Correct' parm on '%s' has been set to" + " 'OpenColorIO'", rop_node ) - return [output_node.path()] - # Ensure at least a single string value is present - if not attrib.strings(): - cls.log.info( - "Primitive path attribute has no " - "string values: %s" % path_attr + if rop_node.evalParm("ociocolorspace") not in \ + hou.Color.ocio_spaces(): + + cls.log.error( + "'OCIO Colorspace' value on '%s' is not valid, " + "select a valid option from the dropdown menu.", + rop_node ) - return [output_node.path()] + return rop_node - paths = None - for attr in pattern.split(" "): - if not attr.strip(): - # Ignore empty values - continue + @classmethod + def repair(cls, instance): + """Set Default View Space Action. - # Check if the primitive attribute exists - attrib = geo.findPrimAttrib(attr) - if not attrib: - # It is allowed to not have the attribute at all - continue + It is a helper action more than a repair action, + used to set colorspace on opengl node to the default view. + """ - # The issue can only happen if at least one string attribute is - # present. So we ignore cases with no values whatsoever. - if not attrib.strings(): - continue + import hou + import PyOpenColorIO as OCIO - check = defaultdict(set) - values = geo.primStringAttribValues(attr) - if paths is None: - paths = geo.primStringAttribValues(path_attr) + rop_node = hou.node(instance.data["instance_node"]) - for path, value in zip(paths, values): - check[path].add(value) + config = OCIO.GetCurrentConfig() + display = hou.Color.ocio_defaultDisplay() + view = hou.Color.ocio_defaultView() - for path, values in check.items(): - # Whenever a single path has multiple values for the - # Primitive to Detail attribute then we consider it - # inconsistent and invalidate the ROP node's content. - if len(values) > 1: - cls.log.warning( - "Path has multiple values: %s (path: %s)" - % (list(values), path) - ) - return [output_node.path()] + default_view_space = config.getDisplayColorSpaceName( + display, view) + + rop_node.setParms({"ociocolorspace" : default_view_space}) + cls.log.debug( + "'OCIO Colorspace' parm on '%s' has been set to '%s'", + default_view_space, rop_node + ) From 4d79320cf4f1abdd05dc3ce6fc46d6ccb30b2aca Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 19 Jul 2023 00:50:43 +0300 Subject: [PATCH 03/25] make hound happy --- .../hosts/houdini/plugins/publish/validate_review_colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 47c1e886d1..02284dc641 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -81,7 +81,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): default_view_space = config.getDisplayColorSpaceName( display, view) - rop_node.setParms({"ociocolorspace" : default_view_space}) + rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( "'OCIO Colorspace' parm on '%s' has been set to '%s'", default_view_space, rop_node From f4a5858edbed465f11908d18697b5dc0c6414b76 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 19 Jul 2023 19:43:39 +0300 Subject: [PATCH 04/25] update validator --- .../houdini/plugins/publish/validate_review_colorspace.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 02284dc641..8f3799cde4 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -33,9 +33,10 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): import hou # noqa + import os rop_node = hou.node(instance.data["instance_node"]) - if hou.Color.ocio_defaultDisplay() == "default": + if os.getenv("OCIO") is None: cls.log.warning( "Default Houdini colorspace is used, " " skipping check.." @@ -78,8 +79,8 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): display = hou.Color.ocio_defaultDisplay() view = hou.Color.ocio_defaultView() - default_view_space = config.getDisplayColorSpaceName( - display, view) + default_view_space = config.getDisplayViewColorSpaceName( + display, view) # works with PyOpenColorIO 2.2.1 rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( From 00d4afd1178d4ee95ee8d09a4a8c8348f3948606 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 19 Jul 2023 19:44:45 +0300 Subject: [PATCH 05/25] make hound happy --- .../hosts/houdini/plugins/publish/validate_review_colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 8f3799cde4..addfa05bf1 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -80,7 +80,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): view = hou.Color.ocio_defaultView() default_view_space = config.getDisplayViewColorSpaceName( - display, view) # works with PyOpenColorIO 2.2.1 + display, view) # works with PyOpenColorIO 2.2.1 rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( From d90d45c56df70e876d02acbf9d4e09aa1b6f5746 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 20 Jul 2023 13:38:09 +0300 Subject: [PATCH 06/25] move get function to colorspace.py --- .../publish/validate_review_colorspace.py | 19 +++++--- openpype/pipeline/colorspace.py | 36 ++++++++++++++++ openpype/scripts/ocio_wrapper.py | 43 +++++++++++++++++++ 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index addfa05bf1..cfc5a5d71d 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -71,19 +71,24 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): """ import hou - import PyOpenColorIO as OCIO + from openpype.pipeline.colorspace import get_display_view_colorspace_name + from openpype.hosts.houdini.api.lib import get_color_management_preferences #noqa rop_node = hou.node(instance.data["instance_node"]) - config = OCIO.GetCurrentConfig() - display = hou.Color.ocio_defaultDisplay() - view = hou.Color.ocio_defaultView() + data = get_color_management_preferences() + config_path = data.get("config") + display = data.get("display") + view = data.get("view") - default_view_space = config.getDisplayViewColorSpaceName( - display, view) # works with PyOpenColorIO 2.2.1 + cls.log.debug("Get default view colorspace name..") + + default_view_space = get_display_view_colorspace_name(config_path, + display, view) rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( - "'OCIO Colorspace' parm on '%s' has been set to '%s'", + "'OCIO Colorspace' parm on '%s' has been set to " + "the default view color space '%s'", default_view_space, rop_node ) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 3f2d4891c1..a1d86b2fec 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -589,3 +589,39 @@ def _get_imageio_settings(project_settings, host_name): imageio_host = project_settings.get(host_name, {}).get("imageio", {}) return imageio_global, imageio_host + +def get_display_view_colorspace_name(config_path, display, view): + + if not compatibility_check(): + # python environment is not compatible with PyOpenColorIO + # needs to be run in subprocess + return get_display_view_colorspace_subprocess(config_path, + display, view) + + from openpype.scripts.ocio_wrapper import _get_display_view_colorspace_name #noqa + + return _get_display_view_colorspace_name(config_path, display, view) + +def get_display_view_colorspace_subprocess(config_path, display, view): + with _make_temp_json_file() as tmp_json_path: + # Prepare subprocess arguments + args = [ + "run", get_ocio_config_script_path(), + "config", "get_display_view_colorspace_name", + "--in_path", config_path, + "--out_path", tmp_json_path, + "--display", display, + "--view", view + + ] + log.info("Executing: {}".format(" ".join(args))) + + process_kwargs = { + "logger": log + } + + run_openpype_process(*args, **process_kwargs) + + # return all colorspaces + return_json_data = open(tmp_json_path).read() + return json.loads(return_json_data) diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index 16558642c6..ca703fd65c 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -173,6 +173,49 @@ def _get_views_data(config_path): return data +def _get_display_view_colorspace_name(config_path, display, view): + config_path = Path(config_path) + + if not config_path.is_file(): + raise IOError("Input path should be `config.ocio` file") + + config = ocio.Config().CreateFromFile(str(config_path)) + colorspace = config.getDisplayViewColorSpaceName(display, view) + + return colorspace + +@config.command( + name="get_display_view_colorspace_name", + help=( + "return default view colorspace name " + "for the given display and view " + "--path input arg is required" + ) +) +@click.option("--in_path", required=True, + help="path where to read ocio config file", + type=click.Path(exists=True)) +@click.option("--out_path", required=True, + help="path where to write output json file", + type=click.Path()) +@click.option("--display", required=True, + help="display", + type=click.STRING) +@click.option("--view", required=True, + help="view", + type=click.STRING) +def get_display_view_colorspace_name(in_path, out_path, + display, view): + + json_path = Path(out_path) + + out_data = _get_display_view_colorspace_name(in_path, + display, view) + + with open(json_path, "w") as f: + json.dump(out_data, f) + + print(f"Viewer data are saved to '{json_path}'") if __name__ == '__main__': main() From 2bb11d956ca2ec629f61d5d14e0b2ef4130a0363 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 20 Jul 2023 13:54:46 +0300 Subject: [PATCH 07/25] add doc strings --- .../publish/validate_review_colorspace.py | 2 +- openpype/pipeline/colorspace.py | 22 ++++++++++++ openpype/scripts/ocio_wrapper.py | 34 +++++++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index cfc5a5d71d..67e29e0ee2 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -71,7 +71,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): """ import hou - from openpype.pipeline.colorspace import get_display_view_colorspace_name + from openpype.pipeline.colorspace import get_display_view_colorspace_name #noqa from openpype.hosts.houdini.api.lib import get_color_management_preferences #noqa rop_node = hou.node(instance.data["instance_node"]) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index a1d86b2fec..22e8175a7e 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -591,6 +591,16 @@ def _get_imageio_settings(project_settings, host_name): return imageio_global, imageio_host def get_display_view_colorspace_name(config_path, display, view): + """get view colorspace name for the given display and view. + + Args: + config_path (str): path string leading to config.ocio + display (str): display name e.g. "ACES" + view (str): view name e.g. "sRGB" + + Returns: + view color space name (str) e.g. "Output - sRGB" + """ if not compatibility_check(): # python environment is not compatible with PyOpenColorIO @@ -603,6 +613,18 @@ def get_display_view_colorspace_name(config_path, display, view): return _get_display_view_colorspace_name(config_path, display, view) def get_display_view_colorspace_subprocess(config_path, display, view): + """get view colorspace name for the given display and view + via subprocess. + + Args: + config_path (str): path string leading to config.ocio + display (str): display name e.g. "ACES" + view (str): view name e.g. "sRGB" + + Returns: + view color space name (str) e.g. "Output - sRGB" + """ + with _make_temp_json_file() as tmp_json_path: # Prepare subprocess arguments args = [ diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index ca703fd65c..f94faabe11 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -174,6 +174,21 @@ def _get_views_data(config_path): return data def _get_display_view_colorspace_name(config_path, display, view): + """get view colorspace name for the given display and view. + + Args: + config_path (str): path string leading to config.ocio + display (str): display name e.g. "ACES" + view (str): view name e.g. "sRGB" + + + Raises: + IOError: Input config does not exist. + + Returns: + view color space name (str) e.g. "Output - sRGB" + """ + config_path = Path(config_path) if not config_path.is_file(): @@ -199,13 +214,28 @@ def _get_display_view_colorspace_name(config_path, display, view): help="path where to write output json file", type=click.Path()) @click.option("--display", required=True, - help="display", + help="display name", type=click.STRING) @click.option("--view", required=True, - help="view", + help="view name", type=click.STRING) def get_display_view_colorspace_name(in_path, out_path, display, view): + """Aggregate view colorspace name to file. + + Python 2 wrapped console command + + Args: + in_path (str): config file path string + out_path (str): temp json file path string + display (str): display name e.g. "ACES" + view (str): view name e.g. "sRGB" + + Example of use: + > pyton.exe ./ocio_wrapper.py config \ + get_display_view_colorspace_name --in_path= \ + --out_path= --display= --view= + """ json_path = Path(out_path) From c8e66fd632323416a63c0c9d1bf248e516f2c2be Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 9 Aug 2023 20:34:05 +0300 Subject: [PATCH 08/25] resolve some conversations --- .../publish/validate_review_colorspace.py | 16 ++++++++-------- openpype/pipeline/colorspace.py | 4 +++- openpype/scripts/ocio_wrapper.py | 4 +++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 67e29e0ee2..e493349946 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -4,6 +4,9 @@ from openpype.pipeline import PublishValidationError from openpype.pipeline.publish import RepairAction from openpype.hosts.houdini.api.action import SelectROPAction +import os +import hou + class SetDefaultViewSpaceAction(RepairAction): label = "Set default view space" @@ -32,8 +35,6 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): - import hou # noqa - import os rop_node = hou.node(instance.data["instance_node"]) if os.getenv("OCIO") is None: @@ -70,16 +71,15 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): used to set colorspace on opengl node to the default view. """ - import hou - from openpype.pipeline.colorspace import get_display_view_colorspace_name #noqa - from openpype.hosts.houdini.api.lib import get_color_management_preferences #noqa + from openpype.pipeline.colorspace import get_display_view_colorspace_name # noqa + from openpype.hosts.houdini.api.lib import get_color_management_preferences # noqa rop_node = hou.node(instance.data["instance_node"]) - data = get_color_management_preferences() + data = get_color_management_preferences() config_path = data.get("config") - display = data.get("display") - view = data.get("view") + display = data.get("display") + view = data.get("view") cls.log.debug("Get default view colorspace name..") diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 22e8175a7e..d84424270c 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -590,6 +590,7 @@ def _get_imageio_settings(project_settings, host_name): return imageio_global, imageio_host + def get_display_view_colorspace_name(config_path, display, view): """get view colorspace name for the given display and view. @@ -608,10 +609,11 @@ def get_display_view_colorspace_name(config_path, display, view): return get_display_view_colorspace_subprocess(config_path, display, view) - from openpype.scripts.ocio_wrapper import _get_display_view_colorspace_name #noqa + from openpype.scripts.ocio_wrapper import _get_display_view_colorspace_name # noqa return _get_display_view_colorspace_name(config_path, display, view) + def get_display_view_colorspace_subprocess(config_path, display, view): """get view colorspace name for the given display and view via subprocess. diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index f94faabe11..556568ce20 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -173,6 +173,7 @@ def _get_views_data(config_path): return data + def _get_display_view_colorspace_name(config_path, display, view): """get view colorspace name for the given display and view. @@ -199,6 +200,7 @@ def _get_display_view_colorspace_name(config_path, display, view): return colorspace + @config.command( name="get_display_view_colorspace_name", help=( @@ -223,7 +225,7 @@ def get_display_view_colorspace_name(in_path, out_path, display, view): """Aggregate view colorspace name to file. - Python 2 wrapped console command + Wrapper command for processes without acces to OpenColorIO Args: in_path (str): config file path string From 877facc5b89317a0fc541d2f06a9d9611c9e1acb Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 9 Aug 2023 21:56:42 +0300 Subject: [PATCH 09/25] set default colorspace on creation if there's OCIO --- .../houdini/plugins/create/create_review.py | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index ab06b30c35..797116aaca 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -3,6 +3,9 @@ from openpype.hosts.houdini.api import plugin from openpype.lib import EnumDef, BoolDef, NumberDef +import os +import hou + class CreateReview(plugin.HoudiniCreator): """Review with OpenGL ROP""" @@ -13,7 +16,6 @@ class CreateReview(plugin.HoudiniCreator): icon = "video-camera" def create(self, subset_name, instance_data, pre_create_data): - import hou instance_data.pop("active", None) instance_data.update({"node_type": "opengl"}) @@ -82,6 +84,10 @@ class CreateReview(plugin.HoudiniCreator): instance_node.setParms(parms) + # Set OCIO Colorspace to the default output colorspace + # if there's OCIO + self.set_colorcorrect_to_default_view_space(instance_node) + to_lock = ["id", "family"] self.lock_parameters(instance_node, to_lock) @@ -123,3 +129,46 @@ class CreateReview(plugin.HoudiniCreator): minimum=0.0001, decimals=3) ] + + def set_colorcorrect_to_default_view_space(self, + instance_node): + """Set ociocolorspace to the default output space.""" + + if os.getenv("OCIO") is None: + # No OCIO, skip setting ociocolorspace + return + + # if there's OCIO then set Color Correction parameter + # to OpenColorIO + instance_node.setParms({"colorcorrect": 2}) + + self.log.debug("Get default view colorspace name..") + + default_view_space = self.get_default_view_space() + instance_node.setParms( + {"ociocolorspace": default_view_space} + ) + + self.log.debug( + "'OCIO Colorspace' parm on '{}' has been set to " + "the default view color space '{}'" + .format(instance_node, default_view_space) + ) + + return default_view_space + + def get_default_view_space(self): + """Get default view space for ociocolorspace parm.""" + + from openpype.pipeline.colorspace import get_display_view_colorspace_name # noqa + from openpype.hosts.houdini.api.lib import get_color_management_preferences # noqa + + data = get_color_management_preferences() + config_path = data.get("config") + display = data.get("display") + view = data.get("view") + + default_view_space = get_display_view_colorspace_name(config_path, + display, view) + + return default_view_space From cff92425676acef62fc6b8489517e66286072925 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 9 Aug 2023 21:57:57 +0300 Subject: [PATCH 10/25] use .format instead of %s --- .../publish/validate_review_colorspace.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index e493349946..5390b6b52f 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -49,17 +49,17 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): # 'Color Correct' parm to be set to 'OpenColorIO' rop_node.setParms({"colorcorrect": 2}) cls.log.debug( - "'Color Correct' parm on '%s' has been set to" - " 'OpenColorIO'", rop_node + "'Color Correct' parm on '{}' has been set to" + " 'OpenColorIO'".format(rop_node) ) if rop_node.evalParm("ociocolorspace") not in \ hou.Color.ocio_spaces(): cls.log.error( - "'OCIO Colorspace' value on '%s' is not valid, " - "select a valid option from the dropdown menu.", - rop_node + "'OCIO Colorspace' value on '{}' is not valid, " + "select a valid option from the dropdown menu." + .format(rop_node) ) return rop_node @@ -88,7 +88,8 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( - "'OCIO Colorspace' parm on '%s' has been set to " - "the default view color space '%s'", - default_view_space, rop_node + "'OCIO Colorspace' parm on '{}' has been set to " + "the default view color space '{}'" + .formate(rop_node, default_view_space) + ) From 256ffee407e8718ca6099c5f7185d0ec88a0ace7 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Mon, 14 Aug 2023 15:54:14 +0300 Subject: [PATCH 11/25] resolve some conversations --- openpype/pipeline/colorspace.py | 2 +- openpype/scripts/ocio_wrapper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 392089237b..a0efb5e18c 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -604,7 +604,7 @@ def _get_imageio_settings(project_settings, host_name): def get_display_view_colorspace_name(config_path, display, view): - """get view colorspace name for the given display and view. + """Return colorspace name for the given display and view. Args: config_path (str): path string leading to config.ocio diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index 556568ce20..e491206ebb 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -247,7 +247,7 @@ def get_display_view_colorspace_name(in_path, out_path, with open(json_path, "w") as f: json.dump(out_data, f) - print(f"Viewer data are saved to '{json_path}'") + print(f"Display view colorspace saved to '{json_path}'") if __name__ == '__main__': main() From 9ff5c071b3f7e0cc1bf7f002719565d192030e3a Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Tue, 29 Aug 2023 21:05:43 +0300 Subject: [PATCH 12/25] resolve conversations --- openpype/hosts/houdini/api/colorspace.py | 18 +++++++++++++- .../houdini/plugins/create/create_review.py | 24 +++---------------- .../publish/validate_review_colorspace.py | 19 ++++----------- openpype/pipeline/colorspace.py | 6 ++--- 4 files changed, 28 insertions(+), 39 deletions(-) diff --git a/openpype/hosts/houdini/api/colorspace.py b/openpype/hosts/houdini/api/colorspace.py index 7047644225..5c3c605cd1 100644 --- a/openpype/hosts/houdini/api/colorspace.py +++ b/openpype/hosts/houdini/api/colorspace.py @@ -1,7 +1,7 @@ import attr import hou from openpype.hosts.houdini.api.lib import get_color_management_preferences - +from openpype.pipeline.colorspace import get_display_view_colorspace_name @attr.s class LayerMetadata(object): @@ -54,3 +54,19 @@ class ARenderProduct(object): ) ] return colorspace_data + + +def get_default_display_view_colorspace(): + """Get default display view colorspace. + + It's used for 'ociocolorspace' parm in OpneGL Node.""" + + data = get_color_management_preferences() + config_path = data.get("config") + display = data.get("display") + view = data.get("view") + + default_view_space = get_display_view_colorspace_name(config_path, + display, + view) + return default_view_space diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 797116aaca..75a92e5e77 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -2,6 +2,7 @@ """Creator plugin for creating openGL reviews.""" from openpype.hosts.houdini.api import plugin from openpype.lib import EnumDef, BoolDef, NumberDef +from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace import os import hou @@ -142,9 +143,8 @@ class CreateReview(plugin.HoudiniCreator): # to OpenColorIO instance_node.setParms({"colorcorrect": 2}) - self.log.debug("Get default view colorspace name..") - - default_view_space = self.get_default_view_space() + # Get default view space for ociocolorspace parm. + default_view_space = get_default_display_view_colorspace() instance_node.setParms( {"ociocolorspace": default_view_space} ) @@ -154,21 +154,3 @@ class CreateReview(plugin.HoudiniCreator): "the default view color space '{}'" .format(instance_node, default_view_space) ) - - return default_view_space - - def get_default_view_space(self): - """Get default view space for ociocolorspace parm.""" - - from openpype.pipeline.colorspace import get_display_view_colorspace_name # noqa - from openpype.hosts.houdini.api.lib import get_color_management_preferences # noqa - - data = get_color_management_preferences() - config_path = data.get("config") - display = data.get("display") - view = data.get("view") - - default_view_space = get_display_view_colorspace_name(config_path, - display, view) - - return default_view_space diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 5390b6b52f..09e4a489d2 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -3,6 +3,7 @@ import pyblish.api from openpype.pipeline import PublishValidationError from openpype.pipeline.publish import RepairAction from openpype.hosts.houdini.api.action import SelectROPAction +from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace import os import hou @@ -38,7 +39,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): rop_node = hou.node(instance.data["instance_node"]) if os.getenv("OCIO") is None: - cls.log.warning( + cls.log.debug( "Default Houdini colorspace is used, " " skipping check.." ) @@ -71,25 +72,15 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): used to set colorspace on opengl node to the default view. """ - from openpype.pipeline.colorspace import get_display_view_colorspace_name # noqa - from openpype.hosts.houdini.api.lib import get_color_management_preferences # noqa - rop_node = hou.node(instance.data["instance_node"]) - data = get_color_management_preferences() - config_path = data.get("config") - display = data.get("display") - view = data.get("view") - - cls.log.debug("Get default view colorspace name..") - - default_view_space = get_display_view_colorspace_name(config_path, - display, view) + # Get default view colorspace name + default_view_space = get_default_display_view_colorspace() rop_node.setParms({"ociocolorspace": default_view_space}) cls.log.debug( "'OCIO Colorspace' parm on '{}' has been set to " "the default view color space '{}'" - .formate(rop_node, default_view_space) + .format(rop_node, default_view_space) ) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index a0efb5e18c..37974f4a0b 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -658,6 +658,6 @@ def get_display_view_colorspace_subprocess(config_path, display, view): run_openpype_process(*args, **process_kwargs) - # return all colorspaces - return_json_data = open(tmp_json_path).read() - return json.loads(return_json_data) + # return default view colorspace name + with open(tmp_json_path, "r") as f: + return json.load(f) From c799ae42eab8be32051ee373bdb71176002a20b8 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Tue, 29 Aug 2023 21:06:36 +0300 Subject: [PATCH 13/25] add spaces --- openpype/hosts/houdini/api/colorspace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/api/colorspace.py b/openpype/hosts/houdini/api/colorspace.py index 5c3c605cd1..2662a968e2 100644 --- a/openpype/hosts/houdini/api/colorspace.py +++ b/openpype/hosts/houdini/api/colorspace.py @@ -67,6 +67,6 @@ def get_default_display_view_colorspace(): view = data.get("view") default_view_space = get_display_view_colorspace_name(config_path, - display, - view) + display, + view) return default_view_space From 75673151a6374591067c5e8f356ee3bb93706961 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Tue, 29 Aug 2023 21:18:27 +0300 Subject: [PATCH 14/25] resolve hound conversations --- openpype/hosts/houdini/plugins/create/create_review.py | 2 +- .../hosts/houdini/plugins/publish/validate_review_colorspace.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index 75a92e5e77..c087c54f6c 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -2,7 +2,7 @@ """Creator plugin for creating openGL reviews.""" from openpype.hosts.houdini.api import plugin from openpype.lib import EnumDef, BoolDef, NumberDef -from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace +from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa import os import hou diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 09e4a489d2..2c7420bf48 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -3,7 +3,7 @@ import pyblish.api from openpype.pipeline import PublishValidationError from openpype.pipeline.publish import RepairAction from openpype.hosts.houdini.api.action import SelectROPAction -from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace +from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa import os import hou From 668bcb2d40d5708fc40c1e1a8465e36c94ffdef8 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 30 Aug 2023 22:28:43 +0300 Subject: [PATCH 15/25] BigRoy's Comments --- openpype/hosts/houdini/api/colorspace.py | 19 +++++++------------ openpype/pipeline/colorspace.py | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/houdini/api/colorspace.py b/openpype/hosts/houdini/api/colorspace.py index 2662a968e2..fb0a724eb9 100644 --- a/openpype/hosts/houdini/api/colorspace.py +++ b/openpype/hosts/houdini/api/colorspace.py @@ -57,16 +57,11 @@ class ARenderProduct(object): def get_default_display_view_colorspace(): - """Get default display view colorspace. + """Get default display view colorspace name. """ - It's used for 'ociocolorspace' parm in OpneGL Node.""" - - data = get_color_management_preferences() - config_path = data.get("config") - display = data.get("display") - view = data.get("view") - - default_view_space = get_display_view_colorspace_name(config_path, - display, - view) - return default_view_space + prefs = get_color_management_preferences() + return get_display_view_colorspace_name( + config_path=prefs["config"], + display=prefs["display"], + view=prefs["view"] + ) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 37974f4a0b..3bb258e8f2 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -650,7 +650,7 @@ def get_display_view_colorspace_subprocess(config_path, display, view): "--view", view ] - log.info("Executing: {}".format(" ".join(args))) + log.debug("Executing: {}".format(" ".join(args))) process_kwargs = { "logger": log From 41babcaa85880b957a6409bf29d02da2291f91d2 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 30 Aug 2023 22:43:52 +0300 Subject: [PATCH 16/25] update doc strings --- openpype/hosts/houdini/api/colorspace.py | 4 +++- openpype/pipeline/colorspace.py | 4 ++-- openpype/scripts/ocio_wrapper.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/houdini/api/colorspace.py b/openpype/hosts/houdini/api/colorspace.py index fb0a724eb9..b1a4d5dcd5 100644 --- a/openpype/hosts/houdini/api/colorspace.py +++ b/openpype/hosts/houdini/api/colorspace.py @@ -57,7 +57,9 @@ class ARenderProduct(object): def get_default_display_view_colorspace(): - """Get default display view colorspace name. """ + """Returns the colorspace attribute of the default (display, view) pair. + + """ prefs = get_color_management_preferences() return get_display_view_colorspace_name( diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 3bb258e8f2..3dd33d0425 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -604,7 +604,7 @@ def _get_imageio_settings(project_settings, host_name): def get_display_view_colorspace_name(config_path, display, view): - """Return colorspace name for the given display and view. + """Returns the colorspace attribute of the (display, view) pair. Args: config_path (str): path string leading to config.ocio @@ -627,7 +627,7 @@ def get_display_view_colorspace_name(config_path, display, view): def get_display_view_colorspace_subprocess(config_path, display, view): - """get view colorspace name for the given display and view + """Returns the colorspace attribute of the (display, view) pair via subprocess. Args: diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index e491206ebb..cae6e6975b 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -175,7 +175,7 @@ def _get_views_data(config_path): def _get_display_view_colorspace_name(config_path, display, view): - """get view colorspace name for the given display and view. + """Returns the colorspace attribute of the (display, view) pair. Args: config_path (str): path string leading to config.ocio From 6c5039f7075ce59b2911a680d41ffae5a59dca09 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 30 Aug 2023 22:46:07 +0300 Subject: [PATCH 17/25] BigRoy's Comment --- openpype/hosts/houdini/api/colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/api/colorspace.py b/openpype/hosts/houdini/api/colorspace.py index b1a4d5dcd5..cc40b9df1c 100644 --- a/openpype/hosts/houdini/api/colorspace.py +++ b/openpype/hosts/houdini/api/colorspace.py @@ -59,7 +59,7 @@ class ARenderProduct(object): def get_default_display_view_colorspace(): """Returns the colorspace attribute of the default (display, view) pair. - """ + It's used for 'ociocolorspace' parm in OpenGL Node.""" prefs = get_color_management_preferences() return get_display_view_colorspace_name( From 1a3c8ad77252ffa9217c6af98ba27dcdd56c366a Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 31 Aug 2023 17:34:42 +0300 Subject: [PATCH 18/25] make validateReviewColorspace optional --- .../plugins/publish/validate_review_colorspace.py | 10 ++++++++-- .../defaults/project_settings/houdini.json | 5 +++++ .../schemas/schema_houdini_publish.json | 6 +++++- .../houdini/server/settings/publish_plugins.py | 14 +++++++++++--- server_addon/houdini/server/version.py | 2 +- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 2c7420bf48..f680f62142 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- import pyblish.api -from openpype.pipeline import PublishValidationError +from openpype.pipeline import ( + PublishValidationError, + OptionalPyblishPluginMixin +) from openpype.pipeline.publish import RepairAction from openpype.hosts.houdini.api.action import SelectROPAction from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa @@ -14,7 +17,8 @@ class SetDefaultViewSpaceAction(RepairAction): icon = "mdi.monitor" -class ValidateReviewColorspace(pyblish.api.InstancePlugin): +class ValidateReviewColorspace(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): """Validate Review Colorspace parameters. It checks if 'OCIO Colorspace' parameter was set to valid value. @@ -26,6 +30,8 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin): label = "Validate Review Colorspace" actions = [SetDefaultViewSpaceAction, SelectROPAction] + optional = True + def process(self, instance): invalid = self.get_invalid(instance) if invalid: diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index 9d047c28bd..93d5c50d5e 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -93,6 +93,11 @@ "$JOB" ] }, + "ValidateReviewColorspace": { + "enabled": true, + "optional": true, + "active": true + }, "ValidateContainers": { "enabled": true, "optional": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json index aa6eaf5164..b57089007e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json @@ -40,6 +40,10 @@ "type": "schema_template", "name": "template_publish_plugin", "template_data": [ + { + "key": "ValidateReviewColorspace", + "label": "Validate Review Colorspace" + }, { "key": "ValidateContainers", "label": "ValidateContainers" @@ -47,4 +51,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/server_addon/houdini/server/settings/publish_plugins.py b/server_addon/houdini/server/settings/publish_plugins.py index 7d35d7e634..4534d8d0d9 100644 --- a/server_addon/houdini/server/settings/publish_plugins.py +++ b/server_addon/houdini/server/settings/publish_plugins.py @@ -120,7 +120,7 @@ class ValidateWorkfilePathsModel(BaseSettingsModel): ) -class ValidateContainersModel(BaseSettingsModel): +class BasicValidateModel(BaseSettingsModel): enabled: bool = Field(title="Enabled") optional: bool = Field(title="Optional") active: bool = Field(title="Active") @@ -130,8 +130,11 @@ class PublishPluginsModel(BaseSettingsModel): ValidateWorkfilePaths: ValidateWorkfilePathsModel = Field( default_factory=ValidateWorkfilePathsModel, title="Validate workfile paths settings.") - ValidateContainers: ValidateContainersModel = Field( - default_factory=ValidateContainersModel, + ValidateReviewColorspace: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Validate Review Colorspace.") + ValidateContainers: BasicValidateModel = Field( + default_factory=BasicValidateModel, title="Validate Latest Containers.") @@ -148,6 +151,11 @@ DEFAULT_HOUDINI_PUBLISH_SETTINGS = { "$JOB" ] }, + "ValidateReviewColorspace": { + "enabled": True, + "optional": True, + "active": True + }, "ValidateContainers": { "enabled": True, "optional": True, diff --git a/server_addon/houdini/server/version.py b/server_addon/houdini/server/version.py index 485f44ac21..b3f4756216 100644 --- a/server_addon/houdini/server/version.py +++ b/server_addon/houdini/server/version.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.1.2" From 1a936c155985e804f0ddc01e14a4573c56bbb8e7 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 31 Aug 2023 22:42:13 +0300 Subject: [PATCH 19/25] BigRoy's comments --- .../houdini/plugins/publish/validate_review_colorspace.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index f680f62142..3f5e5bc354 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -13,7 +13,7 @@ import hou class SetDefaultViewSpaceAction(RepairAction): - label = "Set default view space" + label = "Set default view colorspace" icon = "mdi.monitor" @@ -33,6 +33,10 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, optional = True def process(self, instance): + + if not self.is_active(instance.data): + return + invalid = self.get_invalid(instance) if invalid: raise PublishValidationError( From 869c6277ff1d89599086169926dfb48673c088c0 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Fri, 1 Sep 2023 21:03:09 +0300 Subject: [PATCH 20/25] BigRoy's comment --- .../publish/validate_review_colorspace.py | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 3f5e5bc354..e5d4756556 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -37,15 +37,15 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, if not self.is_active(instance.data): return - invalid = self.get_invalid(instance) - if invalid: + invalid_nodes, message = self.get_invalid_with_message(instance) + if invalid_nodes: raise PublishValidationError( - ("'OCIO Colorspace' parameter is not valid."), + message, title=self.label ) @classmethod - def get_invalid(cls, instance): + def get_invalid_with_message(cls, instance): rop_node = hou.node(instance.data["instance_node"]) if os.getenv("OCIO") is None: @@ -53,26 +53,31 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, "Default Houdini colorspace is used, " " skipping check.." ) - return + return None, None if rop_node.evalParm("colorcorrect") != 2: # any colorspace settings other than default requires # 'Color Correct' parm to be set to 'OpenColorIO' - rop_node.setParms({"colorcorrect": 2}) - cls.log.debug( - "'Color Correct' parm on '{}' has been set to" - " 'OpenColorIO'".format(rop_node) + error = ( + "'Color Correction' parm on '{}' ROP must be set to" + " 'OpenColorIO'".format(rop_node.path()) ) + return rop_node , error if rop_node.evalParm("ociocolorspace") not in \ hou.Color.ocio_spaces(): - cls.log.error( - "'OCIO Colorspace' value on '{}' is not valid, " - "select a valid option from the dropdown menu." - .format(rop_node) + error = ( + "Invalid value: Colorspace name doesn't exist.\n" + "Check 'OCIO Colorspace' parameter on '{}' ROP" + .format(rop_node.path()) ) - return rop_node + return rop_node, error + + @classmethod + def get_invalid(cls, instance): + nodes, _ = cls.get_invalid_with_message(instance) + return nodes @classmethod def repair(cls, instance): @@ -84,6 +89,13 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, rop_node = hou.node(instance.data["instance_node"]) + if rop_node.evalParm("colorcorrect") != 2: + rop_node.setParms({"colorcorrect": 2}) + cls.log.debug( + "'Color Correction' parm on '{}' has been set to" + " 'OpenColorIO'".format(rop_node.path()) + ) + # Get default view colorspace name default_view_space = get_default_display_view_colorspace() From 087aca6d8b9377c054e623bc2f12f6b418a69aa0 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Fri, 1 Sep 2023 21:04:59 +0300 Subject: [PATCH 21/25] resolve hound --- .../hosts/houdini/plugins/publish/validate_review_colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index e5d4756556..47370678d0 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -62,7 +62,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, "'Color Correction' parm on '{}' ROP must be set to" " 'OpenColorIO'".format(rop_node.path()) ) - return rop_node , error + return rop_node, error if rop_node.evalParm("ociocolorspace") not in \ hou.Color.ocio_spaces(): From c2b948d35fea1f0cf2f7146bb0085fc3bd2dfeef Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Mon, 4 Sep 2023 11:09:47 +0300 Subject: [PATCH 22/25] BigRoy's comments --- .../publish/validate_review_colorspace.py | 27 ++++--------------- openpype/pipeline/colorspace.py | 7 +---- openpype/scripts/ocio_wrapper.py | 11 ++++---- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 47370678d0..d457a295c5 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -37,47 +37,30 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, if not self.is_active(instance.data): return - invalid_nodes, message = self.get_invalid_with_message(instance) - if invalid_nodes: - raise PublishValidationError( - message, - title=self.label - ) - - @classmethod - def get_invalid_with_message(cls, instance): - - rop_node = hou.node(instance.data["instance_node"]) if os.getenv("OCIO") is None: - cls.log.debug( + self.log.debug( "Default Houdini colorspace is used, " " skipping check.." ) - return None, None + return + rop_node = hou.node(instance.data["instance_node"]) if rop_node.evalParm("colorcorrect") != 2: # any colorspace settings other than default requires # 'Color Correct' parm to be set to 'OpenColorIO' - error = ( + raise PublishValidationError( "'Color Correction' parm on '{}' ROP must be set to" " 'OpenColorIO'".format(rop_node.path()) ) - return rop_node, error if rop_node.evalParm("ociocolorspace") not in \ hou.Color.ocio_spaces(): - error = ( + raise PublishValidationError( "Invalid value: Colorspace name doesn't exist.\n" "Check 'OCIO Colorspace' parameter on '{}' ROP" .format(rop_node.path()) ) - return rop_node, error - - @classmethod - def get_invalid(cls, instance): - nodes, _ = cls.get_invalid_with_message(instance) - return nodes @classmethod def repair(cls, instance): diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 3dd33d0425..e167e18cfb 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -648,15 +648,10 @@ def get_display_view_colorspace_subprocess(config_path, display, view): "--out_path", tmp_json_path, "--display", display, "--view", view - ] log.debug("Executing: {}".format(" ".join(args))) - process_kwargs = { - "logger": log - } - - run_openpype_process(*args, **process_kwargs) + run_openpype_process(*args, logger=log) # return default view colorspace name with open(tmp_json_path, "r") as f: diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index cae6e6975b..2c11bb7eeb 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -225,7 +225,7 @@ def get_display_view_colorspace_name(in_path, out_path, display, view): """Aggregate view colorspace name to file. - Wrapper command for processes without acces to OpenColorIO + Wrapper command for processes without access to OpenColorIO Args: in_path (str): config file path string @@ -239,15 +239,14 @@ def get_display_view_colorspace_name(in_path, out_path, --out_path= --display= --view= """ - json_path = Path(out_path) - out_data = _get_display_view_colorspace_name(in_path, - display, view) + display, + view) - with open(json_path, "w") as f: + with open(out_path, "w") as f: json.dump(out_data, f) - print(f"Display view colorspace saved to '{json_path}'") + print(f"Display view colorspace saved to '{out_path}'") if __name__ == '__main__': main() From 4ed278c0c885e22fdcf97c9a1b242428fee3ff05 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Mon, 4 Sep 2023 12:18:03 +0300 Subject: [PATCH 23/25] BigRoy's comment --- .../houdini/plugins/publish/validate_review_colorspace.py | 3 +-- openpype/scripts/ocio_wrapper.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index d457a295c5..545d7b16b1 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -83,9 +83,8 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, default_view_space = get_default_display_view_colorspace() rop_node.setParms({"ociocolorspace": default_view_space}) - cls.log.debug( + cls.log.info( "'OCIO Colorspace' parm on '{}' has been set to " "the default view color space '{}'" .format(rop_node, default_view_space) - ) diff --git a/openpype/scripts/ocio_wrapper.py b/openpype/scripts/ocio_wrapper.py index 2c11bb7eeb..40553d30f2 100644 --- a/openpype/scripts/ocio_wrapper.py +++ b/openpype/scripts/ocio_wrapper.py @@ -195,7 +195,7 @@ def _get_display_view_colorspace_name(config_path, display, view): if not config_path.is_file(): raise IOError("Input path should be `config.ocio` file") - config = ocio.Config().CreateFromFile(str(config_path)) + config = ocio.Config.CreateFromFile(str(config_path)) colorspace = config.getDisplayViewColorSpaceName(display, view) return colorspace From 2fdaadcdc151918163477f3275b646a7044f43e6 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Mon, 4 Sep 2023 19:50:00 +0300 Subject: [PATCH 24/25] Minikiu comment --- .../hosts/houdini/plugins/publish/validate_review_colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 545d7b16b1..61c3a755d0 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -39,7 +39,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, if os.getenv("OCIO") is None: self.log.debug( - "Default Houdini colorspace is used, " + "Using Houdini's Default Color Management, " " skipping check.." ) return From 2919d241da617229efa47c9ae52854633e0100c4 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 7 Sep 2023 19:30:10 +0300 Subject: [PATCH 25/25] move import inside --- .../hosts/houdini/plugins/create/create_review.py | 12 ++++-------- .../plugins/publish/validate_review_colorspace.py | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index c087c54f6c..60c34a358b 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -2,7 +2,6 @@ """Creator plugin for creating openGL reviews.""" from openpype.hosts.houdini.api import plugin from openpype.lib import EnumDef, BoolDef, NumberDef -from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa import os import hou @@ -87,7 +86,8 @@ class CreateReview(plugin.HoudiniCreator): # Set OCIO Colorspace to the default output colorspace # if there's OCIO - self.set_colorcorrect_to_default_view_space(instance_node) + if os.getenv("OCIO"): + self.set_colorcorrect_to_default_view_space(instance_node) to_lock = ["id", "family"] @@ -134,13 +134,9 @@ class CreateReview(plugin.HoudiniCreator): def set_colorcorrect_to_default_view_space(self, instance_node): """Set ociocolorspace to the default output space.""" + from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa - if os.getenv("OCIO") is None: - # No OCIO, skip setting ociocolorspace - return - - # if there's OCIO then set Color Correction parameter - # to OpenColorIO + # set Color Correction parameter to OpenColorIO instance_node.setParms({"colorcorrect": 2}) # Get default view space for ociocolorspace parm. diff --git a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py index 61c3a755d0..03ecd1b052 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py +++ b/openpype/hosts/houdini/plugins/publish/validate_review_colorspace.py @@ -6,7 +6,6 @@ from openpype.pipeline import ( ) from openpype.pipeline.publish import RepairAction from openpype.hosts.houdini.api.action import SelectROPAction -from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa import os import hou @@ -69,6 +68,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin, It is a helper action more than a repair action, used to set colorspace on opengl node to the default view. """ + from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa rop_node = hou.node(instance.data["instance_node"])