mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' into enhancement/AY-5552_Publisher-attr-defs-per-instance
This commit is contained in:
commit
7427a0719e
11 changed files with 109 additions and 80 deletions
12
.github/workflows/release_trigger.yml
vendored
Normal file
12
.github/workflows/release_trigger.yml
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
name: 🚀 Release Trigger
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call-release-trigger:
|
||||
uses: ynput/ops-repo-automation/.github/workflows/release_trigger.yml@main
|
||||
secrets:
|
||||
token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
email: ${{ secrets.CI_EMAIL }}
|
||||
user: ${{ secrets.CI_USER }}
|
||||
|
|
@ -19,7 +19,8 @@ class OCIOEnvHook(PreLaunchHook):
|
|||
"nuke",
|
||||
"hiero",
|
||||
"resolve",
|
||||
"openrv"
|
||||
"openrv",
|
||||
"cinema4d"
|
||||
}
|
||||
launch_types = set()
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,10 @@ def collect_frames(files):
|
|||
dict: {'/folder/product_v001.0001.png': '0001', ....}
|
||||
"""
|
||||
|
||||
patterns = [clique.PATTERNS["frames"]]
|
||||
# clique.PATTERNS["frames"] supports only `.1001.exr` not `_1001.exr` so
|
||||
# we use a customized pattern.
|
||||
pattern = "[_.](?P<index>(?P<padding>0*)\\d+)\\.\\D+\\d?$"
|
||||
patterns = [pattern]
|
||||
collections, remainder = clique.assemble(
|
||||
files, minimum_items=1, patterns=patterns)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from .constants import (
|
|||
AVALON_INSTANCE_ID,
|
||||
AYON_CONTAINER_ID,
|
||||
AYON_INSTANCE_ID,
|
||||
HOST_WORKFILE_EXTENSIONS,
|
||||
)
|
||||
|
||||
from .anatomy import Anatomy
|
||||
|
|
@ -114,7 +113,6 @@ __all__ = (
|
|||
"AVALON_INSTANCE_ID",
|
||||
"AYON_CONTAINER_ID",
|
||||
"AYON_INSTANCE_ID",
|
||||
"HOST_WORKFILE_EXTENSIONS",
|
||||
|
||||
# --- Anatomy ---
|
||||
"Anatomy",
|
||||
|
|
|
|||
|
|
@ -4,20 +4,3 @@ AYON_INSTANCE_ID = "ayon.create.instance"
|
|||
# Backwards compatibility
|
||||
AVALON_CONTAINER_ID = "pyblish.avalon.container"
|
||||
AVALON_INSTANCE_ID = "pyblish.avalon.instance"
|
||||
|
||||
# TODO get extensions from host implementations
|
||||
HOST_WORKFILE_EXTENSIONS = {
|
||||
"blender": [".blend"],
|
||||
"celaction": [".scn"],
|
||||
"tvpaint": [".tvpp"],
|
||||
"fusion": [".comp"],
|
||||
"harmony": [".zip"],
|
||||
"houdini": [".hip", ".hiplc", ".hipnc"],
|
||||
"maya": [".ma", ".mb"],
|
||||
"nuke": [".nk"],
|
||||
"hiero": [".hrox"],
|
||||
"photoshop": [".psd", ".psb"],
|
||||
"premiere": [".prproj"],
|
||||
"resolve": [".drp"],
|
||||
"aftereffects": [".aep"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ from ayon_core.pipeline.load import get_representation_path_with_anatomy
|
|||
from ayon_core.pipeline.delivery import (
|
||||
get_format_dict,
|
||||
check_destination_path,
|
||||
deliver_single_file,
|
||||
deliver_sequence,
|
||||
deliver_single_file
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -231,51 +230,55 @@ class DeliveryOptionsDialog(QtWidgets.QDialog):
|
|||
self.log
|
||||
]
|
||||
|
||||
if repre.get("files"):
|
||||
src_paths = []
|
||||
for repre_file in repre["files"]:
|
||||
src_path = self.anatomy.fill_root(repre_file["path"])
|
||||
src_paths.append(src_path)
|
||||
sources_and_frames = collect_frames(src_paths)
|
||||
# TODO: This will currently incorrectly detect 'resources'
|
||||
# that are published along with the publish, because those should
|
||||
# not adhere to the template directly but are ingested in a
|
||||
# customized way. For example, maya look textures or any publish
|
||||
# that directly adds files into `instance.data["transfers"]`
|
||||
src_paths = []
|
||||
for repre_file in repre["files"]:
|
||||
src_path = self.anatomy.fill_root(repre_file["path"])
|
||||
src_paths.append(src_path)
|
||||
sources_and_frames = collect_frames(src_paths)
|
||||
|
||||
frames = set(sources_and_frames.values())
|
||||
frames.discard(None)
|
||||
first_frame = None
|
||||
if frames:
|
||||
first_frame = min(frames)
|
||||
frames = set(sources_and_frames.values())
|
||||
frames.discard(None)
|
||||
first_frame = None
|
||||
if frames:
|
||||
first_frame = min(frames)
|
||||
|
||||
for src_path, frame in sources_and_frames.items():
|
||||
args[0] = src_path
|
||||
# Renumber frames
|
||||
if renumber_frame and frame is not None:
|
||||
# Calculate offset between
|
||||
# first frame and current frame
|
||||
# - '0' for first frame
|
||||
offset = frame_offset - int(first_frame)
|
||||
# Add offset to new frame start
|
||||
dst_frame = int(frame) + offset
|
||||
if dst_frame < 0:
|
||||
msg = "Renumber frame has a smaller number than original frame" # noqa
|
||||
report_items[msg].append(src_path)
|
||||
self.log.warning("{} <{}>".format(
|
||||
msg, dst_frame))
|
||||
continue
|
||||
frame = dst_frame
|
||||
for src_path, frame in sources_and_frames.items():
|
||||
args[0] = src_path
|
||||
# Renumber frames
|
||||
if renumber_frame and frame is not None:
|
||||
# Calculate offset between
|
||||
# first frame and current frame
|
||||
# - '0' for first frame
|
||||
offset = frame_offset - int(first_frame)
|
||||
# Add offset to new frame start
|
||||
dst_frame = int(frame) + offset
|
||||
if dst_frame < 0:
|
||||
msg = "Renumber frame has a smaller number than original frame" # noqa
|
||||
report_items[msg].append(src_path)
|
||||
self.log.warning("{} <{}>".format(
|
||||
msg, dst_frame))
|
||||
continue
|
||||
frame = dst_frame
|
||||
|
||||
if frame is not None:
|
||||
if frame is not None:
|
||||
if repre["context"].get("frame"):
|
||||
anatomy_data["frame"] = frame
|
||||
new_report_items, uploaded = deliver_single_file(*args)
|
||||
report_items.update(new_report_items)
|
||||
self._update_progress(uploaded)
|
||||
else: # fallback for Pype2 and representations without files
|
||||
frame = repre["context"].get("frame")
|
||||
if frame:
|
||||
repre["context"]["frame"] = len(str(frame)) * "#"
|
||||
|
||||
if not frame:
|
||||
new_report_items, uploaded = deliver_single_file(*args)
|
||||
else:
|
||||
new_report_items, uploaded = deliver_sequence(*args)
|
||||
elif repre["context"].get("udim"):
|
||||
anatomy_data["udim"] = frame
|
||||
else:
|
||||
# Fallback
|
||||
self.log.warning(
|
||||
"Representation context has no frame or udim"
|
||||
" data. Supplying sequence frame to '{frame}'"
|
||||
" formatting data."
|
||||
)
|
||||
anatomy_data["frame"] = frame
|
||||
new_report_items, uploaded = deliver_single_file(*args)
|
||||
report_items.update(new_report_items)
|
||||
self._update_progress(uploaded)
|
||||
|
||||
|
|
|
|||
|
|
@ -509,8 +509,11 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
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")
|
||||
for fname in files:
|
||||
if os.path.isabs(fname):
|
||||
raise KnownPublishError(
|
||||
f"Representation file names contains full paths: {fname}"
|
||||
)
|
||||
|
||||
if not is_sequence_representation:
|
||||
return
|
||||
|
|
|
|||
|
|
@ -9,7 +9,14 @@ from ayon_api import (
|
|||
|
||||
|
||||
class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
|
||||
"""Connecting version level dependency links"""
|
||||
"""Connecting version level dependency links
|
||||
|
||||
Handles links:
|
||||
- generative - what gets produced from workfile
|
||||
- reference - what was loaded into workfile
|
||||
|
||||
It expects workfile instance is being published.
|
||||
"""
|
||||
|
||||
order = pyblish.api.IntegratorOrder + 0.2
|
||||
label = "Connect Dependency InputLinks AYON"
|
||||
|
|
@ -47,6 +54,11 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
|
|||
self.create_links_on_server(context, new_links_by_type)
|
||||
|
||||
def split_instances(self, context):
|
||||
"""Separates published instances into workfile and other
|
||||
|
||||
Returns:
|
||||
(tuple(pyblish.plugin.Instance), list(pyblish.plugin.Instance))
|
||||
"""
|
||||
workfile_instance = None
|
||||
other_instances = []
|
||||
|
||||
|
|
@ -83,6 +95,15 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
|
|||
def create_workfile_links(
|
||||
self, workfile_instance, other_instances, new_links_by_type
|
||||
):
|
||||
"""Adds links (generative and reference) for workfile.
|
||||
|
||||
Args:
|
||||
workfile_instance (pyblish.plugin.Instance): published workfile
|
||||
other_instances (list[pyblish.plugin.Instance]): other published
|
||||
instances
|
||||
new_links_by_type (dict[str, list[str]]): dictionary collecting new
|
||||
created links by its type
|
||||
"""
|
||||
if workfile_instance is None:
|
||||
self.log.warn("No workfile in this publish session.")
|
||||
return
|
||||
|
|
@ -97,7 +118,7 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
|
|||
instance.data["versionEntity"]["id"],
|
||||
)
|
||||
|
||||
loaded_versions = workfile_instance.context.get("loadedVersions")
|
||||
loaded_versions = workfile_instance.context.data.get("loadedVersions")
|
||||
if not loaded_versions:
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ class ValidateCurrentSaveFile(pyblish.api.ContextPlugin):
|
|||
|
||||
label = "Validate File Saved"
|
||||
order = pyblish.api.ValidatorOrder - 0.1
|
||||
hosts = ["fusion", "houdini", "max", "maya", "nuke", "substancepainter"]
|
||||
hosts = ["fusion", "houdini", "max", "maya", "nuke", "substancepainter",
|
||||
"cinema4d"]
|
||||
actions = [SaveByVersionUpAction, ShowWorkfilesAction]
|
||||
|
||||
def process(self, context):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import collections
|
||||
|
||||
from ayon_api import get_representations, get_versions_links
|
||||
from ayon_api import (
|
||||
get_representations,
|
||||
get_versions_links,
|
||||
)
|
||||
|
||||
from ayon_core.lib import Logger, NestedCacheItem
|
||||
from ayon_core.addon import AddonsManager
|
||||
|
|
@ -509,18 +512,19 @@ class SiteSyncModel:
|
|||
"reference"
|
||||
)
|
||||
for link_repre_id in links:
|
||||
try:
|
||||
if not self._sitesync_addon.is_representation_on_site(
|
||||
project_name,
|
||||
link_repre_id,
|
||||
site_name
|
||||
):
|
||||
print("Adding {} to linked representation: {}".format(
|
||||
site_name, link_repre_id))
|
||||
self._sitesync_addon.add_site(
|
||||
project_name,
|
||||
link_repre_id,
|
||||
site_name,
|
||||
force=False
|
||||
force=True
|
||||
)
|
||||
except Exception:
|
||||
# do not add/reset working site for references
|
||||
log.debug("Site present", exc_info=True)
|
||||
|
||||
def _get_linked_representation_id(
|
||||
self,
|
||||
|
|
@ -575,7 +579,7 @@ class SiteSyncModel:
|
|||
project_name,
|
||||
versions_to_check,
|
||||
link_types=link_types,
|
||||
link_direction="out")
|
||||
link_direction="in") # looking for 'in'puts for version
|
||||
|
||||
versions_to_check = set()
|
||||
for links in versions_links.values():
|
||||
|
|
@ -584,9 +588,6 @@ class SiteSyncModel:
|
|||
if link["entityType"] != "version":
|
||||
continue
|
||||
entity_id = link["entityId"]
|
||||
# Skip already found linked version ids
|
||||
if entity_id in linked_version_ids:
|
||||
continue
|
||||
linked_version_ids.add(entity_id)
|
||||
versions_to_check.add(entity_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -439,10 +439,13 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
def make_sure_is_visible(self):
|
||||
if self._window_is_visible:
|
||||
self.setWindowState(QtCore.Qt.WindowActive)
|
||||
|
||||
else:
|
||||
self.show()
|
||||
|
||||
self.raise_()
|
||||
self.activateWindow()
|
||||
self.showNormal()
|
||||
|
||||
def showEvent(self, event):
|
||||
self._window_is_visible = True
|
||||
super().showEvent(event)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue