Merge branch 'develop' into maya_new_publisher

# Conflicts:
#	openpype/hosts/maya/api/lib.py
#	openpype/hosts/maya/api/plugin.py
#	openpype/hosts/maya/plugins/create/create_animation.py
#	openpype/hosts/maya/plugins/create/create_review.py
#	openpype/hosts/maya/plugins/load/load_reference.py
#	openpype/modules/deadline/plugins/publish/submit_maya_deadline.py
This commit is contained in:
Toke Stuart Jepsen 2023-05-16 10:23:11 +01:00
commit 544c043ece
451 changed files with 15825 additions and 3076 deletions

View file

@ -0,0 +1,51 @@
from openpype.pipeline import InventoryAction
from openpype.pipeline import get_current_project_name
from openpype.pipeline.load.plugins import discover_loader_plugins
from openpype.pipeline.load.utils import (
get_loader_identifier,
remove_container,
load_container,
)
from openpype.client import get_representation_by_id
class RemoveAndLoad(InventoryAction):
"""Delete inventory item and reload it."""
label = "Remove and load"
icon = "refresh"
def process(self, containers):
project_name = get_current_project_name()
loaders_by_name = {
get_loader_identifier(plugin): plugin
for plugin in discover_loader_plugins(project_name=project_name)
}
for container in containers:
# Get loader
loader_name = container["loader"]
loader = loaders_by_name.get(loader_name, None)
if not loader:
raise RuntimeError(
"Failed to get loader '{}', can't remove "
"and load container".format(loader_name)
)
# Get representation
representation = get_representation_by_id(
project_name, container["representation"]
)
if not representation:
self.log.warning(
"Skipping remove and load because representation id is not"
" found in database: '{}'".format(
container["representation"]
)
)
continue
# Remove container
remove_container(container)
# Load container
load_container(loader, representation)

View file

