From 7d21437dae8c552c0f8f278d71498bcdb02f5fd0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 30 Mar 2023 21:19:24 +0800 Subject: [PATCH] add settings and adjustments based on the new publishers --- .../houdini/plugins/create/create_review.py | 145 ++++++++++++++---- .../plugins/publish/collect_review_data.py | 18 +-- .../houdini/plugins/publish/extract_opengl.py | 55 +++---- .../plugins/publish/validate_scene_review.py | 50 ++++++ 4 files changed, 202 insertions(+), 66 deletions(-) create mode 100644 openpype/hosts/houdini/plugins/publish/validate_scene_review.py diff --git a/openpype/hosts/houdini/plugins/create/create_review.py b/openpype/hosts/houdini/plugins/create/create_review.py index a1bcfc23ed..32b187e511 100644 --- a/openpype/hosts/houdini/plugins/create/create_review.py +++ b/openpype/hosts/houdini/plugins/create/create_review.py @@ -1,11 +1,11 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating pointcache alembics.""" from openpype.hosts.houdini.api import plugin -from openpype.pipeline import ( - CreatedInstance, - OpenPypePyblishPluginMixin -) +from openpype.pipeline import CreatedInstance +from openpype.lib import EnumDef, BoolDef, NumberDef -class CreateReview(plugin.HoudiniCreator, OpenPypePyblishPluginMixin): +class CreateReview(plugin.HoudiniCreator): """Review with OpenGL ROP""" identifier = "io.openpype.creators.houdini.review" @@ -13,34 +13,30 @@ class CreateReview(plugin.HoudiniCreator, OpenPypePyblishPluginMixin): family = "review" icon = "video-camera" - # Default settings for the ROP - # todo: expose in OpenPype settings? - override_resolution = True - width = 1280 - height = 720 - aspect = 1.0 - - def create(self, subset_name, instance_data, pre_create_data): - + def create(self, subset_name, instance_data, pre_create_data): # type: CreatedInstance import hou - # Remove the active, we are checking the bypass flag of the nodes instance_data.pop("active", None) - - instance_data["node_type"] = "opengl" + instance_data.update({"node_type": "opengl"}) + instance_data["imageFormat"] = pre_create_data.get("imageFormat") + instance_data["keepImages"] = pre_create_data.get("keepImages") instance = super(CreateReview, self).create( subset_name, instance_data, - pre_create_data) # type: CreatedInstance + pre_create_data) instance_node = hou.node(instance.get("instance_node")) frame_range = hou.playbar.frameRange() parms = { - "picture": '$HIP/pyblish/`chs("subset")`/`chs("subset")`.$F4.png', - # Render frame range + "picture": "{}{}".format( + hou.text.expandString("$HIP/pyblish/"), + "{}/{}.$F4.{}".format( + subset_name, + subset_name, + pre_create_data.get("image_format") or "png")), "trange": 1, # Unlike many other ROP nodes the opengl node does not default @@ -50,13 +46,13 @@ class CreateReview(plugin.HoudiniCreator, OpenPypePyblishPluginMixin): "f2": frame_range[1], } - if self.override_resolution: - # Override resolution + override_resolution = pre_create_data.get("override_resolution") + if override_resolution: parms.update({ - "tres": True, # Override Camera Resolution - "res1": self.width, - "res2": self.height, - "aspect": self.aspect + "tres": override_resolution, + "res1": pre_create_data.get("resx"), + "res2": pre_create_data.get("resy"), + "aspect": pre_create_data.get("aspect"), }) if self.selected_nodes: @@ -66,9 +62,96 @@ class CreateReview(plugin.HoudiniCreator, OpenPypePyblishPluginMixin): instance_node.setParms(parms) - # Lock any parameters in this list - to_lock = [ - "family", - "id" - ] + to_lock = ["id", "family"] + self.lock_parameters(instance_node, to_lock) + + def get_pre_create_attr_defs(self): + attrs = super().get_pre_create_attr_defs() + image_format_enum = [ + { + "value": "png", + "label": ".png" + }, + { + "value": "tif", + "label": ".tif" + }, + { + "value": "sgi", + "label": ".sgi" + }, + { + "value": "pic.gz", + "label": ".pic.gz" + }, + { + "value": "rat", + "label": ".rat" + }, + { + "value": "jpg", + "label": ".jpg" + }, + { + "value": "cin", + "label": ".cin" + }, + { + "value": "rta", + "label": ".rta" + }, + { + "value": "rat", + "label": ".rat" + }, + { + "value": "bmp", + "label": ".bmp" + }, + { + "value": "tga", + "label": ".tga" + }, + { + "value": "rad", + "label": ".rad" + }, + { + "value": "exr", + "label": ".exr" + }, + { + "value": "pic", + "label": ".pic" + } + ] + + return attrs + [ + BoolDef("keepImages", + label="Keep Image Sequences", + default=False), + EnumDef("imageFormat", + image_format_enum, + label="Image Format Options"), + BoolDef("override_resolution", + label="Override resolution", + tooltip="When disabled the resolution set on the camera " + "is used instead.", + default=True), + NumberDef("resx", + label="Resolution Width", + default=1280, + minimum=2, + decimals=0), + NumberDef("resy", + label="Resolution Height", + default=720, + minimum=2, + decimals=0), + NumberDef("aspect", + label="Aspect Ratio", + default=1.0, + minimum=0.0001, + decimals=3) + ] diff --git a/openpype/hosts/houdini/plugins/publish/collect_review_data.py b/openpype/hosts/houdini/plugins/publish/collect_review_data.py index 7c20f9bea8..e321dcb2fa 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_review_data.py +++ b/openpype/hosts/houdini/plugins/publish/collect_review_data.py @@ -22,19 +22,17 @@ class CollectHoudiniReviewData(pyblish.api.InstancePlugin): ropnode_path = instance.data["instance_node"] ropnode = hou.node(ropnode_path) - try: - camera = ropnode.parm("camera").evalAsNode() - except TypeError: - # Not a valid node path set - self.log.error("No valid camera node found on review node: " - "{}".format(ropnode.path())) - return + camera_path = ropnode.parm("camera").eval() + camera_node = hou.node(camera_path) + if not camera_node: + raise RuntimeError("No valid camera node found on review node: " + "{}".format(camera_path)) # Collect focal length. - focal_length_parm = camera.parm("focal") + focal_length_parm = camera_node.parm("focal") if not focal_length_parm: self.log.warning("No 'focal' (focal length) parameter found on " - "camera: {}".format(camera.path())) + "camera: {}".format(camera_path)) return if focal_length_parm.isTimeDependent(): @@ -50,3 +48,5 @@ class CollectHoudiniReviewData(pyblish.api.InstancePlugin): # Store focal length in `burninDataMembers` burnin_members = instance.data.setdefault("burninDataMembers", {}) burnin_members["focalLength"] = focal_length + + instance.data.setdefault("families", []).append('ftrack') diff --git a/openpype/hosts/houdini/plugins/publish/extract_opengl.py b/openpype/hosts/houdini/plugins/publish/extract_opengl.py index 4875d9b98d..83a85ffb9a 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_opengl.py +++ b/openpype/hosts/houdini/plugins/publish/extract_opengl.py @@ -1,53 +1,56 @@ import os import pyblish.api -from openpype.pipeline import publish -from openpype.hosts.houdini.api.lib import render_rop, get_output_parameter + +from openpype.pipeline import ( + publish, + OptionalPyblishPluginMixin +) +from openpype.hosts.houdini.api.lib import render_rop import hou -class ExtractOpenGL(publish.Extractor): +class ExtractOpenGL(publish.Extractor, + OptionalPyblishPluginMixin): - order = pyblish.api.ExtractorOrder + order = pyblish.api.ExtractorOrder - 0.01 label = "Extract OpenGL" families = ["review"] hosts = ["houdini"] optional = True def process(self, instance): + if not self.is_active(instance.data): + return + ropnode = hou.node(instance.data.get("instance_node")) - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the filename parameter - # `.evalParm(parameter)` will make sure all tokens are resolved - output = get_output_parameter(ropnode).eval() - staging_dir = os.path.dirname(output) + output = ropnode.evalParm("picture") + staging_dir = os.path.normpath(os.path.dirname(output)) instance.data["stagingDir"] = staging_dir file_name = os.path.basename(output) - # We run the render - self.log.info("Extracting '%s' to '%s'" % (file_name, staging_dir)) + self.log.info("Extracting '%s' to '%s'" % (file_name, + staging_dir)) + render_rop(ropnode) - # Unfortunately user interrupting the extraction does not raise an - # error and thus still continues to the integrator. To capture that - # we make sure all files exist - files = instance.data["frames"] - missing = [fname for fname in files - if not os.path.exists(os.path.join(staging_dir, fname))] - if missing: - raise RuntimeError("Failed to complete review extraction. " - "Missing output files: {}".format(missing)) + output = instance.data["frames"] - representation = { - "name": "png", - "ext": "png", - "files": files, + tags = ["review"] + if not instance.data.get("keepImages"): + tags.append("delete") + + representation = { + "name": instance.data["imageFormat"], + "ext": instance.data["imageFormat"], + "files": output, "stagingDir": staging_dir, "frameStart": instance.data["frameStart"], "frameEnd": instance.data["frameEnd"], - "tags": ["review"] + "tags": tags, + "preview": True, + "camera_name": instance.data.get("review_camera") } if "representations" not in instance.data: diff --git a/openpype/hosts/houdini/plugins/publish/validate_scene_review.py b/openpype/hosts/houdini/plugins/publish/validate_scene_review.py new file mode 100644 index 0000000000..3a3b7e6659 --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/validate_scene_review.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +import hou + + +class ValidateSceneReview(pyblish.api.InstancePlugin): + """Validator Some Scene Settings before publishing the review + 1. Scene Path + 2. Resolution + """ + + order = pyblish.api.ValidatorOrder + families = ["review"] + hosts = ["houdini"] + label = "Scene Setting for review" + + def process(self, instance): + invalid = self.get_invalid_scene_path(instance) + if invalid: + raise PublishValidationError( + "Scene path does not exist: %s" % invalid, + title=self.label) + invalid = self.get_invalid_resolution(instance) + if invalid: + raise PublishValidationError( + "Invalid Resolution Setting", + title=self.label) + + def get_invalid_scene_path(self, instance): + invalid = list() + node = hou.node(instance.data.get("instance_node")) + scene_path = node.parm("scenepath").eval() + scene_path_node = hou.node(scene_path) + if not scene_path_node: + invalid.append(scene_path_node) + + return invalid + + def get_invalid_resolution(self, instance): + invalid = list() + node = hou.node(instance.data.get("instance_node")) + res_width = node.parm("res1").eval() + res_height = node.parm("res2").eval() + if res_width == 0: + invalid.append(res_width) + if res_height == 0: + invalid.append(res_height) + + return invalid