Skip to content

validate_frame_range

ValidateFrameRange

Bases: HoudiniInstancePlugin

Validate Frame Range.

Due to the usage of start and end handles, then Frame Range must be >= (start handle + end handle) which results that frameEnd be smaller than frameStart

Source code in client/ayon_houdini/plugins/publish/validate_frame_range.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
class ValidateFrameRange(plugin.HoudiniInstancePlugin):
    """Validate Frame Range.

    Due to the usage of start and end handles,
    then Frame Range must be >= (start handle + end handle)
    which results that frameEnd be smaller than frameStart
    """

    order = pyblish.api.ValidatorOrder - 0.1
    label = "Validate Frame Range"
    actions = [DisableUseTaskHandlesAction, SelectInvalidAction]

    def process(self, instance):

        invalid = self.get_invalid(instance)
        if invalid:
            raise PublishValidationError(
                title="Invalid Frame Range",
                message=(
                    "Invalid frame range because the instance "
                    "start frame ({0[frameStart]}) is higher than "
                    "the end frame ({0[frameEnd]})"
                    .format(instance.data)
                ),
                description=(
                    "## Invalid Frame Range\n"
                    "The frame range for the instance is invalid because "
                    "the start frame is higher than the end frame.\n\nThis "
                    "is likely due to task handles being applied to your "
                    "instance or the ROP node's start frame "
                    "is set higher than the end frame.\n\nIf your ROP frame "
                    "range is correct and you do not want to apply task "
                    "handles make sure to disable Use task handles on the "
                    "publish instance."
                )
            )

    @classmethod
    def get_invalid(cls, instance):

        if not instance.data.get("instance_node"):
            return

        rop_node = hou.node(instance.data["instance_node"])
        frame_start = instance.data.get("frameStart")
        frame_end = instance.data.get("frameEnd")

        if frame_start is None or frame_end is None:
            cls.log.debug(
                "Skipping frame range validation for "
                "instance without frame data: {}".format(rop_node.path())
            )
            return

        if frame_start > frame_end:
            cls.log.info(
                "The ROP node render range is set to "
                "{0[frameStartHandle]} - {0[frameEndHandle]} "
                "The task handles applied to the instance are start handle "
                "{0[handleStart]} and end handle {0[handleEnd]}"
                .format(instance.data)
            )
            return [rop_node]

    @classmethod
    def repair(cls, instance):

        if not cls.get_invalid(instance):
            # Already fixed
            return

        # Disable use task handles
        context = instance.context
        create_context = context.data["create_context"]
        instance_id = instance.data.get("instance_id")
        if not instance_id:
            cls.log.debug("'{}' must have instance id"
                          .format(instance))
            return

        created_instance = create_context.get_instance_by_id(instance_id)
        if not instance_id:
            cls.log.debug("Unable to find instance '{}' by id"
                          .format(instance))
            return

        created_instance.publish_attributes["CollectAssetHandles"]["use_handles"] = False  # noqa

        create_context.save_changes()
        cls.log.debug("use task handles is turned off for '{}'"
                      .format(instance))