From 1f65c27c1b0489d35ea088448ad2239757aadc86 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 30 Nov 2020 18:17:53 +0100 Subject: [PATCH] feat(resolve): publishing wip --- pype/hosts/resolve/lib.py | 27 +++--- pype/hosts/resolve/plugin.py | 7 +- .../{publish => _publish}/collect_clips.py | 0 .../resolve/create/collect_clip_resolution.py | 38 ++++++++ .../resolve/publish/collect_instances.py | 97 +++++++++++++++++++ .../resolve/publish/collect_project.py | 29 ------ .../resolve/publish/collect_workfile.py | 58 +++++++++++ 7 files changed, 211 insertions(+), 45 deletions(-) rename pype/plugins/resolve/{publish => _publish}/collect_clips.py (100%) create mode 100644 pype/plugins/resolve/create/collect_clip_resolution.py create mode 100644 pype/plugins/resolve/publish/collect_instances.py delete mode 100644 pype/plugins/resolve/publish/collect_project.py create mode 100644 pype/plugins/resolve/publish/collect_workfile.py diff --git a/pype/hosts/resolve/lib.py b/pype/hosts/resolve/lib.py index 74f105a130..8dd9566c44 100644 --- a/pype/hosts/resolve/lib.py +++ b/pype/hosts/resolve/lib.py @@ -105,14 +105,16 @@ def get_track_item_pype_tag(track_item): Get pype track item tag created by creator or loader plugin. Attributes: - trackItem (hiero.core.TrackItem): hiero object + trackItem (resolve.TimelineItem): hiero object Returns: hiero.core.Tag: hierarchy, orig clip attributes """ return_tag = None + media_pool_item = track_item.GetMediaPoolItem() + # get all tags from track item - _tags = track_item.GetMetadata() + _tags = media_pool_item.GetMetadata() if not _tags: return None for key, data in _tags.items(): @@ -135,22 +137,17 @@ def set_track_item_pype_tag(track_item, data=None): """ data = data or dict() - # basic Tag's attribute - tag_data = { - "editable": "0", - "note": "Pype data holder", - "icon": "pype_icon.png", - "metadata": {k: v for k, v in data.items()} - } # get available pype tag if any - _tag = get_track_item_pype_tag(track_item) + tag_data = get_track_item_pype_tag(track_item) - if _tag: + if tag_data: + media_pool_item = track_item.GetMediaPoolItem() # it not tag then create one - _tag.update(tag_data) - track_item.SetMetadata(self.pype_tag_name, json.dumps(_tag)) - return _tag + tag_data.update(data) + media_pool_item.SetMetadata(self.pype_tag_name, json.dumps(tag_data)) + return tag_data else: + tag_data = data # if pype tag available then update with input data # add it to the input track item track_item.SetMetadata(self.pype_tag_name, json.dumps(tag_data)) @@ -416,7 +413,7 @@ def swap_clips(from_clip, to_clip, to_clip_name, to_in_frame, to_out_frame): It will add take and activate it to the frame range which is inputted Args: - from_clip (resolve.mediaPoolItem) + from_clip (resolve.TimelineItem) to_clip (resolve.mediaPoolItem) to_clip_name (str): name of to_clip to_in_frame (float): cut in frame, usually `GetLeftOffset()` diff --git a/pype/hosts/resolve/plugin.py b/pype/hosts/resolve/plugin.py index c816735be2..95097434f8 100644 --- a/pype/hosts/resolve/plugin.py +++ b/pype/hosts/resolve/plugin.py @@ -446,12 +446,17 @@ class PublishClip: else: self.tag_data["asset"] = self.ti_name - self.track_item = lib.create_compound_clip( + lib.create_compound_clip( self.track_item_data, self.tag_data["asset"], self.mp_folder ) + # add track_item_data selection to tag + self.tag_data.update({ + "track_data": self.track_item_data["track"] + }) + # create pype tag on track_item and add data lib.imprint(self.track_item, self.tag_data) diff --git a/pype/plugins/resolve/publish/collect_clips.py b/pype/plugins/resolve/_publish/collect_clips.py similarity index 100% rename from pype/plugins/resolve/publish/collect_clips.py rename to pype/plugins/resolve/_publish/collect_clips.py diff --git a/pype/plugins/resolve/create/collect_clip_resolution.py b/pype/plugins/resolve/create/collect_clip_resolution.py new file mode 100644 index 0000000000..3bea68c677 --- /dev/null +++ b/pype/plugins/resolve/create/collect_clip_resolution.py @@ -0,0 +1,38 @@ +import pyblish.api + + +class CollectClipResolution(pyblish.api.InstancePlugin): + """Collect clip geometry resolution""" + + order = pyblish.api.CollectorOrder - 0.1 + label = "Collect Clip Resoluton" + hosts = ["resolve"] + families = ["clip"] + + def process(self, instance): + sequence = instance.context.data['activeSequence'] + item = instance.data["item"] + source_resolution = instance.data.get("sourceResolution", None) + + resolution_width = int(sequence.format().width()) + resolution_height = int(sequence.format().height()) + pixel_aspect = sequence.format().pixelAspect() + + # source exception + if source_resolution: + resolution_width = int(item.source().mediaSource().width()) + resolution_height = int(item.source().mediaSource().height()) + pixel_aspect = item.source().mediaSource().pixelAspect() + + resolution_data = { + "resolutionWidth": resolution_width, + "resolutionHeight": resolution_height, + "pixelAspect": pixel_aspect + } + # add to instacne data + instance.data.update(resolution_data) + + self.log.info("Resolution of instance '{}' is: {}".format( + instance, + resolution_data + )) diff --git a/pype/plugins/resolve/publish/collect_instances.py b/pype/plugins/resolve/publish/collect_instances.py new file mode 100644 index 0000000000..a2c7fea0e0 --- /dev/null +++ b/pype/plugins/resolve/publish/collect_instances.py @@ -0,0 +1,97 @@ +import os +import pyblish +from pype.hosts import resolve + +# # developer reload modules +from pprint import pformat + + +class CollectInstances(pyblish.api.ContextPlugin): + """Collect all Track items selection.""" + + order = pyblish.api.CollectorOrder - 0.5 + label = "Collect Instances" + hosts = ["resolve"] + + def process(self, context): + selected_track_items = resolve.get_current_track_items( + filter=True, selecting_color="Pink") + + self.log.info( + "Processing enabled track items: {}".format( + len(selected_track_items))) + + for track_item_data in selected_track_items: + self.log.debug(pformat(track_item_data)) + data = dict() + track_item = track_item_data["clip"]["item"] + self.log.debug(track_item) + # get pype tag data + tag_parsed_data = resolve.get_track_item_pype_tag(track_item) + self.log.debug(pformat(tag_parsed_data)) + + if not tag_parsed_data: + continue + + if tag_parsed_data.get("id") != "pyblish.avalon.instance": + continue + + compound_source_prop = tag_parsed_data["sourceProperties"] + self.log.debug(f"compound_source_prop: {compound_source_prop}") + + # source = track_item_data.GetMediaPoolItem() + + source_path = os.path.normpath( + compound_source_prop["File Path"]) + source_name = compound_source_prop["File Name"] + source_id = tag_parsed_data["sourceId"] + self.log.debug(f"source_path: {source_path}") + self.log.debug(f"source_name: {source_name}") + self.log.debug(f"source_id: {source_id}") + + # add tag data to instance data + data.update({ + k: v for k, v in tag_parsed_data.items() + if k not in ("id", "applieswhole", "label") + }) + + asset = tag_parsed_data["asset"] + subset = tag_parsed_data["subset"] + review = tag_parsed_data["review"] + + # insert family into families + family = tag_parsed_data["family"] + families = [str(f) for f in tag_parsed_data["families"]] + families.insert(0, str(family)) + + track = tag_parsed_data["track_data"]["name"] + base_name = os.path.basename(source_path) + file_head = os.path.splitext(base_name)[0] + # source_first_frame = int(file_info.startFrame()) + + # apply only for feview and master track instance + if review: + families += ["review", "ftrack"] + + data.update({ + "name": "{} {} {}".format(asset, subset, families), + "asset": asset, + "item": track_item, + "families": families, + + # tags + "tags": tag_parsed_data, + + # track item attributes + "track": track, + + # source attribute + "source": source_path, + "sourcePath": source_path, + "sourceFileHead": file_head, + # "sourceFirst": source_first_frame, + }) + + instance = context.create_instance(**data) + + self.log.info("Creating instance: {}".format(instance)) diff --git a/pype/plugins/resolve/publish/collect_project.py b/pype/plugins/resolve/publish/collect_project.py deleted file mode 100644 index aa57f93619..0000000000 --- a/pype/plugins/resolve/publish/collect_project.py +++ /dev/null @@ -1,29 +0,0 @@ -import os -import pyblish.api -from pype.hosts.resolve.utils import get_resolve_module - - -class CollectProject(pyblish.api.ContextPlugin): - """Collect Project object""" - - order = pyblish.api.CollectorOrder - 0.1 - label = "Collect Project" - hosts = ["resolve"] - - def process(self, context): - exported_projet_ext = ".drp" - current_dir = os.getenv("AVALON_WORKDIR") - resolve = get_resolve_module() - PM = resolve.GetProjectManager() - P = PM.GetCurrentProject() - name = P.GetName() - - fname = name + exported_projet_ext - current_file = os.path.join(current_dir, fname) - normalised = os.path.normpath(current_file) - - context.data["project"] = P - context.data["currentFile"] = normalised - - self.log.info(name) - self.log.debug(normalised) diff --git a/pype/plugins/resolve/publish/collect_workfile.py b/pype/plugins/resolve/publish/collect_workfile.py new file mode 100644 index 0000000000..a8b09573db --- /dev/null +++ b/pype/plugins/resolve/publish/collect_workfile.py @@ -0,0 +1,58 @@ +import os +import pyblish.api +from pype.hosts import resolve +from avalon import api as avalon + + +class CollectWorkfile(pyblish.api.ContextPlugin): + """Inject the current working file into context""" + + label = "Collect Workfile" + order = pyblish.api.CollectorOrder - 0.501 + + def process(self, context): + exported_projet_ext = ".drp" + asset = avalon.Session["AVALON_ASSET"] + staging_dir = os.getenv("AVALON_WORKDIR") + subset = "workfile" + + project = resolve.get_current_project() + name = project.GetName() + + base_name = name + exported_projet_ext + current_file = os.path.join(staging_dir, base_name) + current_file = os.path.normpath(current_file) + + active_sequence = resolve.get_current_sequence() + video_tracks = resolve.get_video_track_names() + + # set main project attributes to context + context.data["activeProject"] = project + context.data["activeSequence"] = active_sequence + context.data["videoTracks"] = video_tracks + context.data["currentFile"] = current_file + + self.log.info("currentFile: {}".format(current_file)) + + # creating workfile representation + representation = { + 'name': 'hrox', + 'ext': 'hrox', + 'files': base_name, + "stagingDir": staging_dir, + } + + instance_data = { + "name": "{}_{}".format(asset, subset), + "asset": asset, + "subset": "{}{}".format(asset, subset.capitalize()), + "item": project, + "family": "workfile", + + # source attribute + "sourcePath": current_file, + "representations": [representation] + } + + instance = context.create_instance(**instance_data) + self.log.info("Creating instance: {}".format(instance))