mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Resolve: merge openpype fixes
This commit is contained in:
parent
f74bf468e0
commit
9228508dff
7 changed files with 100 additions and 223 deletions
|
|
@ -12,7 +12,8 @@ from avalon.tools import (
|
|||
creator,
|
||||
loader,
|
||||
sceneinventory,
|
||||
libraryloader
|
||||
libraryloader,
|
||||
subsetmanager
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -59,19 +60,20 @@ class OpenPypeMenu(QtWidgets.QWidget):
|
|||
)
|
||||
|
||||
self.setWindowTitle("OpenPype")
|
||||
workfiles_btn = QtWidgets.QPushButton("Workfiles ...", self)
|
||||
create_btn = QtWidgets.QPushButton("Create ...", self)
|
||||
publish_btn = QtWidgets.QPushButton("Publish ...", self)
|
||||
load_btn = QtWidgets.QPushButton("Load ...", self)
|
||||
inventory_btn = QtWidgets.QPushButton("Inventory ...", self)
|
||||
libload_btn = QtWidgets.QPushButton("Library ...", self)
|
||||
# rename_btn = QtWidgets.QPushButton("Rename ...", self)
|
||||
# set_colorspace_btn = QtWidgets.QPushButton(
|
||||
# "Set colorspace from presets", self
|
||||
# )
|
||||
# reset_resolution_btn = QtWidgets.QPushButton(
|
||||
# "Reset Resolution from peresets", self
|
||||
# )
|
||||
workfiles_btn = QtWidgets.QPushButton("Workfiles", self)
|
||||
create_btn = QtWidgets.QPushButton("Create", self)
|
||||
publish_btn = QtWidgets.QPushButton("Publish", self)
|
||||
load_btn = QtWidgets.QPushButton("Load", self)
|
||||
inventory_btn = QtWidgets.QPushButton("Inventory", self)
|
||||
subsetm_btn = QtWidgets.QPushButton("Subset Manager", self)
|
||||
libload_btn = QtWidgets.QPushButton("Library", self)
|
||||
rename_btn = QtWidgets.QPushButton("Rename", self)
|
||||
set_colorspace_btn = QtWidgets.QPushButton(
|
||||
"Set colorspace from presets", self
|
||||
)
|
||||
reset_resolution_btn = QtWidgets.QPushButton(
|
||||
"Reset Resolution from peresets", self
|
||||
)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.setContentsMargins(10, 20, 10, 20)
|
||||
|
|
@ -81,19 +83,20 @@ class OpenPypeMenu(QtWidgets.QWidget):
|
|||
layout.addWidget(publish_btn)
|
||||
layout.addWidget(load_btn)
|
||||
layout.addWidget(inventory_btn)
|
||||
layout.addWidget(subsetm_btn)
|
||||
|
||||
layout.addWidget(Spacer(15, self))
|
||||
|
||||
layout.addWidget(libload_btn)
|
||||
|
||||
# layout.addWidget(Spacer(15, self))
|
||||
layout.addWidget(Spacer(15, self))
|
||||
|
||||
# layout.addWidget(rename_btn)
|
||||
layout.addWidget(rename_btn)
|
||||
|
||||
# layout.addWidget(Spacer(15, self))
|
||||
layout.addWidget(Spacer(15, self))
|
||||
|
||||
# layout.addWidget(set_colorspace_btn)
|
||||
# layout.addWidget(reset_resolution_btn)
|
||||
layout.addWidget(set_colorspace_btn)
|
||||
layout.addWidget(reset_resolution_btn)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
|
|
@ -102,10 +105,11 @@ class OpenPypeMenu(QtWidgets.QWidget):
|
|||
publish_btn.clicked.connect(self.on_publish_clicked)
|
||||
load_btn.clicked.connect(self.on_load_clicked)
|
||||
inventory_btn.clicked.connect(self.on_inventory_clicked)
|
||||
subsetm_btn.clicked.connect(self.on_subsetm_clicked)
|
||||
libload_btn.clicked.connect(self.on_libload_clicked)
|
||||
# rename_btn.clicked.connect(self.on_rename_clicked)
|
||||
# set_colorspace_btn.clicked.connect(self.on_set_colorspace_clicked)
|
||||
# reset_resolution_btn.clicked.connect(self.on_reset_resolution_clicked)
|
||||
rename_btn.clicked.connect(self.on_rename_clicked)
|
||||
set_colorspace_btn.clicked.connect(self.on_set_colorspace_clicked)
|
||||
reset_resolution_btn.clicked.connect(self.on_reset_resolution_clicked)
|
||||
|
||||
def on_workfile_clicked(self):
|
||||
print("Clicked Workfile")
|
||||
|
|
@ -127,6 +131,10 @@ class OpenPypeMenu(QtWidgets.QWidget):
|
|||
print("Clicked Inventory")
|
||||
sceneinventory.show()
|
||||
|
||||
def on_subsetm_clicked(self):
|
||||
print("Clicked Subset Manager")
|
||||
subsetmanager.show()
|
||||
|
||||
def on_libload_clicked(self):
|
||||
print("Clicked Library")
|
||||
libraryloader.show()
|
||||
|
|
|
|||
|
|
@ -258,3 +258,51 @@ def on_pyblish_instance_toggled(instance, old_value, new_value):
|
|||
# Whether instances should be passthrough based on new value
|
||||
timeline_item = instance.data["item"]
|
||||
set_publish_attribute(timeline_item, new_value)
|
||||
|
||||
|
||||
def remove_instance(instance):
|
||||
"""Remove instance marker from track item."""
|
||||
instance_id = instance.get("uuid")
|
||||
|
||||
selected_timeline_items = lib.get_current_timeline_items(
|
||||
filter=True, selecting_color=lib.publish_clip_color)
|
||||
|
||||
found_ti = None
|
||||
for timeline_item_data in selected_timeline_items:
|
||||
timeline_item = timeline_item_data["clip"]["item"]
|
||||
|
||||
# get openpype tag data
|
||||
tag_data = lib.get_timeline_item_pype_tag(timeline_item)
|
||||
_ti_id = tag_data.get("uuid")
|
||||
if _ti_id == instance_id:
|
||||
found_ti = timeline_item
|
||||
break
|
||||
|
||||
if found_ti is None:
|
||||
return
|
||||
|
||||
# removing instance by marker color
|
||||
print(f"Removing instance: {found_ti.GetName()}")
|
||||
found_ti.DeleteMarkersByColor(lib.pype_marker_color)
|
||||
|
||||
|
||||
def list_instances():
|
||||
"""List all created instances from current workfile."""
|
||||
listed_instances = []
|
||||
selected_timeline_items = lib.get_current_timeline_items(
|
||||
filter=True, selecting_color=lib.publish_clip_color)
|
||||
|
||||
for timeline_item_data in selected_timeline_items:
|
||||
timeline_item = timeline_item_data["clip"]["item"]
|
||||
ti_name = timeline_item.GetName().split(".")[0]
|
||||
|
||||
# get openpype tag data
|
||||
tag_data = lib.get_timeline_item_pype_tag(timeline_item)
|
||||
|
||||
if tag_data:
|
||||
asset = tag_data.get("asset")
|
||||
subset = tag_data.get("subset")
|
||||
tag_data["label"] = f"{ti_name} [{asset}-{subset}]"
|
||||
listed_instances.append(tag_data)
|
||||
|
||||
return listed_instances
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import re
|
||||
import uuid
|
||||
from avalon import api
|
||||
import openpype.api as pype
|
||||
from openpype.hosts import resolve
|
||||
|
|
@ -697,13 +698,13 @@ class PublishClip:
|
|||
Populating the tag data into internal variable self.tag_data
|
||||
"""
|
||||
# define vertical sync attributes
|
||||
master_layer = True
|
||||
hero_track = True
|
||||
self.review_layer = ""
|
||||
if self.vertical_sync:
|
||||
# check if track name is not in driving layer
|
||||
if self.track_name not in self.driving_layer:
|
||||
# if it is not then define vertical sync as None
|
||||
master_layer = False
|
||||
hero_track = False
|
||||
|
||||
# increasing steps by index of rename iteration
|
||||
self.count_steps *= self.rename_index
|
||||
|
|
@ -717,7 +718,7 @@ class PublishClip:
|
|||
self.tag_data[_k] = _v["value"]
|
||||
|
||||
# driving layer is set as positive match
|
||||
if master_layer or self.vertical_sync:
|
||||
if hero_track or self.vertical_sync:
|
||||
# mark review layer
|
||||
if self.review_track and (
|
||||
self.review_track not in self.review_track_default):
|
||||
|
|
@ -751,35 +752,39 @@ class PublishClip:
|
|||
hierarchy_formating_data
|
||||
)
|
||||
|
||||
tag_hierarchy_data.update({"masterLayer": True})
|
||||
if master_layer and self.vertical_sync:
|
||||
# tag_hierarchy_data.update({"masterLayer": True})
|
||||
tag_hierarchy_data.update({"heroTrack": True})
|
||||
if hero_track and self.vertical_sync:
|
||||
self.vertical_clip_match.update({
|
||||
(self.clip_in, self.clip_out): tag_hierarchy_data
|
||||
})
|
||||
|
||||
if not master_layer and self.vertical_sync:
|
||||
if not hero_track and self.vertical_sync:
|
||||
# driving layer is set as negative match
|
||||
for (_in, _out), master_data in self.vertical_clip_match.items():
|
||||
master_data.update({"masterLayer": False})
|
||||
for (_in, _out), hero_data in self.vertical_clip_match.items():
|
||||
hero_data.update({"heroTrack": False})
|
||||
if _in == self.clip_in and _out == self.clip_out:
|
||||
data_subset = master_data["subset"]
|
||||
# add track index in case duplicity of names in master data
|
||||
data_subset = hero_data["subset"]
|
||||
# add track index in case duplicity of names in hero data
|
||||
if self.subset in data_subset:
|
||||
master_data["subset"] = self.subset + str(
|
||||
hero_data["subset"] = self.subset + str(
|
||||
self.track_index)
|
||||
# in case track name and subset name is the same then add
|
||||
if self.subset_name == self.track_name:
|
||||
master_data["subset"] = self.subset
|
||||
hero_data["subset"] = self.subset
|
||||
# assing data to return hierarchy data to tag
|
||||
tag_hierarchy_data = master_data
|
||||
tag_hierarchy_data = hero_data
|
||||
|
||||
# add data to return data dict
|
||||
self.tag_data.update(tag_hierarchy_data)
|
||||
|
||||
if master_layer and self.review_layer:
|
||||
# add uuid to tag data
|
||||
self.tag_data["uuid"] = str(uuid.uuid4())
|
||||
|
||||
# add review track only to hero track
|
||||
if hero_track and self.review_layer:
|
||||
self.tag_data.update({"reviewTrack": self.review_layer})
|
||||
|
||||
|
||||
def _solve_tag_hierarchy_data(self, hierarchy_formating_data):
|
||||
""" Solve tag data from hierarchy data and templates. """
|
||||
# fill up clip name and hierarchy keys
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class CreateShotClip(resolve.Creator):
|
|||
"vSyncTrack": {
|
||||
"value": gui_tracks, # noqa
|
||||
"type": "QComboBox",
|
||||
"label": "Master track",
|
||||
"label": "Hero track",
|
||||
"target": "ui",
|
||||
"toolTip": "Select driving track name which should be mastering all others", # noqa
|
||||
"order": 1}
|
||||
|
|
|
|||
|
|
@ -1,129 +0,0 @@
|
|||
import pyblish
|
||||
from openpype.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.59
|
||||
label = "Collect Instances"
|
||||
hosts = ["resolve"]
|
||||
|
||||
def process(self, context):
|
||||
otio_timeline = context.data["otioTimeline"]
|
||||
selected_timeline_items = resolve.get_current_timeline_items(
|
||||
filter=True, selecting_color=resolve.publish_clip_color)
|
||||
|
||||
self.log.info(
|
||||
"Processing enabled track items: {}".format(
|
||||
len(selected_timeline_items)))
|
||||
|
||||
for timeline_item_data in selected_timeline_items:
|
||||
|
||||
data = dict()
|
||||
timeline_item = timeline_item_data["clip"]["item"]
|
||||
|
||||
# get openpype tag data
|
||||
tag_data = resolve.get_timeline_item_pype_tag(timeline_item)
|
||||
self.log.debug(f"__ tag_data: {pformat(tag_data)}")
|
||||
|
||||
if not tag_data:
|
||||
continue
|
||||
|
||||
if tag_data.get("id") != "pyblish.avalon.instance":
|
||||
continue
|
||||
|
||||
media_pool_item = timeline_item.GetMediaPoolItem()
|
||||
clip_property = media_pool_item.GetClipProperty()
|
||||
self.log.debug(f"clip_property: {clip_property}")
|
||||
|
||||
# add tag data to instance data
|
||||
data.update({
|
||||
k: v for k, v in tag_data.items()
|
||||
if k not in ("id", "applieswhole", "label")
|
||||
})
|
||||
|
||||
asset = tag_data["asset"]
|
||||
subset = tag_data["subset"]
|
||||
|
||||
# insert family into families
|
||||
family = tag_data["family"]
|
||||
families = [str(f) for f in tag_data["families"]]
|
||||
families.insert(0, str(family))
|
||||
|
||||
data.update({
|
||||
"name": "{} {} {}".format(asset, subset, families),
|
||||
"asset": asset,
|
||||
"item": timeline_item,
|
||||
"families": families,
|
||||
"publish": resolve.get_publish_attribute(timeline_item),
|
||||
"fps": context.data["fps"]
|
||||
})
|
||||
|
||||
# otio clip data
|
||||
otio_data = resolve.get_otio_clip_instance_data(
|
||||
otio_timeline, timeline_item_data) or {}
|
||||
data.update(otio_data)
|
||||
|
||||
# add resolution
|
||||
self.get_resolution_to_data(data, context)
|
||||
|
||||
# create instance
|
||||
instance = context.create_instance(**data)
|
||||
|
||||
# create shot instance for shot attributes create/update
|
||||
self.create_shot_instance(context, timeline_item, **data)
|
||||
|
||||
self.log.info("Creating instance: {}".format(instance))
|
||||
self.log.debug(
|
||||
"_ instance.data: {}".format(pformat(instance.data)))
|
||||
|
||||
def get_resolution_to_data(self, data, context):
|
||||
assert data.get("otioClip"), "Missing `otioClip` data"
|
||||
|
||||
# solve source resolution option
|
||||
if data.get("sourceResolution", None):
|
||||
otio_clip_metadata = data[
|
||||
"otioClip"].media_reference.metadata
|
||||
data.update({
|
||||
"resolutionWidth": otio_clip_metadata["width"],
|
||||
"resolutionHeight": otio_clip_metadata["height"],
|
||||
"pixelAspect": otio_clip_metadata["pixelAspect"]
|
||||
})
|
||||
else:
|
||||
otio_tl_metadata = context.data["otioTimeline"].metadata
|
||||
data.update({
|
||||
"resolutionWidth": otio_tl_metadata["width"],
|
||||
"resolutionHeight": otio_tl_metadata["height"],
|
||||
"pixelAspect": otio_tl_metadata["pixelAspect"]
|
||||
})
|
||||
|
||||
def create_shot_instance(self, context, timeline_item, **data):
|
||||
master_layer = data.get("masterLayer")
|
||||
hierarchy_data = data.get("hierarchyData")
|
||||
|
||||
if not master_layer:
|
||||
return
|
||||
|
||||
if not hierarchy_data:
|
||||
return
|
||||
|
||||
asset = data["asset"]
|
||||
subset = "shotMain"
|
||||
|
||||
# insert family into families
|
||||
family = "shot"
|
||||
|
||||
data.update({
|
||||
"name": "{} {} {}".format(asset, subset, family),
|
||||
"subset": subset,
|
||||
"asset": asset,
|
||||
"family": family,
|
||||
"families": [],
|
||||
"publish": resolve.get_publish_attribute(timeline_item)
|
||||
})
|
||||
|
||||
context.create_instance(**data)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
import pyblish.api
|
||||
from openpype.hosts import resolve
|
||||
from avalon import api as avalon
|
||||
from pprint import pformat
|
||||
|
||||
# dev
|
||||
from importlib import reload
|
||||
from openpype.hosts.resolve.otio import davinci_export
|
||||
reload(davinci_export)
|
||||
|
||||
|
||||
class CollectWorkfile(pyblish.api.ContextPlugin):
|
||||
"""Inject the current working file into context"""
|
||||
|
||||
label = "Collect Workfile"
|
||||
order = pyblish.api.CollectorOrder - 0.6
|
||||
|
||||
def process(self, context):
|
||||
|
||||
asset = avalon.Session["AVALON_ASSET"]
|
||||
subset = "workfile"
|
||||
project = resolve.get_current_project()
|
||||
fps = project.GetSetting("timelineFrameRate")
|
||||
|
||||
active_timeline = resolve.get_current_timeline()
|
||||
video_tracks = resolve.get_video_track_names()
|
||||
|
||||
# adding otio timeline to context
|
||||
otio_timeline = davinci_export.create_otio_timeline(project)
|
||||
|
||||
instance_data = {
|
||||
"name": "{}_{}".format(asset, subset),
|
||||
"asset": asset,
|
||||
"subset": "{}{}".format(asset, subset.capitalize()),
|
||||
"item": project,
|
||||
"family": "workfile"
|
||||
}
|
||||
|
||||
# create instance with workfile
|
||||
instance = context.create_instance(**instance_data)
|
||||
|
||||
# update context with main project attributes
|
||||
context_data = {
|
||||
"activeProject": project,
|
||||
"otioTimeline": otio_timeline,
|
||||
"videoTracks": video_tracks,
|
||||
"currentFile": project.GetName(),
|
||||
"fps": fps,
|
||||
}
|
||||
context.data.update(context_data)
|
||||
|
||||
self.log.info("Creating instance: {}".format(instance))
|
||||
self.log.debug("__ instance.data: {}".format(pformat(instance.data)))
|
||||
self.log.debug("__ context_data: {}".format(pformat(context_data)))
|
||||
|
|
@ -58,9 +58,8 @@ def _close_window(event):
|
|||
def _export_button(event):
|
||||
pm = resolve.GetProjectManager()
|
||||
project = pm.GetCurrentProject()
|
||||
fps = project.GetSetting("timelineFrameRate")
|
||||
timeline = project.GetCurrentTimeline()
|
||||
otio_timeline = otio_export.create_otio_timeline(timeline, fps)
|
||||
otio_timeline = otio_export.create_otio_timeline(project)
|
||||
otio_path = os.path.join(
|
||||
itm["exportfilebttn"].Text,
|
||||
timeline.GetName() + ".otio")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue