diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index b5bdca456e..ab9c06280f 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -3241,8 +3241,8 @@ def get_visible_in_frame_range(nodes, start, end): Args: nodes (list): List of node names to consider. - start (int): Start frame. - end (int): End frame. + start (int, float): Start frame. + end (int, float): End frame. Returns: list: List of node names. These will be long full path names so diff --git a/openpype/hosts/maya/plugins/publish/validate_visible_only.py b/openpype/hosts/maya/plugins/publish/validate_visible_only.py new file mode 100644 index 0000000000..9094a421c6 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_visible_only.py @@ -0,0 +1,53 @@ +import pyblish.api + +import openpype.api +from openpype.hosts.maya.api.lib import get_visible_in_frame_range +import openpype.hosts.maya.api.action + + +class ValidateAlembicVisibleOnly(pyblish.api.InstancePlugin): + """Validates at least a single node is visible in frame range. + + This validation only validates if the `visibleOnly` flag is enabled + on the instance - otherwise the validation is skipped. + + """ + order = openpype.api.ValidateContentsOrder + 0.05 + label = "Alembic Visible Only" + hosts = ["maya"] + families = ["pointcache", "animation"] + actions = [openpype.hosts.maya.api.action.SelectInvalidAction] + + def process(self, instance): + + if not instance.data.get("visibleOnly", False): + self.log.debug("Visible only is disabled. Validation skipped..") + return + + invalid = self.get_invalid(instance) + if invalid: + start, end = self.get_frame_range(instance) + raise RuntimeError("No visible nodes found in " + "frame range {}-{}.".format(start, end)) + + @classmethod + def get_invalid(cls, instance): + + if instance.data["family"] == "animation": + # Special behavior to use the nodes in out_SET + nodes = instance.data["out_hierarchy"] + else: + nodes = instance[:] + + start, end = cls.get_frame_range(instance) + visible = get_visible_in_frame_range(nodes, start, end) + + if not visible: + # Return the nodes we have considered so the user can identify + # them with the select invalid action + return nodes + + @staticmethod + def get_frame_range(instance): + data = instance.data + return data["frameStartHandle"], data["frameEndHandle"]