diff --git a/openpype/hosts/houdini/plugins/load/load_fbx.py b/openpype/hosts/houdini/plugins/load/load_fbx.py index 681837e046..9c7dbf578e 100644 --- a/openpype/hosts/houdini/plugins/load/load_fbx.py +++ b/openpype/hosts/houdini/plugins/load/load_fbx.py @@ -1,12 +1,5 @@ # -*- coding: utf-8 -*- -"""Fbx Loader for houdini. - -It's almost a copy of -'load_bgeo.py'and 'load_alembic.py' -however this one includes extra comments for demonstration. - -This plugin is part of publish process guide. -""" +"""Fbx Loader for houdini. """ from openpype.pipeline import ( load, get_representation_path, @@ -15,17 +8,17 @@ from openpype.hosts.houdini.api import pipeline class FbxLoader(load.LoaderPlugin): - """Load fbx files to Houdini.""" + """Load fbx files. """ label = "Load FBX" - families = ["staticMesh", "fbx"] - representations = ["fbx"] - - # Usually you will use these value as default - order = -10 icon = "code-fork" color = "orange" + order = -10 + + families = ["staticMesh", "fbx"] + representations = ["fbx"] + def load(self, context, name=None, namespace=None, data=None): # get file path diff --git a/openpype/hosts/houdini/plugins/publish/collect_staticmesh_type.py b/openpype/hosts/houdini/plugins/publish/collect_staticmesh_type.py index 8fb07c1c5c..263d7c1001 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_staticmesh_type.py +++ b/openpype/hosts/houdini/plugins/publish/collect_staticmesh_type.py @@ -16,5 +16,5 @@ class CollectStaticMeshType(pyblish.api.InstancePlugin): def process(self, instance): if instance.data["creator_identifier"] == "io.openpype.creators.houdini.unrealstaticmesh.fbx": # noqa: E501 - # Marking this instance as FBX which triggers the FBX extractor. + # Marking this instance as FBX triggers the FBX extractor. instance.data["families"] += ["fbx"] diff --git a/openpype/hosts/houdini/plugins/publish/extract_fbx.py b/openpype/hosts/houdini/plugins/publish/extract_fbx.py index c0e84c00c8..2a95734ece 100644 --- a/openpype/hosts/houdini/plugins/publish/extract_fbx.py +++ b/openpype/hosts/houdini/plugins/publish/extract_fbx.py @@ -1,15 +1,8 @@ -"""Extract FilmBox FBX. - -Extractors are used to generate output and -update representation dictionary. - -This plugin is part of publish process guide. -""" +# -*- coding: utf-8 -*- +"""Fbx Extractor for houdini. """ import os - import pyblish.api - from openpype.pipeline import publish from openpype.hosts.houdini.api.lib import render_rop @@ -22,10 +15,8 @@ class ExtractFBX(publish.Extractor): families = ["fbx"] hosts = ["houdini"] - # Usually you will use this value as default order = pyblish.api.ExtractorOrder + 0.1 - # overrides Extractor.process() def process(self, instance): # get rop node diff --git a/openpype/hosts/houdini/plugins/publish/validate_mesh_is_static.py b/openpype/hosts/houdini/plugins/publish/validate_mesh_is_static.py new file mode 100644 index 0000000000..90985b4239 --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/validate_mesh_is_static.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +"""Validator for correct naming of Static Meshes.""" +import pyblish.api +from openpype.pipeline import ( + PublishValidationError, + OptionalPyblishPluginMixin +) +from openpype.pipeline.publish import ValidateContentsOrder + +from openpype.hosts.houdini.api.action import SelectInvalidAction + +import hou + + +class ValidateMeshIsStatic(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): + """Validate mesh is static. + + It checks if output node is time dependant. + """ + + families = ["staticMesh"] + hosts = ["houdini"] + label = "Validate Mesh is Static" + order = ValidateContentsOrder + 0.1 + actions = [SelectInvalidAction] + + def process(self, instance): + + invalid = self.get_invalid(instance) + if invalid: + nodes = [n.path() for n in invalid if isinstance(n, hou.Node)] + raise PublishValidationError( + "See log for details. " + "Invalid nodes: {0}".format(nodes) + ) + + @classmethod + def get_invalid(cls, instance): + + invalid = [] + + output_node = instance.data.get("output_node") + if output_node is None: + cls.log.debug( + "No Output Node, skipping check.." + ) + return + + + + if output_node.name().isTimeDependent(): + invalid.append(output_node) + cls.log.error( + "Output node '%s' is time dependent.", + output_node.name() + ) + + if output_node.childTypeCategory() == hou.objNodeTypeCategory(): + for child in output_node.children(): + if output_node.name().isTimeDependent(): + invalid.append(child) + cls.log.error( + "Child node '%s' in '%s' " + "his time dependent.", + child.name(), output_node.path() + ) + break + + return invalid diff --git a/openpype/hosts/houdini/plugins/publish/validate_output_node.py b/openpype/hosts/houdini/plugins/publish/validate_output_node.py new file mode 100644 index 0000000000..99a6cda077 --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/validate_output_node.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +from openpype.hosts.houdini.api.action import ( + SelectInvalidAction, + SelectROPAction, +) + +import hou + + +class ValidateOutputNode(pyblish.api.InstancePlugin): + """Validate the instance Output Node. + + This will ensure: + - The Output Node Path is set. + - The Output Node Path refers to an existing object. + """ + + order = pyblish.api.ValidatorOrder + families = ["fbx"] + hosts = ["houdini"] + label = "Validate Output Node" + actions = [SelectROPAction, SelectInvalidAction] + + def process(self, instance): + + invalid = self.get_invalid(instance) + if invalid: + raise PublishValidationError( + "Output node(s) are incorrect", + title="Invalid output node(s)" + ) + + @classmethod + def get_invalid(cls, instance): + output_node = instance.data.get("output_node") + + if output_node is None: + rop_node = hou.node(instance.data["instance_node"]) + cls.log.error( + "Output node in '%s' does not exist. " + "Ensure a valid output path is set.", rop_node.path() + ) + + return [rop_node] + + if output_node.type().category().name() not in ["Sop", "Object"]: + cls.log.error( + "Output node %s is not a SOP or OBJ node. " + "It must point to a SOP or OBJ node, " + "instead found category type: %s" + % (output_node.path(), output_node.type().category().name()) + ) + return [output_node] diff --git a/openpype/hosts/houdini/plugins/publish/validate_sop_output_node.py b/openpype/hosts/houdini/plugins/publish/validate_sop_output_node.py index d9dee38680..9590e37d26 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_sop_output_node.py +++ b/openpype/hosts/houdini/plugins/publish/validate_sop_output_node.py @@ -24,7 +24,7 @@ class ValidateSopOutputNode(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder families = ["pointcache", "vdbcache"] hosts = ["houdini"] - label = "Validate Output Node" + label = "Validate Output Node (SOP)" actions = [SelectROPAction, SelectInvalidAction] def process(self, instance): diff --git a/openpype/hosts/houdini/plugins/publish/validate_unreal_staticmesh_naming.py b/openpype/hosts/houdini/plugins/publish/validate_unreal_staticmesh_naming.py index 7820be4009..f1ea9b3844 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_unreal_staticmesh_naming.py +++ b/openpype/hosts/houdini/plugins/publish/validate_unreal_staticmesh_naming.py @@ -53,8 +53,7 @@ class ValidateUnrealStaticMeshName(pyblish.api.InstancePlugin, nodes = [n.path() for n in invalid if isinstance(n, hou.Node)] raise PublishValidationError( "See log for details. " - "Invalid nodes: {0}".format(nodes), - title=self.label + "Invalid nodes: {0}".format(nodes) ) @classmethod @@ -64,7 +63,11 @@ class ValidateUnrealStaticMeshName(pyblish.api.InstancePlugin, rop_node = hou.node(instance.data["instance_node"]) output_node = instance.data.get("output_node") - cls.log.debug(cls.collision_prefixes) + if output_node is None: + cls.log.debug( + "No Output Node, skipping check.." + ) + return # Check nodes names if output_node.childTypeCategory() == hou.objNodeTypeCategory():