resolve: rename sequence namespace to timeline

This commit is contained in:
Jakub Jezek 2021-01-29 18:03:57 +01:00
parent 5339aad2c2
commit 5c73fc0713
No known key found for this signature in database
GPG key ID: C4B96E101D2A47F3
9 changed files with 32 additions and 493 deletions

View file

@ -18,7 +18,7 @@ from .api.lib import (
publish_clip_color,
get_project_manager,
get_current_project,
get_current_sequence,
get_current_timeline,
create_bin,
get_media_pool_item,
create_media_pool_item,
@ -81,7 +81,7 @@ __all__ = [
"publish_clip_color",
"get_project_manager",
"get_current_project",
"get_current_sequence",
"get_current_timeline",
"create_bin",
"get_media_pool_item",
"create_media_pool_item",

View file

@ -50,10 +50,10 @@ def maintain_current_timeline(to_timeline: object,
timeline2
>>> with maintain_current_timeline(to_timeline):
... print(get_current_sequence().GetName())
... print(get_current_timeline().GetName())
timeline2
>>> print(get_current_sequence().GetName())
>>> print(get_current_timeline().GetName())
timeline1
"""
project = get_current_project()
@ -91,7 +91,7 @@ def get_current_project():
return self.project_manager.GetCurrentProject()
def get_current_sequence(new=False):
def get_current_timeline(new=False):
# get current project
project = get_current_project()
@ -217,7 +217,7 @@ def create_timeline_item(media_pool_item: object,
media_pool = project.GetMediaPool()
clip_property = media_pool_item.GetClipProperty()
clip_name = clip_property["File Name"]
timeline = timeline or get_current_sequence()
timeline = timeline or get_current_timeline()
# if timeline was used then switch it to current timeline
with maintain_current_timeline(timeline):
@ -260,7 +260,7 @@ def get_timeline_item(media_pool_item: object,
clip_property = media_pool_item.GetClipProperty()
clip_name = clip_property["File Name"]
output_timeline_item = None
timeline = timeline or get_current_sequence()
timeline = timeline or get_current_timeline()
with maintain_current_timeline(timeline):
# search the timeline for the added clip
@ -277,15 +277,15 @@ def get_timeline_item(media_pool_item: object,
def get_video_track_names() -> list:
tracks = list()
track_type = "video"
sequence = get_current_sequence()
timeline = get_current_timeline()
# get all tracks count filtered by track type
selected_track_count = sequence.GetTrackCount(track_type)
selected_track_count = timeline.GetTrackCount(track_type)
# loop all tracks and get items
track_index: int
for track_index in range(1, (int(selected_track_count) + 1)):
track_name = sequence.GetTrackName("video", track_index)
track_name = timeline.GetTrackName("video", track_index)
tracks.append(track_name)
return tracks
@ -301,29 +301,29 @@ def get_current_timeline_items(
track_type = track_type or "video"
selecting_color = selecting_color or "Chocolate"
project = get_current_project()
sequence = get_current_sequence()
timeline = get_current_timeline()
selected_clips = list()
# get all tracks count filtered by track type
selected_track_count = sequence.GetTrackCount(track_type)
selected_track_count = timeline.GetTrackCount(track_type)
# loop all tracks and get items
_clips = dict()
for track_index in range(1, (int(selected_track_count) + 1)):
_track_name = sequence.GetTrackName(track_type, track_index)
_track_name = timeline.GetTrackName(track_type, track_index)
# filter out all unmathed track names
if track_name:
if _track_name not in track_name:
continue
timeline_items = sequence.GetItemListInTrack(
timeline_items = timeline.GetItemListInTrack(
track_type, track_index)
_clips[track_index] = timeline_items
_data = {
"project": project,
"sequence": sequence,
"timeline": timeline,
"track": {
"name": _track_name,
"index": track_index,
@ -529,7 +529,7 @@ def create_compound_clip(clip_data, name, folder):
"""
# get basic objects form data
project = clip_data["project"]
sequence = clip_data["sequence"]
timeline = clip_data["timeline"]
clip = clip_data["clip"]
# get details of objects
@ -560,7 +560,7 @@ def create_compound_clip(clip_data, name, folder):
out_frame = opentime.to_frames(mp_out_rc)
# keep original sequence
sq_origin = sequence
tl_origin = timeline
# Set current folder to input media_pool_folder:
mp.SetCurrentFolder(folder)
@ -582,7 +582,7 @@ def create_compound_clip(clip_data, name, folder):
if c.GetName() in name), None)
print(f"_ cct created: {cct}")
with maintain_current_timeline(cct, sq_origin):
with maintain_current_timeline(cct, tl_origin):
# Add input clip to the current timeline:
mp.AppendToTimeline([{
"mediaPoolItem": mp_item,
@ -775,7 +775,7 @@ def _convert_resolve_list_type(resolve_list):
def create_otio_time_range_from_timeline_item_data(timeline_item_data):
timeline_item = timeline_item_data["clip"]["item"]
project = timeline_item_data["project"]
timeline = timeline_item_data["sequence"]
timeline = timeline_item_data["timeline"]
timeline_start = timeline.GetStartFrame()
frame_start = int(timeline_item.GetStart() - timeline_start)

View file

@ -38,6 +38,9 @@ def install():
# Disable all families except for the ones we explicitly want to see
family_states = [
"imagesequence",
"render2d",
"plate",
"render",
"mov",
"clip"
]

View file

@ -320,9 +320,9 @@ class ClipLoader:
self.active_timeline = options["timeline"]
else:
# create new sequence
self.active_timeline = lib.get_current_sequence(new=True)
self.active_timeline = lib.get_current_timeline(new=True)
else:
self.active_timeline = lib.get_current_sequence()
self.active_timeline = lib.get_current_timeline()
cls.timeline = self.active_timeline
@ -476,7 +476,7 @@ class Creator(api.Creator):
# adding basic current context resolve objects
self.project = resolve.get_current_project()
self.sequence = resolve.get_current_sequence()
self.timeline = resolve.get_current_timeline()
if (self.options or {}).get("useSelection"):
self.selected = resolve.get_current_timeline_items(filter=True)
@ -529,8 +529,8 @@ class PublishClip:
# get main parent objects
self.timeline_item_data = timeline_item_data
self.timeline_item = timeline_item_data["clip"]["item"]
sequence_name = timeline_item_data["sequence"].GetName()
self.sequence_name = str(sequence_name).replace(" ", "_")
timeline_name = timeline_item_data["timeline"].GetName()
self.timeline_name = str(timeline_name).replace(" ", "_")
# track item (clip) main attributes
self.ti_name = self.timeline_item.GetName()
@ -601,7 +601,7 @@ class PublishClip:
self.timeline_item_default_data = {
"_folder_": "shots",
"_sequence_": self.sequence_name,
"_sequence_": self.timeline_name,
"_track_": self.track_name,
"_clip_": self.ti_name,
"_trackIndex_": self.track_index,

View file

@ -1,38 +0,0 @@
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
))

View file

@ -1,162 +0,0 @@
import os
from pyblish import api
from pype.hosts import resolve
import json
class CollectClips(api.ContextPlugin):
"""Collect all Track items selection."""
order = api.CollectorOrder + 0.01
label = "Collect Clips"
hosts = ["resolve"]
def process(self, context):
# create asset_names conversion table
if not context.data.get("assetsShared"):
self.log.debug("Created `assetsShared` in context")
context.data["assetsShared"] = dict()
projectdata = context.data["projectEntity"]["data"]
selection = resolve.get_current_track_items(
filter=True, selecting_color="Pink")
for clip_data in selection:
data = dict()
# get basic objects form data
project = clip_data["project"]
sequence = clip_data["sequence"]
clip = clip_data["clip"]
# sequence attrs
sq_frame_start = sequence.GetStartFrame()
self.log.debug(f"sq_frame_start: {sq_frame_start}")
sq_markers = sequence.GetMarkers()
# get details of objects
clip_item = clip["item"]
track = clip_data["track"]
mp = project.GetMediaPool()
# get clip attributes
clip_metadata = resolve.get_pype_clip_metadata(clip_item)
clip_metadata = json.loads(clip_metadata)
self.log.debug(f"clip_metadata: {clip_metadata}")
compound_source_prop = clip_metadata["sourceProperties"]
self.log.debug(f"compound_source_prop: {compound_source_prop}")
asset_name = clip_item.GetName()
mp_item = clip_item.GetMediaPoolItem()
mp_prop = mp_item.GetClipProperty()
source_first = int(compound_source_prop["Start"])
source_last = int(compound_source_prop["End"])
source_duration = compound_source_prop["Frames"]
fps = float(mp_prop["FPS"])
self.log.debug(f"source_first: {source_first}")
self.log.debug(f"source_last: {source_last}")
self.log.debug(f"source_duration: {source_duration}")
self.log.debug(f"fps: {fps}")
source_path = os.path.normpath(
compound_source_prop["File Path"])
source_name = compound_source_prop["File Name"]
source_id = clip_metadata["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}")
clip_left_offset = int(clip_item.GetLeftOffset())
clip_right_offset = int(clip_item.GetRightOffset())
self.log.debug(f"clip_left_offset: {clip_left_offset}")
self.log.debug(f"clip_right_offset: {clip_right_offset}")
# source in/out
source_in = int(source_first + clip_left_offset)
source_out = int(source_first + clip_right_offset)
self.log.debug(f"source_in: {source_in}")
self.log.debug(f"source_out: {source_out}")
clip_in = int(clip_item.GetStart() - sq_frame_start)
clip_out = int(clip_item.GetEnd() - sq_frame_start)
clip_duration = int(clip_item.GetDuration())
self.log.debug(f"clip_in: {clip_in}")
self.log.debug(f"clip_out: {clip_out}")
self.log.debug(f"clip_duration: {clip_duration}")
is_sequence = False
self.log.debug(
"__ assets_shared: {}".format(
context.data["assetsShared"]))
# Check for clips with the same range
# this is for testing if any vertically neighbouring
# clips has been already processed
clip_matching_with_range = next(
(k for k, v in context.data["assetsShared"].items()
if (v.get("_clipIn", 0) == clip_in)
and (v.get("_clipOut", 0) == clip_out)
), False)
# check if clip name is the same in matched
# vertically neighbouring clip
# if it is then it is correct and resent variable to False
# not to be rised wrong name exception
if asset_name in str(clip_matching_with_range):
clip_matching_with_range = False
# rise wrong name exception if found one
assert (not clip_matching_with_range), (
"matching clip: {asset}"
" timeline range ({clip_in}:{clip_out})"
" conflicting with {clip_matching_with_range}"
" >> rename any of clips to be the same as the other <<"
).format(
**locals())
if ("[" in source_name) and ("]" in source_name):
is_sequence = True
data.update({
"name": "_".join([
track["name"], asset_name, source_name]),
"item": clip_item,
"source": mp_item,
# "timecodeStart": str(source.timecodeStart()),
"timelineStart": sq_frame_start,
"sourcePath": source_path,
"sourceFileHead": source_name,
"isSequence": is_sequence,
"track": track["name"],
"trackIndex": track["index"],
"sourceFirst": source_first,
"sourceIn": source_in,
"sourceOut": source_out,
"mediaDuration": source_duration,
"clipIn": clip_in,
"clipOut": clip_out,
"clipDuration": clip_duration,
"asset": asset_name,
"subset": "plateMain",
"family": "clip",
"families": [],
"handleStart": projectdata.get("handleStart", 0),
"handleEnd": projectdata.get("handleEnd", 0)})
instance = context.create_instance(**data)
self.log.info("Created instance: {}".format(instance))
self.log.info("Created instance.data: {}".format(instance.data))
context.data["assetsShared"][asset_name] = {
"_clipIn": clip_in,
"_clipOut": clip_out
}
self.log.info(
"context.data[\"assetsShared\"]: {}".format(
context.data["assetsShared"]))

View file

@ -240,11 +240,11 @@ class CreateShotClip(resolve.Creator):
sorted_selected_track_items.extend(unsorted_selected_track_items)
# sequence attrs
sq_frame_start = self.sequence.GetStartFrame()
sq_markers = self.sequence.GetMarkers()
sq_frame_start = self.timeline.GetStartFrame()
sq_markers = self.timeline.GetMarkers()
# create media bin for compound clips (trackItems)
mp_folder = resolve.create_current_sequence_media_bin(self.sequence)
mp_folder = resolve.create_current_sequence_media_bin(self.timeline)
kwargs = {
"ui_inputs": widget.result,

View file

@ -1,263 +0,0 @@
# from pprint import pformat
from pype.hosts import resolve
from pype.hosts.resolve import lib
class CreateShotClip(resolve.Creator):
"""Publishable clip"""
label = "Create Publishable Clip"
family = "clip"
icon = "film"
defaults = ["Main"]
gui_tracks = resolve.get_video_track_names()
gui_name = "Pype publish attributes creator"
gui_info = "Define sequential rename and fill hierarchy data."
gui_inputs = {
"renameHierarchy": {
"type": "section",
"label": "Shot Hierarchy And Rename Settings",
"target": "ui",
"order": 0,
"value": {
"hierarchy": {
"value": "{folder}/{sequence}",
"type": "QLineEdit",
"label": "Shot Parent Hierarchy",
"target": "tag",
"toolTip": "Parents folder for shot root folder, Template filled with `Hierarchy Data` section", # noqa
"order": 0},
"clipRename": {
"value": False,
"type": "QCheckBox",
"label": "Rename clips",
"target": "ui",
"toolTip": "Renaming selected clips on fly", # noqa
"order": 1},
"clipName": {
"value": "{sequence}{shot}",
"type": "QLineEdit",
"label": "Clip Name Template",
"target": "ui",
"toolTip": "template for creating shot namespaused for renaming (use rename: on)", # noqa
"order": 2},
"countFrom": {
"value": 10,
"type": "QSpinBox",
"label": "Count sequence from",
"target": "ui",
"toolTip": "Set when the sequence number stafrom", # noqa
"order": 3},
"countSteps": {
"value": 10,
"type": "QSpinBox",
"label": "Stepping number",
"target": "ui",
"toolTip": "What number is adding every new step", # noqa
"order": 4},
}
},
"hierarchyData": {
"type": "dict",
"label": "Shot Template Keywords",
"target": "tag",
"order": 1,
"value": {
"folder": {
"value": "shots",
"type": "QLineEdit",
"label": "{folder}",
"target": "tag",
"toolTip": "Name of folder used for root of generated shots.\nUsable tokens:\n\t{_clip_}: name of used clip\n\t{_track_}: name of parent track layer\n\t{_sequence_}: name of parent sequence (timeline)", # noqa
"order": 0},
"episode": {
"value": "ep01",
"type": "QLineEdit",
"label": "{episode}",
"target": "tag",
"toolTip": "Name of episode.\nUsable tokens:\n\t{_clip_}: name of used clip\n\t{_track_}: name of parent track layer\n\t{_sequence_}: name of parent sequence (timeline)", # noqa
"order": 1},
"sequence": {
"value": "sq01",
"type": "QLineEdit",
"label": "{sequence}",
"target": "tag",
"toolTip": "Name of sequence of shots.\nUsable tokens:\n\t{_clip_}: name of used clip\n\t{_track_}: name of parent track layer\n\t{_sequence_}: name of parent sequence (timeline)", # noqa
"order": 2},
"track": {
"value": "{_track_}",
"type": "QLineEdit",
"label": "{track}",
"target": "tag",
"toolTip": "Name of sequence of shots.\nUsable tokens:\n\t{_clip_}: name of used clip\n\t{_track_}: name of parent track layer\n\t{_sequence_}: name of parent sequence (timeline)", # noqa
"order": 3},
"shot": {
"value": "sh###",
"type": "QLineEdit",
"label": "{shot}",
"target": "tag",
"toolTip": "Name of shot. `#` is converted to paded number. \nAlso could be used with usable tokens:\n\t{_clip_}: name of used clip\n\t{_track_}: name of parent track layer\n\t{_sequence_}: name of parent sequence (timeline)", # noqa
"order": 4}
}
},
"verticalSync": {
"type": "section",
"label": "Vertical Synchronization Of Attributes",
"target": "ui",
"order": 2,
"value": {
"vSyncOn": {
"value": True,
"type": "QCheckBox",
"label": "Enable Vertical Sync",
"target": "ui",
"toolTip": "Switch on if you want clips above each other to share its attributes", # noqa
"order": 0},
"vSyncTrack": {
"value": gui_tracks, # noqa
"type": "QComboBox",
"label": "Master track",
"target": "ui",
"toolTip": "Select driving track name which should be mastering all others", # noqa
"order": 1}
}
},
"publishSettings": {
"type": "section",
"label": "Publish Settings",
"target": "ui",
"order": 3,
"value": {
"subsetName": {
"value": ["<track_name>", "main", "bg", "fg", "bg",
"animatic"],
"type": "QComboBox",
"label": "Subset Name",
"target": "ui",
"toolTip": "chose subset name patern, if <track_name> is selected, name of track layer will be used", # noqa
"order": 0},
"subsetFamily": {
"value": ["plate", "take"],
"type": "QComboBox",
"label": "Subset Family",
"target": "ui", "toolTip": "What use of this subset is for", # noqa
"order": 1},
"reviewTrack": {
"value": ["< none >"] + gui_tracks,
"type": "QComboBox",
"label": "Use Review Track",
"target": "ui",
"toolTip": "Generate preview videos on fly, if `< none >` is defined nothing will be generated.", # noqa
"order": 2},
"audio": {
"value": False,
"type": "QCheckBox",
"label": "Include audio",
"target": "tag",
"toolTip": "Process subsets with corresponding audio", # noqa
"order": 3},
"sourceResolution": {
"value": False,
"type": "QCheckBox",
"label": "Source resolution",
"target": "tag",
"toolTip": "Is resloution taken from timeline or source?", # noqa
"order": 4},
}
},
"shotAttr": {
"type": "section",
"label": "Shot Attributes",
"target": "ui",
"order": 4,
"value": {
"workfileFrameStart": {
"value": 1001,
"type": "QSpinBox",
"label": "Workfiles Start Frame",
"target": "tag",
"toolTip": "Set workfile starting frame number", # noqa
"order": 0},
"handleStart": {
"value": 0,
"type": "QSpinBox",
"label": "Handle start (head)",
"target": "tag",
"toolTip": "Handle at start of clip", # noqa
"order": 1},
"handleEnd": {
"value": 0,
"type": "QSpinBox",
"label": "Handle end (tail)",
"target": "tag",
"toolTip": "Handle at end of clip", # noqa
"order": 2},
}
}
}
presets = None
def process(self):
# get key pares from presets and match it on ui inputs
for k, v in self.gui_inputs.items():
if v["type"] in ("dict", "section"):
# nested dictionary (only one level allowed
# for sections and dict)
for _k, _v in v["value"].items():
if self.presets.get(_k) is not None:
self.gui_inputs[k][
"value"][_k]["value"] = self.presets[_k]
if self.presets.get(k):
self.gui_inputs[k]["value"] = self.presets[k]
# open widget for plugins inputs
widget = self.widget(self.gui_name, self.gui_info, self.gui_inputs)
widget.exec_()
if len(self.selected) < 1:
return
if not widget.result:
print("Operation aborted")
return
self.rename_add = 0
# get ui output for track name for vertical sync
v_sync_track = widget.result["vSyncTrack"]["value"]
# sort selected trackItems by
sorted_selected_track_items = list()
unsorted_selected_track_items = list()
for track_item_data in self.selected:
if track_item_data["track"]["name"] in v_sync_track:
sorted_selected_track_items.append(track_item_data)
else:
unsorted_selected_track_items.append(track_item_data)
sorted_selected_track_items.extend(unsorted_selected_track_items)
# sequence attrs
sq_frame_start = self.sequence.GetStartFrame()
sq_markers = self.sequence.GetMarkers()
# create media bin for compound clips (trackItems)
mp_folder = resolve.create_current_sequence_media_bin(self.sequence)
kwargs = {
"ui_inputs": widget.result,
"avalon": self.data,
"mp_folder": mp_folder,
"sq_frame_start": sq_frame_start,
"sq_markers": sq_markers
}
for i, track_item_data in enumerate(sorted_selected_track_items):
self.rename_index = i
# convert track item to timeline media pool item
track_item = resolve.PublishClip(
self, track_item_data, **kwargs).convert()
track_item.SetClipColor(lib.publish_clip_color)

View file

@ -22,7 +22,7 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
project = resolve.get_current_project()
fps = project.GetSetting("timelineFrameRate")
active_sequence = resolve.get_current_sequence()
active_timeline = resolve.get_current_timeline()
video_tracks = resolve.get_video_track_names()
# adding otio timeline to context
@ -42,7 +42,6 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
# update context with main project attributes
context_data = {
"activeProject": project,
"activeSequence": active_sequence,
"otioTimeline": otio_timeline,
"videoTracks": video_tracks,
"currentFile": project.GetName(),