@ -50,7 +50,6 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
project_name = context.data["projectName"]
self.fill_missing_asset_docs(context, project_name)
self.fill_instance_data_from_asset(context)
self.fill_latest_versions(context, project_name)
self.fill_anatomy_data(context)
@ -115,23 +114,6 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
"Not found asset documents with names \"{}\"."
).format(joined_asset_names))
def fill_instance_data_from_asset(self, context):
for instance in context:
asset_doc = instance.data.get("assetEntity")
if not asset_doc:
continue
asset_data = asset_doc["data"]
for key in (
"fps",
"frameStart",
"frameEnd",
"handleStart",
"handleEnd",
):
if key not in instance.data and key in asset_data:
instance.data[key] = asset_data[key]
def fill_latest_versions(self, context, project_name):
"""Try to find latest version for each instance's subset.

View file

@ -83,10 +83,11 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
"hierarchy": instance.data["hierarchy"]
})
anatomy_filled = anatomy.format(template_data)
if "folder" in anatomy.templates["publish"]:
publish_folder = anatomy_filled["publish"]["folder"]
publish_templates = anatomy.templates_obj["publish"]
if "folder" in publish_templates:
publish_folder = publish_templates["folder"].format_strict(
template_data
)
else:
# solve deprecated situation when `folder` key is not underneath
# `publish` anatomy
@ -95,8 +96,7 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
" key underneath `publish` (in global of for project `{}`)."
).format(anatomy.project_name))
file_path = anatomy_filled["publish"]["path"]
# Directory
file_path = publish_templates["path"].format_strict(template_data)
publish_folder = os.path.dirname(file_path)
publish_folder = os.path.normpath(publish_folder)

View file

@ -49,7 +49,8 @@ class ExtractBurnin(publish.Extractor):
"webpublisher",
"aftereffects",
"photoshop",
"flame"
"flame",
"houdini"
# "resolve"
]
@ -78,9 +79,10 @@ class ExtractBurnin(publish.Extractor):
self.log.warning("No profiles present for create burnin")
return
# QUESTION what is this for and should we raise an exception?
if "representations" not in instance.data:
raise RuntimeError("Burnin needs already created mov to work on.")
if not instance.data.get("representations"):
self.log.info(
"Instance does not have filled representations. Skipping")
return
self.main_process(instance)

View file

@ -44,6 +44,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
"nuke",
"maya",
"blender",
"houdini",
"shell",
"hiero",
"premiere",

View file

@ -19,9 +19,9 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
order = pyblish.api.ExtractorOrder
families = [
"imagesequence", "render", "render2d", "prerender",
"source", "clip", "take", "online"
"source", "clip", "take", "online", "image"
]
hosts = ["shell", "fusion", "resolve", "traypublisher"]
hosts = ["shell", "fusion", "resolve", "traypublisher", "substancepainter"]
enabled = False
# presetable attribute

View file

@ -163,6 +163,11 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
"Instance is marked to be processed on farm. Skipping")
return
# Instance is marked to not get integrated
if not instance.data.get("integrate", True):
self.log.info("Instance is marked to skip integrating. Skipping")
return
filtered_repres = self.filter_representations(instance)
# Skip instance if there are not representations to integrate
# all representations should not be integrated
@ -665,8 +670,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
# - 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
path_template_obj = anatomy.templates_obj[template_name]["path"]
# Treat template with 'orignalBasename' in special way
if "{originalBasename}" in template:
@ -700,8 +704,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
template_data["originalBasename"], _ = os.path.splitext(
src_file_name)
anatomy_filled = anatomy.format(template_data)
dst = anatomy_filled[template_name]["path"]
dst = path_template_obj.format_strict(template_data)
src = os.path.join(stagingdir, src_file_name)
transfers.append((src, dst))
if repre_context is None:
@ -761,8 +764,9 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
template_data["udim"] = index
else:
template_data["frame"] = index
anatomy_filled = anatomy.format(template_data)
template_filled = anatomy_filled[template_name]["path"]
template_filled = path_template_obj.format_strict(
template_data
)
dst_filepaths.append(template_filled)
if repre_context is None:
self.log.debug(
@ -798,8 +802,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
if is_udim:
template_data["udim"] = repre["udim"][0]
# Construct destination filepath from template
anatomy_filled = anatomy.format(template_data)
template_filled = anatomy_filled[template_name]["path"]
template_filled = path_template_obj.format_strict(template_data)
repre_context = template_filled.used_values
dst = os.path.normpath(template_filled)
@ -810,11 +813,9 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
# todo: Are we sure the assumption each representation
# ends up in the same folder is valid?
if not instance.data.get("publishDir"):
instance.data["publishDir"] = (
anatomy_filled
[template_name]
["folder"]
)
template_obj = anatomy.templates_obj[template_name]["folder"]
template_filled = template_obj.format_strict(template_data)
instance.data["publishDir"] = template_filled
for key in self.db_representation_context_keys:
# Also add these values to the context even if not used by the

View file

@ -291,6 +291,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
))
try:
src_to_dst_file_paths = []
path_template_obj = anatomy.templates_obj[template_key]["path"]
for repre_info in published_repres.values():
# Skip if new repre does not have published repre files
@ -303,9 +304,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
anatomy_data.pop("version", None)
# Get filled path to repre context
anatomy_filled = anatomy.format(anatomy_data)
template_filled = anatomy_filled[template_key]["path"]
template_filled = path_template_obj.format_strict(anatomy_data)
repre_data = {
"path": str(template_filled),
"template": hero_template
@ -343,8 +342,9 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
# Get head and tail for collection
frame_splitter = "_-_FRAME_SPLIT_-_"
anatomy_data["frame"] = frame_splitter
_anatomy_filled = anatomy.format(anatomy_data)
_template_filled = _anatomy_filled[template_key]["path"]
_template_filled = path_template_obj.format_strict(
anatomy_data
)
head, tail = _template_filled.split(frame_splitter)
padding = int(
anatomy.templates[template_key]["frame_padding"]
@ -520,24 +520,24 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
})
if "folder" in anatomy.templates[template_key]:
anatomy_filled = anatomy.format(template_data)
publish_folder = anatomy_filled[template_key]["folder"]
template_obj = anatomy.templates_obj[template_key]["folder"]
publish_folder = template_obj.format_strict(template_data)
else:
# This is for cases of Deprecated anatomy without `folder`
# TODO remove when all clients have solved this issue
template_data.update({
"frame": "FRAME_TEMP",
"representation": "TEMP"
})
anatomy_filled = anatomy.format(template_data)
# solve deprecated situation when `folder` key is not underneath
# `publish` anatomy
self.log.warning((
"Deprecation warning: Anatomy does not have set `folder`"
" key underneath `publish` (in global of for project `{}`)."
).format(anatomy.project_name))
# solve deprecated situation when `folder` key is not underneath
# `publish` anatomy
template_data.update({
"frame": "FRAME_TEMP",
"representation": "TEMP"
})
template_obj = anatomy.templates_obj[template_key]["path"]
file_path = template_obj.format_strict(template_data)
file_path = anatomy_filled[template_key]["path"]
# Directory
publish_folder = os.path.dirname(file_path)

View file

@ -480,8 +480,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
else:
template_data["udim"] = src_padding_exp % i
anatomy_filled = anatomy.format(template_data)
template_filled = anatomy_filled[template_name]["path"]
template_obj = anatomy.templates_obj[template_name]["path"]
template_filled = template_obj.format_strict(template_data)
if repre_context is None:
repre_context = template_filled.used_values
test_dest_files.append(
@ -587,8 +587,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
if repre.get("udim"):
template_data["udim"] = repre["udim"][0]
src = os.path.join(stagingdir, fname)
anatomy_filled = anatomy.format(template_data)
template_filled = anatomy_filled[template_name]["path"]
template_obj = anatomy.templates_obj[template_name]["path"]
template_filled = template_obj.format_strict(template_data)
repre_context = template_filled.used_values
dst = os.path.normpath(template_filled)
@ -600,9 +600,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
if not instance.data.get("publishDir"):
instance.data["publishDir"] = (
anatomy_filled
[template_name]
["folder"]
anatomy.templates_obj[template_name]["folder"]
.format_strict(template_data)
)
if repre.get("udim"):
repre_context["udim"] = repre.get("udim") # store list

View file

@ -271,9 +271,9 @@ class IntegrateThumbnails(pyblish.api.ContextPlugin):
"thumbnail_type": "thumbnail"
})
anatomy_filled = anatomy.format(template_data)
thumbnail_template = anatomy.templates["publish"]["thumbnail"]
template_filled = anatomy_filled["publish"]["thumbnail"]
template_obj = anatomy.templates_obj["publish"]["thumbnail"]
template_filled = template_obj.format_strict(template_data)
thumbnail_template = template_filled.template
dst_full_path = os.path.normpath(str(template_filled))
self.log.debug("Copying file .. {} -> {}".format(

View file

@ -1,34 +0,0 @@
import pyblish.api
class ValidateSequenceFrames(pyblish.api.InstancePlugin):
"""Ensure the sequence of frames is complete
The files found in the folder are checked against the startFrame and
endFrame of the instance. If the first or last file is not
corresponding with the first or last frame it is flagged as invalid.
"""
order = pyblish.api.ValidatorOrder
label = "Validate Sequence Frames"
families = ["imagesequence"]
hosts = ["shell"]
def process(self, instance):
collection = instance[0]
self.log.info(collection)
frames = list(collection.indexes)
current_range = (frames[0], frames[-1])
required_range = (instance.data["frameStart"],
instance.data["frameEnd"])
if current_range != required_range:
raise ValueError("Invalid frame range: {0} - "
"expected: {1}".format(current_range,
required_range))
missing = collection.holes().indexes
assert not missing, "Missing frames: %s" % (missing,)