Skip to content

collect_shots

CollectShot

Bases: InstancePlugin

Collect new shots.

Source code in client/ayon_hiero/plugins/publish/collect_shots.py
 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
class CollectShot(pyblish.api.InstancePlugin):
    """Collect new shots."""

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

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

    @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)

        # Adjust handles:
        # Explain
        track_item = instance.data["trackItem"]
        instance.data.update({
            "handleStart": min(
                instance.data["handleStart"], int(track_item.handleInLength())),
            "handleEnd": min(
                instance.data["handleEnd"], int(track_item.handleOutLength())),
        })

        # 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"] = {}

        edit_shared_data = context.data["editorialSharedData"].setdefault(
            instance_id, {}
        )
        edit_shared_data.update({
            key: value for key, value in instance.data.items()
            if key in cls.SHARED_KEYS
        })
        # also add `shot_clip_index` to shared data for audio instance
        edit_shared_data["shot_clip_index"] = instance.data["clip_index"]

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

        # 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(
                f"Could not retrieve otioClip for shot {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"]

        marker_metadata = json.loads(marker.metadata["json_metadata"])
        inst_data = marker_metadata["hiero_sub_products"].get(creator_id, {})

        # Overwrite settings with clip metadata is "sourceResolution"
        overwrite_clip_metadata = inst_data.get("sourceResolution", False)
        active_timeline = instance.context.data["activeTimeline"]

        # Adjust info from track_item on timeline
        track_item = None
        for video_track in active_timeline.videoTracks():
            for item in video_track.items():
                if item.guid() == instance.data["clip_index"]:
                    track_item = item
                    break

        if not track_item:
            raise PublishError(
                'Could not retrieve item from '
                f'clip guid: {instance.data["clip_index"]}'
            )

        instance.data.update({
            "annotations": self.clip_annotations(track_item.source()),
            "trackItem": track_item,
            "subtracks": self.clip_subtrack(track_item),
            "tags": lib.get_track_item_tags(track_item),
        })

        # Retrieve clip from active_timeline
        if overwrite_clip_metadata:
            source_clip = track_item.source()
            item_format = source_clip.format()

        # Get resolution from active timeline
        else:
            item_format = active_timeline.format()

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

    @staticmethod
    def clip_annotations(clip):
        """
        Args:
            clip (hiero.core.TrackItem): The clip to inspect.

        Returns:
            list[hiero.core.Annotation]: Associated clips annotations.
        """
        annotations = []
        subTrackItems = lib.flatten(clip.subTrackItems())
        annotations += [item for item in subTrackItems if isinstance(
            item, hiero.core.Annotation)]
        return annotations

    @staticmethod
    def clip_subtrack(clip):
        """
        Args:
            clip (hiero.core.TrackItem): The clip to inspect.

        Returns:
            list[hiero.core.SubTrackItem]: Associated clips SubTrackItem.
        """
        subtracks = []
        subTrackItems = lib.flatten(clip.parent().subTrackItems())
        for item in subTrackItems:
            if "TimeWarp" in item.name():
                continue
            # avoid all annotation
            if isinstance(item, hiero.core.Annotation):
                continue
            # avoid all disabled
            if not item.isEnabled():
                continue
            subtracks.append(item)
        return subtracks

clip_annotations(clip) staticmethod

Parameters:

Name Type Description Default
clip TrackItem

The clip to inspect.

required

Returns:

Type Description

list[hiero.core.Annotation]: Associated clips annotations.

Source code in client/ayon_hiero/plugins/publish/collect_shots.py
142
143
144
145
146
147
148
149
150
151
152
153
154
155
@staticmethod
def clip_annotations(clip):
    """
    Args:
        clip (hiero.core.TrackItem): The clip to inspect.

    Returns:
        list[hiero.core.Annotation]: Associated clips annotations.
    """
    annotations = []
    subTrackItems = lib.flatten(clip.subTrackItems())
    annotations += [item for item in subTrackItems if isinstance(
        item, hiero.core.Annotation)]
    return annotations

clip_subtrack(clip) staticmethod

Parameters:

Name Type Description Default
clip TrackItem

The clip to inspect.

required

Returns:

Type Description

list[hiero.core.SubTrackItem]: Associated clips SubTrackItem.

Source code in client/ayon_hiero/plugins/publish/collect_shots.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
@staticmethod
def clip_subtrack(clip):
    """
    Args:
        clip (hiero.core.TrackItem): The clip to inspect.

    Returns:
        list[hiero.core.SubTrackItem]: Associated clips SubTrackItem.
    """
    subtracks = []
    subTrackItems = lib.flatten(clip.parent().subTrackItems())
    for item in subTrackItems:
        if "TimeWarp" in item.name():
            continue
        # avoid all annotation
        if isinstance(item, hiero.core.Annotation):
            continue
        # avoid all disabled
        if not item.isEnabled():
            continue
        subtracks.append(item)
    return subtracks

process(instance)

Parameters:

Name Type Description Default
instance Instance

The shot instance to update.

required
Source code in client/ayon_hiero/plugins/publish/collect_shots.py
 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
130
131
132
133
134
135
136
137
138
139
140
def process(self, instance):
    """
    Args:
        instance (pyblish.Instance): The shot instance to update.
    """
    instance.data["integrate"] = False  # no representation for shot

    # 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(
            f"Could not retrieve otioClip for shot {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"]

    marker_metadata = json.loads(marker.metadata["json_metadata"])
    inst_data = marker_metadata["hiero_sub_products"].get(creator_id, {})

    # Overwrite settings with clip metadata is "sourceResolution"
    overwrite_clip_metadata = inst_data.get("sourceResolution", False)
    active_timeline = instance.context.data["activeTimeline"]

    # Adjust info from track_item on timeline
    track_item = None
    for video_track in active_timeline.videoTracks():
        for item in video_track.items():
            if item.guid() == instance.data["clip_index"]:
                track_item = item
                break

    if not track_item:
        raise PublishError(
            'Could not retrieve item from '
            f'clip guid: {instance.data["clip_index"]}'
        )

    instance.data.update({
        "annotations": self.clip_annotations(track_item.source()),
        "trackItem": track_item,
        "subtracks": self.clip_subtrack(track_item),
        "tags": lib.get_track_item_tags(track_item),
    })

    # Retrieve clip from active_timeline
    if overwrite_clip_metadata:
        source_clip = track_item.source()
        item_format = source_clip.format()

    # Get resolution from active timeline
    else:
        item_format = active_timeline.format()

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