Skip to content

validate_frame_range

ValidateFrameRange

Bases: InstancePlugin, OptionalPyblishPluginMixin

Validates the frame ranges.

This is an optional validator checking if the frame range on instance matches the frame range specified for the folder.

It also validates render frame ranges of render layers.

Repair action will change everything to match the folder frame range.

This can be turned off by the artist to allow custom ranges.

Source code in client/ayon_max/plugins/publish/validate_frame_range.py
 16
 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
108
109
110
111
class ValidateFrameRange(pyblish.api.InstancePlugin,
                         OptionalPyblishPluginMixin):
    """Validates the frame ranges.

    This is an optional validator checking if the frame range on instance
    matches the frame range specified for the folder.

    It also validates render frame ranges of render layers.

    Repair action will change everything to match the folder frame range.

    This can be turned off by the artist to allow custom ranges.
    """

    label = "Validate Frame Range"
    order = ValidateContentsOrder
    families = ["camera", "maxrender",
                "pointcache", "pointcloud",
                "review", "redshiftproxy"]
    hosts = ["max"]
    optional = True
    actions = [RepairAction]

    settings_category = "max"

    def process(self, instance):
        if not self.is_active(instance.data):
            self.log.debug("Skipping Validate Frame Range...")
            return

        frame_range = get_frame_range(
            instance.data["taskEntity"])

        inst_frame_start = instance.data.get("frameStartHandle")
        inst_frame_end = instance.data.get("frameEndHandle")
        if inst_frame_start is None or inst_frame_end is None:
            raise KnownPublishError(
                "Missing frame start and frame end on "
                "instance to to validate."
            )
        frame_start_handle = frame_range["frameStartHandle"]
        frame_end_handle = frame_range["frameEndHandle"]
        errors = []
        if frame_start_handle != inst_frame_start:
            errors.append(
                f"Start frame ({inst_frame_start}) on instance does not match " # noqa
                f"with the start frame ({frame_start_handle}) set on the folder attributes. ")    # noqa
        if frame_end_handle != inst_frame_end:
            errors.append(
                f"End frame ({inst_frame_end}) on instance does not match "
                f"with the end frame ({frame_end_handle}) "
                "from the folder attributes. ")

        if errors:
            bullet_point_errors = "\n".join(
                "- {}".format(err) for err in errors
            )
            report = (
                "Frame range settings are incorrect.\n\n"
                f"{bullet_point_errors}\n\n"
                "You can use repair action to fix it."
            )
            raise PublishValidationError(report, title="Frame Range incorrect")

    @classmethod
    def get_invalid(cls, instance, frameStart, frameEnd):
        inst_frame_start = instance.data.get("frameStartHandle")
        inst_frame_end = instance.data.get("frameEndHandle")
        if inst_frame_start is None or inst_frame_end is None:
            raise KnownPublishError(
                "Missing frame start and frame end on "
                "instance to to validate."
            )
        invalid = []
        if frameStart != inst_frame_start:
            invalid.append(
                f"Start frame ({inst_frame_start}) on instance does not match " # noqa
                f"with the start frame ({frameStart}) set on the asset data. ")    # noqa
        if frameEnd != inst_frame_end:
            invalid.append(
                f"End frame ({inst_frame_end}) on instance does not match "
                f"with the end frame ({frameEnd}) "
                "from the asset data. ")
        return invalid

    @classmethod
    def repair(cls, instance):
        frame_range = get_frame_range()
        frame_start_handle = frame_range["frameStartHandle"]
        frame_end_handle = frame_range["frameEndHandle"]

        if instance.data["productType"] == "maxrender":
            rt.rendStart = frame_start_handle
            rt.rendEnd = frame_end_handle
        else:
            set_timeline(frame_start_handle, frame_end_handle)