From 78946d04baa08b7b4a9c781a07a66177f9469351 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 2 Dec 2020 11:28:14 +0100 Subject: [PATCH] feat(resolve): create with markers and publishing via markers --- pype/hosts/resolve/__init__.py | 2 + pype/hosts/resolve/lib.py | 136 +++++++++++++----- pype/hosts/resolve/otio.py | 12 +- pype/hosts/resolve/plugin.py | 20 +-- .../resolve/create/create_shot_clip_new.py | 7 +- .../resolve/publish/collect_instances.py | 24 ++-- 6 files changed, 132 insertions(+), 69 deletions(-) diff --git a/pype/hosts/resolve/__init__.py b/pype/hosts/resolve/__init__.py index b8457438c6..83f8e3a720 100644 --- a/pype/hosts/resolve/__init__.py +++ b/pype/hosts/resolve/__init__.py @@ -14,6 +14,7 @@ from .pipeline import ( ) from .lib import ( + publish_clip_color, get_project_manager, get_current_project, get_current_sequence, @@ -66,6 +67,7 @@ __all__ = [ "get_resolve_module", # lib + "publish_clip_color", "get_project_manager", "get_current_project", "get_current_sequence", diff --git a/pype/hosts/resolve/lib.py b/pype/hosts/resolve/lib.py index 8dd9566c44..2ade558d89 100644 --- a/pype/hosts/resolve/lib.py +++ b/pype/hosts/resolve/lib.py @@ -2,31 +2,41 @@ import sys import json import ast from opentimelineio import opentime -from pprint import pformat - from pype.api import Logger log = Logger().get_logger(__name__, "resolve") self = sys.modules[__name__] -self.pm = None +self.project_manager = None + +# Pype sequencial rename variables self.rename_index = 0 self.rename_add = 0 + +self.publish_clip_color = "Pink" +self.pype_marker_workflow = True + +# Pype compound clip workflow variable self.pype_tag_name = "VFX Notes" +# Pype marker workflow variables +self.pype_marker_name = "PYPEDATA" +self.pype_marker_duration = 1 +self.pype_marker_color = "Mint" +self.temp_marker_frame = None def get_project_manager(): from . import bmdvr - if not self.pm: - self.pm = bmdvr.GetProjectManager() - return self.pm + if not self.project_manager: + self.project_manager = bmdvr.GetProjectManager() + return self.project_manager def get_current_project(): # initialize project manager get_project_manager() - return self.pm.GetCurrentProject() + return self.project_manager.GetCurrentProject() def get_current_sequence(): @@ -111,16 +121,20 @@ def get_track_item_pype_tag(track_item): hiero.core.Tag: hierarchy, orig clip attributes """ return_tag = None - media_pool_item = track_item.GetMediaPoolItem() - # get all tags from track item - _tags = media_pool_item.GetMetadata() - if not _tags: - return None - for key, data in _tags.items(): - # return only correct tag defined by global name - if key in self.pype_tag_name: - return_tag = json.loads(data) + if self.pype_marker_workflow: + return_tag = get_pype_marker(track_item) + else: + media_pool_item = track_item.GetMediaPoolItem() + + # get all tags from track item + _tags = media_pool_item.GetMetadata() + if not _tags: + return None + for key, data in _tags.items(): + # return only correct tag defined by global name + if key in self.pype_tag_name: + return_tag = json.loads(data) return return_tag @@ -130,28 +144,37 @@ def set_track_item_pype_tag(track_item, data=None): Set pype track item tag to input track_item. Attributes: - trackItem (hiero.core.TrackItem): hiero object + trackItem (resolve.TimelineItem): resolve api object Returns: - hiero.core.Tag + dict: json loaded data """ data = data or dict() # get available pype tag if any tag_data = get_track_item_pype_tag(track_item) - if tag_data: - media_pool_item = track_item.GetMediaPoolItem() - # it not tag then create one + if self.pype_marker_workflow: + # delete tag as it is not updatable + if tag_data: + delete_pype_marker(track_item) + tag_data.update(data) - media_pool_item.SetMetadata(self.pype_tag_name, json.dumps(tag_data)) - return tag_data + set_pype_marker(track_item, 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)) - return tag_data + if tag_data: + media_pool_item = track_item.GetMediaPoolItem() + # it not tag then create one + tag_data.update(data) + media_pool_item.SetMetadata( + self.pype_tag_name, json.dumps(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)) + + return tag_data def imprint(track_item, data=None): @@ -187,7 +210,7 @@ def set_publish_attribute(track_item, value): value (bool): True or False """ tag_data = get_track_item_pype_tag(track_item) - tag_data["publish"] = str(value) + tag_data["publish"] = value # set data to the publish attribute set_track_item_pype_tag(track_item, tag_data) @@ -200,10 +223,47 @@ def get_publish_attribute(track_item): value (bool): True or False """ tag_data = get_track_item_pype_tag(track_item) - value = tag_data["publish"] + return tag_data["publish"] - # return value converted to bool value. Atring is stored in tag. - return ast.literal_eval(value) + +def set_pype_marker(track_item, tag_data): + source_start = track_item.GetLeftOffset() + item_duration = track_item.GetDuration() + frame = int(source_start + (item_duration / 2)) + + # marker attributes + frameId = (frame / 10) * 10 + color = self.pype_marker_color + name = self.pype_marker_name + note = json.dumps(tag_data) + duration = (self.pype_marker_duration / 10) * 10 + + track_item.AddMarker( + frameId, + color, + name, + note, + duration + ) + + +def get_pype_marker(track_item): + track_item_markers = track_item.GetMarkers() + for marker_frame in track_item_markers: + note = track_item_markers[marker_frame]["note"] + color = track_item_markers[marker_frame]["color"] + name = track_item_markers[marker_frame]["name"] + print(f"_ marker data: {marker_frame} | {name} | {color} | {note}") + if name == self.pype_marker_name and color == self.pype_marker_color: + self.temp_marker_frame = marker_frame + return json.loads(note) + + return dict() + + +def delete_pype_marker(track_item): + track_item.DeleteMarkerAtFrame(self.temp_marker_frame) + self.temp_marker_frame = None def create_current_sequence_media_bin(sequence): @@ -523,16 +583,16 @@ def set_project_manager_to_folder_name(folder_name): set_folder = False # go back to root folder - if self.pm.GotoRootFolder(): + if self.project_manager.GotoRootFolder(): log.info(f"Testing existing folder: {folder_name}") folders = convert_resolve_list_type( - self.pm.GetFoldersInCurrentFolder()) + self.project_manager.GetFoldersInCurrentFolder()) log.info(f"Testing existing folders: {folders}") # get me first available folder object # with the same name as in `folder_name` else return False if next((f for f in folders if f in folder_name), False): log.info(f"Found existing folder: {folder_name}") - set_folder = self.pm.OpenFolder(folder_name) + set_folder = self.project_manager.OpenFolder(folder_name) if set_folder: return True @@ -540,11 +600,11 @@ def set_project_manager_to_folder_name(folder_name): # if folder by name is not existent then create one # go back to root folder log.info(f"Folder `{folder_name}` not found and will be created") - if self.pm.GotoRootFolder(): + if self.project_manager.GotoRootFolder(): try: # create folder by given name - self.pm.CreateFolder(folder_name) - self.pm.OpenFolder(folder_name) + self.project_manager.CreateFolder(folder_name) + self.project_manager.OpenFolder(folder_name) return True except NameError as e: log.error((f"Folder with name `{folder_name}` cannot be created!" diff --git a/pype/hosts/resolve/otio.py b/pype/hosts/resolve/otio.py index 3edb6b08c2..7a6d142a10 100644 --- a/pype/hosts/resolve/otio.py +++ b/pype/hosts/resolve/otio.py @@ -36,19 +36,19 @@ def create_reference(media_pool_item): def create_markers(track_item, frame_rate): track_item_markers = track_item.GetMarkers() markers = [] - for m_frame in track_item_markers: + for marker_frame in track_item_markers: markers.append( otio.schema.Marker( - name=track_item_markers[m_frame]["name"], + name=track_item_markers[marker_frame]["name"], marked_range=create_time_range( - m_frame, - track_item_markers[m_frame]["duration"], + marker_frame, + track_item_markers[marker_frame]["duration"], frame_rate ), - color=track_item_markers[m_frame]["color"].upper(), + color=track_item_markers[marker_frame]["color"].upper(), metadata={ "Resolve": { - "note": track_item_markers[m_frame]["note"] + "note": track_item_markers[marker_frame]["note"] } } ) diff --git a/pype/hosts/resolve/plugin.py b/pype/hosts/resolve/plugin.py index 95097434f8..be666358ae 100644 --- a/pype/hosts/resolve/plugin.py +++ b/pype/hosts/resolve/plugin.py @@ -446,16 +446,18 @@ class PublishClip: else: self.tag_data["asset"] = self.ti_name - lib.create_compound_clip( - self.track_item_data, - self.tag_data["asset"], - self.mp_folder - ) + if not lib.pype_marker_workflow: + # create compound clip workflow + 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"] - }) + # 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/create/create_shot_clip_new.py b/pype/plugins/resolve/create/create_shot_clip_new.py index a94e30ed73..5f6790394b 100644 --- a/pype/plugins/resolve/create/create_shot_clip_new.py +++ b/pype/plugins/resolve/create/create_shot_clip_new.py @@ -259,7 +259,6 @@ class CreateShotClipNew(resolve.Creator): self.rename_index = i # convert track item to timeline media pool item - resolve.PublishClip(self, track_item_data, **kwargs).convert() - - # clear color after it is done - track_item_data["clip"]["item"].ClearClipColor() + track_item = resolve.PublishClip( + self, track_item_data, **kwargs).convert() + track_item.SetClipColor(lib.publish_clip_color) diff --git a/pype/plugins/resolve/publish/collect_instances.py b/pype/plugins/resolve/publish/collect_instances.py index b556117e65..b8c929f3d6 100644 --- a/pype/plugins/resolve/publish/collect_instances.py +++ b/pype/plugins/resolve/publish/collect_instances.py @@ -15,7 +15,7 @@ class CollectInstances(pyblish.api.ContextPlugin): def process(self, context): selected_track_items = resolve.get_current_track_items( - filter=True, selecting_color="Pink") + filter=True, selecting_color=resolve.publish_clip_color) self.log.info( "Processing enabled track items: {}".format( @@ -36,18 +36,15 @@ class CollectInstances(pyblish.api.ContextPlugin): if tag_data.get("id") != "pyblish.avalon.instance": continue - compound_source_prop = tag_data["sourceProperties"] - self.log.debug(f"compound_source_prop: {compound_source_prop}") - - # source = track_item_data.GetMediaPoolItem() + media_pool_item = track_item.GetMediaPoolItem() + clip_property = media_pool_item.GetClipProperty() + self.log.debug(f"clip_property: {clip_property}") source_path = os.path.normpath( - compound_source_prop["File Path"]) - source_name = compound_source_prop["File Name"] - source_id = tag_data["sourceId"] + clip_property["File Path"]) + source_name = clip_property["File Name"] 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({ @@ -64,10 +61,13 @@ class CollectInstances(pyblish.api.ContextPlugin): families = [str(f) for f in tag_data["families"]] families.insert(0, str(family)) - track = tag_data["track_data"]["name"] + track = track_item_data["track"]["name"] base_name = os.path.basename(source_path) file_head = os.path.splitext(base_name)[0] - # source_first_frame = int(file_info.startFrame()) + source_first_frame = int( + track_item.GetStart() + - track_item.GetLeftOffset() + ) # apply only for feview and master track instance if review: @@ -89,7 +89,7 @@ class CollectInstances(pyblish.api.ContextPlugin): "source": source_path, "sourcePath": source_path, "sourceFileHead": file_head, - # "sourceFirst": source_first_frame, + "sourceFirst": source_first_frame, }) instance = context.create_instance(**data)