mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge branch 'develop' into feature/OP-4710_TVP-publishing-update
This commit is contained in:
commit
2c2dd3d92e
6 changed files with 142 additions and 55 deletions
|
|
@ -164,7 +164,6 @@ def get_linked_representation_id(
|
|||
# Recursive graph lookup for inputs
|
||||
{"$graphLookup": graph_lookup}
|
||||
]
|
||||
|
||||
conn = get_project_connection(project_name)
|
||||
result = conn.aggregate(query_pipeline)
|
||||
referenced_version_ids = _process_referenced_pipeline_result(
|
||||
|
|
@ -213,7 +212,7 @@ def _process_referenced_pipeline_result(result, link_type):
|
|||
|
||||
for output in sorted(outputs_recursive, key=lambda o: o["depth"]):
|
||||
output_links = output.get("data", {}).get("inputLinks")
|
||||
if not output_links:
|
||||
if not output_links and output["type"] != "hero_version":
|
||||
continue
|
||||
|
||||
# Leaf
|
||||
|
|
@ -232,6 +231,9 @@ def _process_referenced_pipeline_result(result, link_type):
|
|||
|
||||
|
||||
def _filter_input_links(input_links, link_type, correctly_linked_ids):
|
||||
if not input_links: # to handle hero versions
|
||||
return
|
||||
|
||||
for input_link in input_links:
|
||||
if link_type and input_link["type"] != link_type:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class AppendBlendLoader(plugin.AssetLoader):
|
|||
"""
|
||||
|
||||
representations = ["blend"]
|
||||
families = ["*"]
|
||||
families = ["workfile"]
|
||||
|
||||
label = "Append Workfile"
|
||||
order = 9
|
||||
|
|
@ -68,7 +68,7 @@ class ImportBlendLoader(plugin.AssetLoader):
|
|||
"""
|
||||
|
||||
representations = ["blend"]
|
||||
families = ["*"]
|
||||
families = ["workfile"]
|
||||
|
||||
label = "Import Workfile"
|
||||
order = 9
|
||||
|
|
|
|||
|
|
@ -34,12 +34,24 @@ class AddSyncSite(load.LoaderPlugin):
|
|||
return self._sync_server
|
||||
|
||||
def load(self, context, name=None, namespace=None, data=None):
|
||||
self.log.info("Adding {} to representation: {}".format(
|
||||
data["site_name"], data["_id"]))
|
||||
family = context["representation"]["context"]["family"]
|
||||
project_name = data["project_name"]
|
||||
repre_id = data["_id"]
|
||||
""""Adds site skeleton information on representation_id
|
||||
|
||||
Looks for loaded containers for workfile, adds them site skeleton too
|
||||
(eg. they should be downloaded too).
|
||||
Args:
|
||||
context (dict):
|
||||
name (str):
|
||||
namespace (str):
|
||||
data (dict): expects {"site_name": SITE_NAME_TO_ADD}
|
||||
"""
|
||||
# self.log wont propagate
|
||||
project_name = context["project"]["name"]
|
||||
repre_doc = context["representation"]
|
||||
family = repre_doc["context"]["family"]
|
||||
repre_id = repre_doc["_id"]
|
||||
site_name = data["site_name"]
|
||||
print("Adding {} to representation: {}".format(
|
||||
data["site_name"], repre_id))
|
||||
|
||||
self.sync_server.add_site(project_name, repre_id, site_name,
|
||||
force=True)
|
||||
|
|
@ -52,6 +64,8 @@ class AddSyncSite(load.LoaderPlugin):
|
|||
)
|
||||
for link_repre_id in links:
|
||||
try:
|
||||
print("Adding {} to linked representation: {}".format(
|
||||
data["site_name"], link_repre_id))
|
||||
self.sync_server.add_site(project_name, link_repre_id,
|
||||
site_name,
|
||||
force=False)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ from openpype.pipeline import load
|
|||
|
||||
|
||||
class RemoveSyncSite(load.LoaderPlugin):
|
||||
"""Remove sync site and its files on representation"""
|
||||
"""Remove sync site and its files on representation.
|
||||
|
||||
Removes files only on local site!
|
||||
"""
|
||||
representations = ["*"]
|
||||
families = ["*"]
|
||||
|
||||
|
|
@ -24,13 +27,18 @@ class RemoveSyncSite(load.LoaderPlugin):
|
|||
return self._sync_server
|
||||
|
||||
def load(self, context, name=None, namespace=None, data=None):
|
||||
self.log.info("Removing {} on representation: {}".format(
|
||||
data["site_name"], data["_id"]))
|
||||
self.sync_server.remove_site(data["project_name"],
|
||||
data["_id"],
|
||||
data["site_name"],
|
||||
project_name = context["project"]["name"]
|
||||
repre_doc = context["representation"]
|
||||
repre_id = repre_doc["_id"]
|
||||
site_name = data["site_name"]
|
||||
|
||||
print("Removing {} on representation: {}".format(site_name, repre_id))
|
||||
|
||||
self.sync_server.remove_site(project_name,
|
||||
repre_id,
|
||||
site_name,
|
||||
True)
|
||||
self.log.debug("Site added.")
|
||||
self.log.debug("Site removed.")
|
||||
|
||||
def filepath_from_context(self, context):
|
||||
"""No real file loading"""
|
||||
|
|
|
|||
|
|
@ -506,6 +506,43 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
|
||||
return version_doc
|
||||
|
||||
def _validate_repre_files(self, files, is_sequence_representation):
|
||||
"""Validate representation files before transfer preparation.
|
||||
|
||||
Check if files contain only filenames instead of full paths and check
|
||||
if sequence don't contain more than one sequence or has remainders.
|
||||
|
||||
Args:
|
||||
files (Union[str, List[str]]): Files from representation.
|
||||
is_sequence_representation (bool): Files are for sequence.
|
||||
|
||||
Raises:
|
||||
KnownPublishError: If validations don't pass.
|
||||
"""
|
||||
|
||||
if not files:
|
||||
return
|
||||
|
||||
if not is_sequence_representation:
|
||||
files = [files]
|
||||
|
||||
if any(os.path.isabs(fname) for fname in files):
|
||||
raise KnownPublishError("Given file names contain full paths")
|
||||
|
||||
if not is_sequence_representation:
|
||||
return
|
||||
|
||||
src_collections, remainders = clique.assemble(files)
|
||||
if len(files) < 2 or len(src_collections) != 1 or remainders:
|
||||
raise KnownPublishError((
|
||||
"Files of representation does not contain proper"
|
||||
" sequence files.\nCollected collections: {}"
|
||||
"\nCollected remainders: {}"
|
||||
).format(
|
||||
", ".join([str(col) for col in src_collections]),
|
||||
", ".join([str(rem) for rem in remainders])
|
||||
))
|
||||
|
||||
def prepare_representation(self, repre,
|
||||
template_name,
|
||||
existing_repres_by_name,
|
||||
|
|
@ -587,7 +624,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
is_udim = bool(repre.get("udim"))
|
||||
|
||||
# handle publish in place
|
||||
if "originalDirname" in template:
|
||||
if "{originalDirname}" in template:
|
||||
# store as originalDirname only original value without project root
|
||||
# if instance collected originalDirname is present, it should be
|
||||
# used for all represe
|
||||
|
|
@ -606,24 +643,64 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
template_data["originalDirname"] = without_root
|
||||
|
||||
is_sequence_representation = isinstance(files, (list, tuple))
|
||||
if is_sequence_representation:
|
||||
# Collection of files (sequence)
|
||||
if any(os.path.isabs(fname) for fname in files):
|
||||
raise KnownPublishError("Given file names contain full paths")
|
||||
self._validate_repre_files(files, is_sequence_representation)
|
||||
|
||||
# Output variables of conditions below:
|
||||
# - transfers (List[Tuple[str, str]]): src -> dst filepaths to copy
|
||||
# - repre_context (Dict[str, Any]): context data used to fill template
|
||||
# - template_data (Dict[str, Any]): source data used to fill template
|
||||
# - to add required data to 'repre_context' not used for
|
||||
# formatting
|
||||
# - anatomy_filled (Dict[str, Any]): filled anatomy of last file
|
||||
# - to fill 'publishDir' on instance.data -> not ideal
|
||||
|
||||
# Treat template with 'orignalBasename' in special way
|
||||
if "{originalBasename}" in template:
|
||||
# Remove 'frame' from template data
|
||||
template_data.pop("frame", None)
|
||||
|
||||
# Find out first frame string value
|
||||
first_index_padded = None
|
||||
if not is_udim and is_sequence_representation:
|
||||
col = clique.assemble(files)[0][0]
|
||||
sorted_frames = tuple(sorted(col.indexes))
|
||||
# First frame used for end value
|
||||
first_frame = sorted_frames[0]
|
||||
# Get last frame for padding
|
||||
last_frame = sorted_frames[-1]
|
||||
# Use padding from collection of length of last frame as string
|
||||
padding = max(col.padding, len(str(last_frame)))
|
||||
first_index_padded = get_frame_padded(
|
||||
frame=first_frame,
|
||||
padding=padding
|
||||
)
|
||||
|
||||
# Convert files to list for single file as remaining part is only
|
||||
# transfers creation (iteration over files)
|
||||
if not is_sequence_representation:
|
||||
files = [files]
|
||||
|
||||
repre_context = None
|
||||
transfers = []
|
||||
for src_file_name in files:
|
||||
template_data["originalBasename"], _ = os.path.splitext(
|
||||
src_file_name)
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
dst = anatomy_filled[template_name]["path"]
|
||||
src = os.path.join(stagingdir, src_file_name)
|
||||
transfers.append((src, dst))
|
||||
if repre_context is None:
|
||||
repre_context = dst.used_values
|
||||
|
||||
if not is_udim and first_index_padded is not None:
|
||||
repre_context["frame"] = first_index_padded
|
||||
|
||||
elif is_sequence_representation:
|
||||
# Collection of files (sequence)
|
||||
src_collections, remainders = clique.assemble(files)
|
||||
if len(files) < 2 or len(src_collections) != 1 or remainders:
|
||||
raise KnownPublishError((
|
||||
"Files of representation does not contain proper"
|
||||
" sequence files.\nCollected collections: {}"
|
||||
"\nCollected remainders: {}"
|
||||
).format(
|
||||
", ".join([str(col) for col in src_collections]),
|
||||
", ".join([str(rem) for rem in remainders])
|
||||
))
|
||||
|
||||
src_collection = src_collections[0]
|
||||
template_data["originalBasename"] = src_collection.head[:-1]
|
||||
destination_indexes = list(src_collection.indexes)
|
||||
# Use last frame for minimum padding
|
||||
# - that should cover both 'udim' and 'frame' minimum padding
|
||||
|
|
@ -645,11 +722,8 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
# In case source are published in place we need to
|
||||
# skip renumbering
|
||||
repre_frame_start = repre.get("frameStart")
|
||||
if (
|
||||
"originalBasename" not in template
|
||||
and repre_frame_start is not None
|
||||
):
|
||||
index_frame_start = int(repre["frameStart"])
|
||||
if repre_frame_start is not None:
|
||||
index_frame_start = int(repre_frame_start)
|
||||
# Shift destination sequence to the start frame
|
||||
destination_indexes = [
|
||||
index_frame_start + idx
|
||||
|
|
@ -705,15 +779,6 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
|
||||
else:
|
||||
# Single file
|
||||
fname = files
|
||||
if os.path.isabs(fname):
|
||||
self.log.error(
|
||||
"Filename in representation is filepath {}".format(fname)
|
||||
)
|
||||
raise KnownPublishError(
|
||||
"This is a bug. Representation file name is full path"
|
||||
)
|
||||
template_data["originalBasename"], _ = os.path.splitext(fname)
|
||||
# Manage anatomy template data
|
||||
template_data.pop("frame", None)
|
||||
if is_udim:
|
||||
|
|
@ -725,7 +790,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
dst = os.path.normpath(template_filled)
|
||||
|
||||
# Single file transfer
|
||||
src = os.path.join(stagingdir, fname)
|
||||
src = os.path.join(stagingdir, files)
|
||||
transfers = [(src, dst)]
|
||||
|
||||
# todo: Are we sure the assumption each representation
|
||||
|
|
|
|||
|
|
@ -1480,23 +1480,21 @@ class RepresentationWidget(QtWidgets.QWidget):
|
|||
repre_ids = []
|
||||
data_by_repre_id = {}
|
||||
selected_side = action_representation.get("selected_side")
|
||||
site_name = "{}_site_name".format(selected_side)
|
||||
|
||||
is_sync_loader = tools_lib.is_sync_loader(loader)
|
||||
for item in items:
|
||||
item_id = item.get("_id")
|
||||
repre_ids.append(item_id)
|
||||
repre_id = item["_id"]
|
||||
repre_ids.append(repre_id)
|
||||
if not is_sync_loader:
|
||||
continue
|
||||
|
||||
site_name = "{}_site_name".format(selected_side)
|
||||
data_site_name = item.get(site_name)
|
||||
if not data_site_name:
|
||||
continue
|
||||
|
||||
data_by_repre_id[item_id] = {
|
||||
"_id": item_id,
|
||||
"site_name": data_site_name,
|
||||
"project_name": self.dbcon.active_project()
|
||||
data_by_repre_id[repre_id] = {
|
||||
"site_name": data_site_name
|
||||
}
|
||||
|
||||
repre_contexts = get_repres_contexts(repre_ids, self.dbcon)
|
||||
|
|
@ -1586,8 +1584,8 @@ def _load_representations_by_loader(loader, repre_contexts,
|
|||
version_name = version_doc.get("name")
|
||||
try:
|
||||
if data_by_repre_id:
|
||||
_id = repre_context["representation"]["_id"]
|
||||
data = data_by_repre_id.get(_id)
|
||||
repre_id = repre_context["representation"]["_id"]
|
||||
data = data_by_repre_id.get(repre_id)
|
||||
options.update(data)
|
||||
load_with_repre_context(
|
||||
loader,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue