Skip to content

collect_shots

CollectShot

Bases: InstancePlugin

Collect new shots.

Source code in client/ayon_resolve/plugins/publish/collect_shots.py
  9
 10
 11
 12
 13
 14
 15
 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
class CollectShot(pyblish.api.InstancePlugin):
    """Collect new shots."""

    order = pyblish.api.CollectorOrder - 0.49
    label = "Collect Shots"
    hosts = ["resolve"]
    families = ["shot"]

    SHARED_KEYS = (
        "folderPath",
        "fps",
        "handleStart",
        "handleEnd",
        "resolutionWidth",
        "resolutionHeight",
        "pixelAspect",
    )

    @classmethod
    def _inject_editorial_shared_data(cls, instance):
        """
        Args:
            instance (obj): The publishing instance.
        """
        context = instance.context
        instance_id = instance.data["instance_id"]

        # Inject folderPath and other creator_attributes to ensure
        # new shots/hierarchy are properly handled.
        creator_attributes = instance.data['creator_attributes']
        instance.data.update(creator_attributes)

        # Inject/Distribute instance shot data as editorialSharedData
        # to make it available for clip/plate/audio products
        # in sub-collectors.
        if not context.data.get("editorialSharedData"):
            context.data["editorialSharedData"] = {}

        context.data["editorialSharedData"][instance_id] = {
            key: value for key, value in instance.data.items()
            if key in cls.SHARED_KEYS
        }

    def process(self, instance):
        """
        Args:
            instance (pyblish.Instance): The shot instance to update.
        """
        instance.data["integrate"] = False  # no representation for shot
        track_item = instance.data["transientData"]["track_item"]

        # Adjust handles - use track item handles if they are shorter
        # than expected instance handles.
        available_start = int(track_item.GetLeftOffset())
        available_end = int(track_item.GetRightOffset())
        self.log.info(
            "Available handles: start=%s, end=%s",
            available_start, available_end)
        instance.data.update({
            "handleStart": min(
                instance.data["handleStart"], int(available_start)),
            "handleEnd": min(
                instance.data["handleEnd"], int(available_end)),
        })

        # Adjust instance data from parent otio timeline.
        otio_timeline = instance.context.data["otioTimeline"]
        otio_clip, marker = utils.get_marker_from_clip_index(
            otio_timeline, instance.data["clip_index"]
        )
        if not otio_clip:
            raise PublishError("Could not retrieve otioClip for shot %r", instance)

        # Compute fps from creator attribute.
        if instance.data['creator_attributes']["fps"] == "from_selection":
            instance.data['creator_attributes']["fps"] = instance.context.data["fps"]

        # Retrieve AyonData marker for associated clip.
        instance.data["otioClip"] = otio_clip
        creator_id = instance.data["creator_identifier"]
        inst_data = marker.metadata["resolve_sub_products"].get(creator_id, {})

        # Overwrite settings with clip metadata is "useSourceResolution"
        creator_attributes = instance.data["creator_attributes"]
        overwrite_clip_metadata = creator_attributes.get("useSourceResolution", False)
        if overwrite_clip_metadata:
            clip_metadata = inst_data["clip_source_resolution"]
            width = clip_metadata["width"]
            height = clip_metadata["height"]
            pixel_aspect = clip_metadata["pixelAspect"]

        else:
            # AYON's OTIO export = resolution from timeline metadata.
            # This is metadata is inserted by ayon_resolve.otio.davinci_export.
            width = height = None
            try:
                width = otio_timeline.metadata["width"]
                height = otio_timeline.metadata["height"]
                pixel_aspect = otio_timeline.metadata["pixelAspect"]

            except KeyError:
                # Retrieve resolution for project.
                project = lib.get_current_resolve_project()
                project_settings = project.GetSetting()
                try:
                    pixel_aspect = int(project_settings["timelinePixelAspectRatio"])
                except ValueError:
                    pixel_aspect = 1.0

                width = int(project_settings["timelineResolutionWidth"])
                height = int(project_settings["timelineResolutionHeight"])

        instance.data.update(
            {
                "resolutionWidth": width,
                "resolutionHeight": height,
                "pixelAspect": pixel_aspect,
            }
        )

        self._inject_editorial_shared_data(instance)

process(instance)

Parameters:

Name Type Description Default
instance Instance

The shot instance to update.

required
Source code in client/ayon_resolve/plugins/publish/collect_shots.py
 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def process(self, instance):
    """
    Args:
        instance (pyblish.Instance): The shot instance to update.
    """
    instance.data["integrate"] = False  # no representation for shot
    track_item = instance.data["transientData"]["track_item"]

    # Adjust handles - use track item handles if they are shorter
    # than expected instance handles.
    available_start = int(track_item.GetLeftOffset())
    available_end = int(track_item.GetRightOffset())
    self.log.info(
        "Available handles: start=%s, end=%s",
        available_start, available_end)
    instance.data.update({
        "handleStart": min(
            instance.data["handleStart"], int(available_start)),
        "handleEnd": min(
            instance.data["handleEnd"], int(available_end)),
    })

    # Adjust instance data from parent otio timeline.
    otio_timeline = instance.context.data["otioTimeline"]
    otio_clip, marker = utils.get_marker_from_clip_index(
        otio_timeline, instance.data["clip_index"]
    )
    if not otio_clip:
        raise PublishError("Could not retrieve otioClip for shot %r", instance)

    # Compute fps from creator attribute.
    if instance.data['creator_attributes']["fps"] == "from_selection":
        instance.data['creator_attributes']["fps"] = instance.context.data["fps"]

    # Retrieve AyonData marker for associated clip.
    instance.data["otioClip"] = otio_clip
    creator_id = instance.data["creator_identifier"]
    inst_data = marker.metadata["resolve_sub_products"].get(creator_id, {})

    # Overwrite settings with clip metadata is "useSourceResolution"
    creator_attributes = instance.data["creator_attributes"]
    overwrite_clip_metadata = creator_attributes.get("useSourceResolution", False)
    if overwrite_clip_metadata:
        clip_metadata = inst_data["clip_source_resolution"]
        width = clip_metadata["width"]
        height = clip_metadata["height"]
        pixel_aspect = clip_metadata["pixelAspect"]

    else:
        # AYON's OTIO export = resolution from timeline metadata.
        # This is metadata is inserted by ayon_resolve.otio.davinci_export.
        width = height = None
        try:
            width = otio_timeline.metadata["width"]
            height = otio_timeline.metadata["height"]
            pixel_aspect = otio_timeline.metadata["pixelAspect"]

        except KeyError:
            # Retrieve resolution for project.
            project = lib.get_current_resolve_project()
            project_settings = project.GetSetting()
            try:
                pixel_aspect = int(project_settings["timelinePixelAspectRatio"])
            except ValueError:
                pixel_aspect = 1.0

            width = int(project_settings["timelineResolutionWidth"])
            height = int(project_settings["timelineResolutionHeight"])

    instance.data.update(
        {
            "resolutionWidth": width,
            "resolutionHeight": height,
            "pixelAspect": pixel_aspect,
        }
    )

    self._inject_editorial_shared_data(instance)