From fe9cef1c8fe931324ac880d4bb68a66e431b84d5 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Thu, 22 Aug 2024 23:07:14 +0300 Subject: [PATCH 01/30] Easier settings for ExtractOIIOTranscode --- server/settings/publish_plugins.py | 42 +++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py index 8ca96432f4..cce1891fda 100644 --- a/server/settings/publish_plugins.py +++ b/server/settings/publish_plugins.py @@ -57,7 +57,7 @@ class CollectFramesFixDefModel(BaseSettingsModel): True, title="Show 'Rewrite latest version' toggle" ) - + class ContributionLayersModel(BaseSettingsModel): _layout = "compact" @@ -256,8 +256,8 @@ class ExtractThumbnailModel(BaseSettingsModel): def _extract_oiio_transcoding_type(): return [ - {"value": "colorspace", "label": "Use Colorspace"}, - {"value": "display", "label": "Use Display&View"} + {"value": "use_colorspace", "label": "Use Colorspace"}, + {"value": "use_display_view", "label": "Use Display&View"} ] @@ -266,6 +266,17 @@ class OIIOToolArgumentsModel(BaseSettingsModel): default_factory=list, title="Arguments") +class UseColorspaceModel(BaseSettingsModel): + _layout = "expanded" + colorspace: str = SettingsField("", title="Target Colorspace") + + +class UseDisplayViewModel(BaseSettingsModel): + _layout = "expanded" + display: str = SettingsField("", title="Target Display") + view: str = SettingsField("", title="Target View") + + class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): _layout = "expanded" name: str = SettingsField( @@ -276,13 +287,20 @@ class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): ) extension: str = SettingsField("", title="Extension") transcoding_type: str = SettingsField( - "colorspace", + "use_colorspace", title="Transcoding type", - enum_resolver=_extract_oiio_transcoding_type + enum_resolver=_extract_oiio_transcoding_type, + conditionalEnum=True ) - colorspace: str = SettingsField("", title="Colorspace") - display: str = SettingsField("", title="Display") - view: str = SettingsField("", title="View") + use_colorspace: UseColorspaceModel = SettingsField( + title="Use Colorspace", + default_factory=UseColorspaceModel + ) + use_display_view: UseDisplayViewModel = SettingsField( + title="Use Display&View", + default_factory=UseDisplayViewModel + ) + oiiotool_args: OIIOToolArgumentsModel = SettingsField( default_factory=OIIOToolArgumentsModel, title="OIIOtool arguments") @@ -360,7 +378,7 @@ class ExtractReviewFFmpegModel(BaseSettingsModel): def extract_review_filter_enum(): return [ { - "value": "everytime", + "value": "everytime", # codespell:ignore everytime "label": "Always" }, { @@ -382,7 +400,7 @@ class ExtractReviewFilterModel(BaseSettingsModel): default_factory=list, title="Custom Tags" ) single_frame_filter: str = SettingsField( - "everytime", + "everytime", # codespell:ignore everytime description=( "Use output always / only if input is 1 frame" " image / only if has 2+ frames or is video" @@ -780,7 +798,7 @@ class IntegrateHeroVersionModel(BaseSettingsModel): class CleanUpModel(BaseSettingsModel): _isGroup = True - paterns: list[str] = SettingsField( + paterns: list[str] = SettingsField( # codespell:ignore paterns default_factory=list, title="Patterns (regex)" ) @@ -1200,7 +1218,7 @@ DEFAULT_PUBLISH_VALUES = { "use_hardlinks": False }, "CleanUp": { - "paterns": [], + "paterns": [], # codespell:ignore paterns "remove_temp_renders": False }, "CleanUpFarm": { From 00d7f6c378225b7643450605587bab0724243a3a Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Thu, 22 Aug 2024 23:08:42 +0300 Subject: [PATCH 02/30] adopt to the new settings --- .../plugins/publish/extract_color_transcode.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index a28a761e7e..c5f90e4c99 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -122,12 +122,15 @@ class ExtractOIIOTranscode(publish.Extractor): transcoding_type = output_def["transcoding_type"] target_colorspace = view = display = None - if transcoding_type == "colorspace": - target_colorspace = (output_def["colorspace"] or + # NOTE: we use colorspace_data as the fallback values for the target colorspace. + if transcoding_type == "use_colorspace": + # TODO: Should we fallback to the colorspace (which used as source above) ? + # or should we compute the target colorspace from current view and display ? + target_colorspace = (output_def["use_colorspace"]["colorspace"] or colorspace_data.get("colorspace")) - else: - view = output_def["view"] or colorspace_data.get("view") - display = (output_def["display"] or + elif transcoding_type == "use_display_view": + view = output_def["use_display_view"]["view"] or colorspace_data.get("view") + display = (output_def["use_display_view"]["display"] or colorspace_data.get("display")) # both could be already collected by DCC, @@ -192,7 +195,7 @@ class ExtractOIIOTranscode(publish.Extractor): new_repre["files"] = new_repre["files"][0] # If the source representation has "review" tag, but its not - # part of the output defintion tags, then both the + # part of the output definition tags, then both the # representations will be transcoded in ExtractReview and # their outputs will clash in integration. if "review" in repre.get("tags", []): From d90310079cbd7a81a032be3f3d50f7346805ff76 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 3 Sep 2024 15:13:36 +0300 Subject: [PATCH 03/30] refactor settings names --- .../plugins/publish/extract_color_transcode.py | 15 +++++++++------ server/settings/publish_plugins.py | 18 +++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index c5f90e4c99..77ab6d0428 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -123,15 +123,18 @@ class ExtractOIIOTranscode(publish.Extractor): target_colorspace = view = display = None # NOTE: we use colorspace_data as the fallback values for the target colorspace. - if transcoding_type == "use_colorspace": + if transcoding_type == "colorspace": # TODO: Should we fallback to the colorspace (which used as source above) ? # or should we compute the target colorspace from current view and display ? - target_colorspace = (output_def["use_colorspace"]["colorspace"] or + target_colorspace = (output_def["colorspace"] or colorspace_data.get("colorspace")) - elif transcoding_type == "use_display_view": - view = output_def["use_display_view"]["view"] or colorspace_data.get("view") - display = (output_def["use_display_view"]["display"] or - colorspace_data.get("display")) + elif transcoding_type == "display_view": + display_view = output_def["display_view"] + view = display_view["view"] or colorspace_data.get("view") + display = ( + display_view["display"] + or colorspace_data.get("display") + ) # both could be already collected by DCC, # but could be overwritten when transcoding diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py index cbfab4c5c6..98a50e6101 100644 --- a/server/settings/publish_plugins.py +++ b/server/settings/publish_plugins.py @@ -267,8 +267,8 @@ class ExtractThumbnailModel(BaseSettingsModel): def _extract_oiio_transcoding_type(): return [ - {"value": "use_colorspace", "label": "Use Colorspace"}, - {"value": "use_display_view", "label": "Use Display&View"} + {"value": "colorspace", "label": "Use Colorspace"}, + {"value": "display_view", "label": "Use Display&View"} ] @@ -277,11 +277,6 @@ class OIIOToolArgumentsModel(BaseSettingsModel): default_factory=list, title="Arguments") -class UseColorspaceModel(BaseSettingsModel): - _layout = "expanded" - colorspace: str = SettingsField("", title="Target Colorspace") - - class UseDisplayViewModel(BaseSettingsModel): _layout = "expanded" display: str = SettingsField("", title="Target Display") @@ -298,16 +293,13 @@ class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): ) extension: str = SettingsField("", title="Extension") transcoding_type: str = SettingsField( - "use_colorspace", + "colorspace", title="Transcoding type", enum_resolver=_extract_oiio_transcoding_type, conditionalEnum=True ) - use_colorspace: UseColorspaceModel = SettingsField( - title="Use Colorspace", - default_factory=UseColorspaceModel - ) - use_display_view: UseDisplayViewModel = SettingsField( + colorspace: str = SettingsField("", title="Target Colorspace") + display_view: UseDisplayViewModel = SettingsField( title="Use Display&View", default_factory=UseDisplayViewModel ) From e29ade4e7d36d3f0def6bf4b8c998b3fd3fb446d Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Wed, 11 Sep 2024 11:49:09 +0300 Subject: [PATCH 04/30] Add tool tips for `ExtractOIIOTranscode` settings --- server/settings/publish_plugins.py | 72 ++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py index 98a50e6101..cdcd28a9ce 100644 --- a/server/settings/publish_plugins.py +++ b/server/settings/publish_plugins.py @@ -274,13 +274,30 @@ def _extract_oiio_transcoding_type(): class OIIOToolArgumentsModel(BaseSettingsModel): additional_command_args: list[str] = SettingsField( - default_factory=list, title="Arguments") + default_factory=list, + title="Arguments", + description="Additional command line arguments for *oiiotool*." + ) class UseDisplayViewModel(BaseSettingsModel): _layout = "expanded" - display: str = SettingsField("", title="Target Display") - view: str = SettingsField("", title="Target View") + display: str = SettingsField( + "", + title="Target Display", + description=( + "Display of the target transform. If left empty, the" + " source Display value will be used." + ) + ) + view: str = SettingsField( + "", + title="Target View", + description=( + "View of the target transform. If left empty, the" + " source View value will be used." + ) + ) class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): @@ -291,14 +308,35 @@ class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): description="Output name (no space)", regex=r"[a-zA-Z0-9_]([a-zA-Z0-9_\.\-]*[a-zA-Z0-9_])?$", ) - extension: str = SettingsField("", title="Extension") + extension: str = SettingsField( + "", + title="Extension", + description=( + "Target extension. If left empty, original" + " extension is used." + ), + ) transcoding_type: str = SettingsField( "colorspace", title="Transcoding type", enum_resolver=_extract_oiio_transcoding_type, - conditionalEnum=True + conditionalEnum=True, + description=( + "Select the transcoding type for your output, choosing either " + "*Colorspace* or *Display&View* transform." + " Only one option can be applied per output definition." + ), + ) + colorspace: str = SettingsField( + "", + title="Target Colorspace", + description=( + "Choose the desired target colorspace, confirming its availability" + " in the active OCIO config. If left empty, the" + " source colorspace value will be used, resulting in no" + " colorspace conversion." + ) ) - colorspace: str = SettingsField("", title="Target Colorspace") display_view: UseDisplayViewModel = SettingsField( title="Use Display&View", default_factory=UseDisplayViewModel @@ -308,9 +346,19 @@ class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): default_factory=OIIOToolArgumentsModel, title="OIIOtool arguments") - tags: list[str] = SettingsField(default_factory=list, title="Tags") + tags: list[str] = SettingsField( + default_factory=list, + title="Tags", + description=( + "Additional tags that will be added to the created representation." + "\nAdd *review* tag to create review from the transcoded" + " representation instead of the original." + ) + ) custom_tags: list[str] = SettingsField( - default_factory=list, title="Custom Tags" + default_factory=list, + title="Custom Tags", + description="Additional custom tags that will be added to the created representation." ) @@ -338,7 +386,13 @@ class ExtractOIIOTranscodeProfileModel(BaseSettingsModel): ) delete_original: bool = SettingsField( True, - title="Delete Original Representation" + title="Delete Original Representation", + description=( + "Choose to preserve or remove the original representation.\n" + "Keep in mind that if the transcoded representation includes" + " a `review` tag, it will take precedence over" + " the original for creating reviews." + ), ) outputs: list[ExtractOIIOTranscodeOutputModel] = SettingsField( default_factory=list, From 3c5603c9241560b578b28d4b27ab8eb3da486085 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 16 Sep 2024 23:47:41 +0300 Subject: [PATCH 05/30] fix line lengths --- .../ayon_core/plugins/publish/extract_color_transcode.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index 77ab6d0428..3e54d324e3 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -122,10 +122,13 @@ class ExtractOIIOTranscode(publish.Extractor): transcoding_type = output_def["transcoding_type"] target_colorspace = view = display = None - # NOTE: we use colorspace_data as the fallback values for the target colorspace. + # NOTE: we use colorspace_data as the fallback values for + # the target colorspace. if transcoding_type == "colorspace": - # TODO: Should we fallback to the colorspace (which used as source above) ? - # or should we compute the target colorspace from current view and display ? + # TODO: Should we fallback to the colorspace + # (which used as source above) ? + # or should we compute the target colorspace from + # current view and display ? target_colorspace = (output_def["colorspace"] or colorspace_data.get("colorspace")) elif transcoding_type == "display_view": From 98918b1dd4e4140f93f23de8f16178d43494cd65 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 20 Sep 2024 00:23:28 +0300 Subject: [PATCH 06/30] Add `ExtractOIIOTranscode` settings override --- server/settings/conversion.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/server/settings/conversion.py b/server/settings/conversion.py index f513738603..7eed13bb69 100644 --- a/server/settings/conversion.py +++ b/server/settings/conversion.py @@ -71,10 +71,36 @@ def _convert_validate_version_0_3_3(publish_overrides): validate_version["plugin_state_profiles"] = [profile] +def _convert_oiio_transcode_0_4_5(publish_overrides): + """ExtractOIIOTranscode plugin changed in 0.4.5.""" + if "ExtractOIIOTranscode" not in publish_overrides: + return + + transcode_profiles = publish_overrides["ExtractOIIOTranscode"]["profiles"] + + for profile in transcode_profiles: + for output in profile["outputs"]: + transcode_type = output["transcoding_type"] + if transcode_type == "display": + output["transcoding_type"] = "display_view" + # Already new settings + if "display_view" in output: + continue + + output["display_view"] = {} + if output["display"]: + output["display_view"].update({"display": output["display"]}) + output.pop("display") + if output["view"]: + output["display_view"].update({"view": output["view"]}) + output.pop("view") + + def _conver_publish_plugins(overrides): if "publish" not in overrides: return _convert_validate_version_0_3_3(overrides["publish"]) + _convert_oiio_transcode_0_4_5(overrides["publish"]) def convert_settings_overrides( From 9ea9e344a2e147e1681a291795f3352ea71cb5af Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 20 Sep 2024 12:28:34 +0200 Subject: [PATCH 07/30] Log the filepath it invalidated for clearer log --- client/ayon_core/plugins/publish/integrate.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/integrate.py b/client/ayon_core/plugins/publish/integrate.py index d3f6c04333..e8fe09bab7 100644 --- a/client/ayon_core/plugins/publish/integrate.py +++ b/client/ayon_core/plugins/publish/integrate.py @@ -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 From 451d5e77cd4edeadd5cc18bcf14fdc9d350c3a5c Mon Sep 17 00:00:00 2001 From: Mustafa Jafar Date: Mon, 23 Sep 2024 12:13:23 +0300 Subject: [PATCH 08/30] exit _convert_oiio_transcode_0_4_5 if there are no profiles Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/conversion.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/settings/conversion.py b/server/settings/conversion.py index 7eed13bb69..06a1c2c02b 100644 --- a/server/settings/conversion.py +++ b/server/settings/conversion.py @@ -76,7 +76,9 @@ def _convert_oiio_transcode_0_4_5(publish_overrides): if "ExtractOIIOTranscode" not in publish_overrides: return - transcode_profiles = publish_overrides["ExtractOIIOTranscode"]["profiles"] + transcode_profiles = publish_overrides["ExtractOIIOTranscode"].get("profiles") + if not transcode_profiles: + return for profile in transcode_profiles: for output in profile["outputs"]: From 50428f1528a241176da08092eceeef746e8b4359 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 23 Sep 2024 13:55:09 +0200 Subject: [PATCH 09/30] Fix delivering UDIMs using {udim} in delivery template --- client/ayon_core/lib/path_tools.py | 5 ++++- client/ayon_core/plugins/load/delivery.py | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/lib/path_tools.py b/client/ayon_core/lib/path_tools.py index a65f0f8e13..5c81fbfebf 100644 --- a/client/ayon_core/lib/path_tools.py +++ b/client/ayon_core/lib/path_tools.py @@ -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(?P0*)\\d+)\\.\\D+\\d?$" + patterns = [pattern] collections, remainder = clique.assemble( files, minimum_items=1, patterns=patterns) diff --git a/client/ayon_core/plugins/load/delivery.py b/client/ayon_core/plugins/load/delivery.py index c7954a18b2..449d4f0554 100644 --- a/client/ayon_core/plugins/load/delivery.py +++ b/client/ayon_core/plugins/load/delivery.py @@ -231,6 +231,11 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): self.log ] + # 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"]`. if repre.get("files"): src_paths = [] for repre_file in repre["files"]: @@ -263,7 +268,18 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): frame = dst_frame if frame is not None: - anatomy_data["frame"] = frame + if repre["context"].get("frame"): + anatomy_data["frame"] = frame + 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) From cd5303ef7b09014115f56432337a4b461617d2df Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 23 Sep 2024 14:42:01 +0200 Subject: [PATCH 10/30] Remove legacy code --- client/ayon_core/plugins/load/delivery.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/client/ayon_core/plugins/load/delivery.py b/client/ayon_core/plugins/load/delivery.py index c7954a18b2..60d4c01258 100644 --- a/client/ayon_core/plugins/load/delivery.py +++ b/client/ayon_core/plugins/load/delivery.py @@ -267,17 +267,11 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): 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) - report_items.update(new_report_items) - self._update_progress(uploaded) + else: + raise ValueError( + "Representation entity is lacking `files`." + f" Unable to process entity: {repre}" + ) self.text_area.setText(self._format_report(report_items)) self.text_area.setVisible(True) From b85289080e4289810bdebbca9b87f490ddac19fa Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 23 Sep 2024 15:02:12 +0200 Subject: [PATCH 11/30] Remove unused import --- client/ayon_core/plugins/load/delivery.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/load/delivery.py b/client/ayon_core/plugins/load/delivery.py index 60d4c01258..09c396ff6f 100644 --- a/client/ayon_core/plugins/load/delivery.py +++ b/client/ayon_core/plugins/load/delivery.py @@ -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 ) From ffd548201849c20436f147d109998e8cd1a98dbd Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 23 Sep 2024 15:17:47 +0200 Subject: [PATCH 12/30] Fix not removing absolute path in Maya DL submission This occured only in Maya (or DCC with AOV), caused pasting whole absolute path to metadata.json which could caused `Given file names contain full paths` (if ValidateExpectedFiles was disabled). 'files' is expecting only file names, not full path. --- client/ayon_core/pipeline/farm/pyblish_functions.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index b218dc78e5..af90903bd8 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -788,6 +788,11 @@ def _create_instances_for_aov(instance, skeleton, aov_filter, additional_data, colorspace = product.colorspace break + if isinstance(files, (list, tuple)): + files = [os.path.basename(f) for f in files] + else: + files = os.path.basename(files) + rep = { "name": ext, "ext": ext, From e9b67edc0f16f972c6d0d53f056ff69c03f49653 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 23 Sep 2024 15:37:58 +0200 Subject: [PATCH 13/30] Remove legacy condition completely --- client/ayon_core/plugins/load/delivery.py | 70 +++++++++++------------ 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/client/ayon_core/plugins/load/delivery.py b/client/ayon_core/plugins/load/delivery.py index 09c396ff6f..6a0947cc42 100644 --- a/client/ayon_core/plugins/load/delivery.py +++ b/client/ayon_core/plugins/load/delivery.py @@ -230,47 +230,41 @@ 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) + 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: - anatomy_data["frame"] = frame - new_report_items, uploaded = deliver_single_file(*args) - report_items.update(new_report_items) - self._update_progress(uploaded) - else: - raise ValueError( - "Representation entity is lacking `files`." - f" Unable to process entity: {repre}" - ) + if frame is not None: + anatomy_data["frame"] = frame + new_report_items, uploaded = deliver_single_file(*args) + report_items.update(new_report_items) + self._update_progress(uploaded) self.text_area.setText(self._format_report(report_items)) self.text_area.setVisible(True) From d93c114d14bab45a0406588414999844c5a6c62a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:45:18 +0200 Subject: [PATCH 14/30] Fix querying of loadedVersions It si only in context.data, without it 'reference' links (of loaded containers) won't be created. --- client/ayon_core/plugins/publish/integrate_inputlinks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/integrate_inputlinks.py b/client/ayon_core/plugins/publish/integrate_inputlinks.py index 16aef09a39..113d6144ce 100644 --- a/client/ayon_core/plugins/publish/integrate_inputlinks.py +++ b/client/ayon_core/plugins/publish/integrate_inputlinks.py @@ -97,7 +97,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 From 5189ee77243c7e6f4633f3b7a0e2251b0d88252f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:45:37 +0200 Subject: [PATCH 15/30] Added docstrings --- .../plugins/publish/integrate_inputlinks.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/integrate_inputlinks.py b/client/ayon_core/plugins/publish/integrate_inputlinks.py index 113d6144ce..912420e7b3 100644 --- a/client/ayon_core/plugins/publish/integrate_inputlinks.py +++ b/client/ayon_core/plugins/publish/integrate_inputlinks.py @@ -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 From ebbd65cc6902bde884c120f3219467ad1ff6a24a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:45:54 +0200 Subject: [PATCH 16/30] Refactor imports --- client/ayon_core/tools/loader/models/sitesync.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/tools/loader/models/sitesync.py b/client/ayon_core/tools/loader/models/sitesync.py index 02504c2ad3..753a2e4d5c 100644 --- a/client/ayon_core/tools/loader/models/sitesync.py +++ b/client/ayon_core/tools/loader/models/sitesync.py @@ -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 From 2bd7f814bfbedd8fa300d1f9c2f929a662ba6377 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:47:12 +0200 Subject: [PATCH 17/30] Fix directions of links Currently workfile instance is on 'outside' side of reference link, we must look for 'input' reference links for it --- client/ayon_core/tools/loader/models/sitesync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/loader/models/sitesync.py b/client/ayon_core/tools/loader/models/sitesync.py index 753a2e4d5c..8d29845f5d 100644 --- a/client/ayon_core/tools/loader/models/sitesync.py +++ b/client/ayon_core/tools/loader/models/sitesync.py @@ -578,7 +578,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(): From 2c673ea4c4563822292e77c4414750e141e5b249 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:48:34 +0200 Subject: [PATCH 18/30] Refactor adding site to linked representations Previously it was handled by ugly exception, not it actually checks if representation files are present and if not it forces redownload immediately. --- client/ayon_core/tools/loader/models/sitesync.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/tools/loader/models/sitesync.py b/client/ayon_core/tools/loader/models/sitesync.py index 8d29845f5d..375ef9aa26 100644 --- a/client/ayon_core/tools/loader/models/sitesync.py +++ b/client/ayon_core/tools/loader/models/sitesync.py @@ -512,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, From 7106ff04416c11de216943ba330e45c92c3fe919 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 12:49:19 +0200 Subject: [PATCH 19/30] Refactor remove unneeded check for adding to set --- client/ayon_core/tools/loader/models/sitesync.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/ayon_core/tools/loader/models/sitesync.py b/client/ayon_core/tools/loader/models/sitesync.py index 375ef9aa26..c7f0038df4 100644 --- a/client/ayon_core/tools/loader/models/sitesync.py +++ b/client/ayon_core/tools/loader/models/sitesync.py @@ -588,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) From 7c1602340949fa3576eec1eec49720d5a3e7fcb6 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 24 Sep 2024 14:49:20 +0200 Subject: [PATCH 20/30] Fix docstring type definition Co-authored-by: Roy Nieterau --- client/ayon_core/plugins/publish/integrate_inputlinks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/integrate_inputlinks.py b/client/ayon_core/plugins/publish/integrate_inputlinks.py index 912420e7b3..a3b6a228d6 100644 --- a/client/ayon_core/plugins/publish/integrate_inputlinks.py +++ b/client/ayon_core/plugins/publish/integrate_inputlinks.py @@ -101,7 +101,7 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin): 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 + new_links_by_type (dict[str, list[str]]): dictionary collecting new created links by its type """ if workfile_instance is None: From 166ac0a5f75821e9331c0cdb57169fafc7af38d3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 25 Sep 2024 23:57:12 +0200 Subject: [PATCH 21/30] Add cinema4d to OCIO prelaunch hook --- client/ayon_core/hooks/pre_ocio_hook.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hooks/pre_ocio_hook.py b/client/ayon_core/hooks/pre_ocio_hook.py index 6c30b267bc..7406aa42cf 100644 --- a/client/ayon_core/hooks/pre_ocio_hook.py +++ b/client/ayon_core/hooks/pre_ocio_hook.py @@ -19,7 +19,8 @@ class OCIOEnvHook(PreLaunchHook): "nuke", "hiero", "resolve", - "openrv" + "openrv", + "cinema4d" } launch_types = set() From f9b962d233639067436e21bab54c9f4a5b1a6817 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 26 Sep 2024 00:07:26 +0200 Subject: [PATCH 22/30] Add `cinema4d` to `HOST_WORKFILE_EXTENSIONS` constants --- client/ayon_core/pipeline/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/pipeline/constants.py b/client/ayon_core/pipeline/constants.py index 7a08cbb3aa..88cddc6e1a 100644 --- a/client/ayon_core/pipeline/constants.py +++ b/client/ayon_core/pipeline/constants.py @@ -9,6 +9,7 @@ AVALON_INSTANCE_ID = "pyblish.avalon.instance" HOST_WORKFILE_EXTENSIONS = { "blender": [".blend"], "celaction": [".scn"], + "cinema4d": [".c4d"], "tvpaint": [".tvpp"], "fusion": [".comp"], "harmony": [".zip"], From 85752510f0fe90a91e5f6a1c774264a8b788e64f Mon Sep 17 00:00:00 2001 From: Mustafa Jafar Date: Thu, 26 Sep 2024 11:57:49 +0300 Subject: [PATCH 23/30] optimize `_convert_oiio_transcode_0_4_5` Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/conversion.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/server/settings/conversion.py b/server/settings/conversion.py index 06a1c2c02b..0a345e2059 100644 --- a/server/settings/conversion.py +++ b/server/settings/conversion.py @@ -81,21 +81,25 @@ def _convert_oiio_transcode_0_4_5(publish_overrides): return for profile in transcode_profiles: - for output in profile["outputs"]: - transcode_type = output["transcoding_type"] + outputs = profile.get("outputs") + if outputs is None: + return + + for output in outputs : + # Already new settings + if "display" not in output and "view" not in output: + break + + # Fix 'display' -> 'display_view' in 'transcoding_type' + transcode_type = output.get("transcoding_type") if transcode_type == "display": output["transcoding_type"] = "display_view" - # Already new settings - if "display_view" in output: - continue - - output["display_view"] = {} - if output["display"]: - output["display_view"].update({"display": output["display"]}) - output.pop("display") - if output["view"]: - output["display_view"].update({"view": output["view"]}) - output.pop("view") + + # Convert 'display' and 'view' to new values + output["display_view"] = { + "display": output.pop("display", ""), + "view": output.pop("view", ""), + } def _conver_publish_plugins(overrides): From 6f2e69c3f7f24a0499a430d6f282647a672d4428 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Thu, 26 Sep 2024 12:02:39 +0300 Subject: [PATCH 24/30] fix code linting --- server/settings/conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/conversion.py b/server/settings/conversion.py index 0a345e2059..2337492ef2 100644 --- a/server/settings/conversion.py +++ b/server/settings/conversion.py @@ -94,7 +94,7 @@ def _convert_oiio_transcode_0_4_5(publish_overrides): transcode_type = output.get("transcoding_type") if transcode_type == "display": output["transcoding_type"] = "display_view" - + # Convert 'display' and 'view' to new values output["display_view"] = { "display": output.pop("display", ""), From fa54805d94152b92bcb3c0a7903f2a10528e6409 Mon Sep 17 00:00:00 2001 From: Mustafa Jafar Date: Thu, 26 Sep 2024 12:06:28 +0300 Subject: [PATCH 25/30] enhance a condition in `_convert_oiio_transcode_0_4_5` Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/conversion.py b/server/settings/conversion.py index 2337492ef2..c855863591 100644 --- a/server/settings/conversion.py +++ b/server/settings/conversion.py @@ -87,7 +87,7 @@ def _convert_oiio_transcode_0_4_5(publish_overrides): for output in outputs : # Already new settings - if "display" not in output and "view" not in output: + if "display_view" in output: break # Fix 'display' -> 'display_view' in 'transcoding_type' From ceea08636bb9f951246c408b79fb51dfcd0f4e0e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 26 Sep 2024 17:06:34 +0200 Subject: [PATCH 26/30] Add validate file saved for Cinema4D --- client/ayon_core/plugins/publish/validate_file_saved.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/validate_file_saved.py b/client/ayon_core/plugins/publish/validate_file_saved.py index d132ba8d3a..f52998cef3 100644 --- a/client/ayon_core/plugins/publish/validate_file_saved.py +++ b/client/ayon_core/plugins/publish/validate_file_saved.py @@ -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): From f17529b0510704d29e1ae83c784f553e71060e22 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 27 Sep 2024 13:05:31 +0200 Subject: [PATCH 27/30] Make Publisher UI raised to the front when clicking `AYON > Create...` or `AYON > Publish...` in host integrations if it was already opened. --- client/ayon_core/tools/utils/host_tools.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/ayon_core/tools/utils/host_tools.py b/client/ayon_core/tools/utils/host_tools.py index 1eff746b9e..3cddb69eae 100644 --- a/client/ayon_core/tools/utils/host_tools.py +++ b/client/ayon_core/tools/utils/host_tools.py @@ -252,6 +252,9 @@ class HostToolsHelper: if tab: window.set_current_tab(tab) window.make_sure_is_visible() + window.raise_() + window.activateWindow() + window.showNormal() def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs): """Show tool by it's name. From 28d30bc4ba7d9cbc95e5cde311db963d36645e66 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:11:11 +0200 Subject: [PATCH 28/30] added release trigger action --- .github/workflows/release_trigger.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/release_trigger.yml diff --git a/.github/workflows/release_trigger.yml b/.github/workflows/release_trigger.yml new file mode 100644 index 0000000000..01a3b3a682 --- /dev/null +++ b/.github/workflows/release_trigger.yml @@ -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 }} From 3712152cb7d5d45abad425d97e235b234f93d797 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 30 Sep 2024 16:52:48 +0200 Subject: [PATCH 29/30] removed 'HOST_WORKFILE_EXTENSIONS' --- client/ayon_core/pipeline/__init__.py | 2 -- client/ayon_core/pipeline/constants.py | 18 ------------------ 2 files changed, 20 deletions(-) diff --git a/client/ayon_core/pipeline/__init__.py b/client/ayon_core/pipeline/__init__.py index 4fcea60d5e..8e89029e7b 100644 --- a/client/ayon_core/pipeline/__init__.py +++ b/client/ayon_core/pipeline/__init__.py @@ -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", diff --git a/client/ayon_core/pipeline/constants.py b/client/ayon_core/pipeline/constants.py index 88cddc6e1a..e6156b3138 100644 --- a/client/ayon_core/pipeline/constants.py +++ b/client/ayon_core/pipeline/constants.py @@ -4,21 +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"], - "cinema4d": [".c4d"], - "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"] -} From d667f21625bdd043a3642fad5f36e7f0b6357ec0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 1 Oct 2024 10:15:23 +0200 Subject: [PATCH 30/30] Move logic to `make_sure_is_visible` --- client/ayon_core/tools/publisher/window.py | 5 ++++- client/ayon_core/tools/utils/host_tools.py | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/tools/publisher/window.py b/client/ayon_core/tools/publisher/window.py index a8ca605ecb..434c2ca602 100644 --- a/client/ayon_core/tools/publisher/window.py +++ b/client/ayon_core/tools/publisher/window.py @@ -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) diff --git a/client/ayon_core/tools/utils/host_tools.py b/client/ayon_core/tools/utils/host_tools.py index 3cddb69eae..1eff746b9e 100644 --- a/client/ayon_core/tools/utils/host_tools.py +++ b/client/ayon_core/tools/utils/host_tools.py @@ -252,9 +252,6 @@ class HostToolsHelper: if tab: window.set_current_tab(tab) window.make_sure_is_visible() - window.raise_() - window.activateWindow() - window.showNormal() def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs): """Show tool by it's name.